|
|
1.1 ! root 1: ! 2: #include "task.h" ! 3: ! 4: /* macros giving the addresses of the stack frame pointer ! 5: and the program counter of the caller of the current function ! 6: given the first local variable ! 7: ! 8: TOP points to the top of the current stack frame ! 9: given the last local variable ! 10: */ ! 11: ! 12: #ifdef pdp11 ! 13: ! 14: #define FP() (&_that+4) ! 15: #define OLD_FP(fp) (*fp) ! 16: #define TOP(var9) (&var9) ! 17: ! 18: #endif ! 19: #ifdef vax ! 20: ! 21: #define FP(p) ((int*)(&p+1)) ! 22: #define OLD_AP(fp) (*(fp+2)) ! 23: #define OLD_FP(fp) (*(fp+3)) ! 24: #define TOP(p) top(&p) ! 25: extern int * top(...); ! 26: ! 27: #endif ! 28: ! 29: #define SETTRAP() t_trap = *(t_basep-t_stacksize+1) ! 30: #define CHECKTRAP() if (t_trap != *(t_basep-t_stacksize+1)) task_error(E_STACK,0) ! 31: ! 32: ! 33: int _hwm; ! 34: ! 35: class team ! 36: { ! 37: friend task; ! 38: int no_of_tasks; ! 39: task* got_stack; ! 40: int* stack; ! 41: team(task*, int = 0); ! 42: ~team() { delete stack; } ! 43: }; ! 44: team.team(task* t, int stacksize) { ! 45: no_of_tasks = 1; ! 46: got_stack = t; ! 47: if (stacksize) { ! 48: stack = new int[stacksize]; ! 49: while (stack == 0) task_error(E_STORE,0); ! 50: } ! 51: } ! 52: ! 53: ! 54: void usemainstack() ! 55: /* fudge to allow simple stack overflow check */ ! 56: { ! 57: register v[SIZE+100]; ! 58: ! 59: if (_hwm) ! 60: for (register i=0;i<SIZE+100;i++) v[i] = UNTOUCHED; ! 61: else ! 62: v[0] = 0; ! 63: } ! 64: ! 65: void copy_stack(register* f, register c, register* t) ! 66: /* ! 67: copy c words down from f to t ! 68: do NOT attempt to copy "copy_stack"'s own stackframe ! 69: */ ! 70: { ! 71: while (c--) { *t-- = *f--;} ! 72: } ! 73: ! 74: void task.swap_stack(int* p, int* ta, int* de, int* pa, int* ap) ! 75: { ! 76: int x = pa-TOP(x)+1; /* size of active stack */ ! 77: copy_stack(pa,x,p); ! 78: x = pa-p; /* distance from old stack to new */ ! 79: t_framep = ta-x; /* fp on new frame */ ! 80: /* now doctor the new frame */ ! 81: #ifdef vax ! 82: OLD_AP(t_framep) = int(ap-x); ! 83: #endif ! 84: OLD_FP(t_framep) = int(de-x); ! 85: restore(); ! 86: } ! 87: ! 88: task.task(char* name, int mode, int stacksize) : (TASK) ! 89: /* ! 90: executed in the task creating a new task - thistask. ! 91: 1: put thistask at head of scheduler queue, ! 92: 2: create new task ! 93: 3: transfer execution to new task ! 94: derived::derived can never return - its return link is destroyed ! 95: ! 96: if thistask==0 then we are executing on main()'s stack and ! 97: should turn it into the "main" task ! 98: */ ! 99: { ! 100: int* p; ! 101: int* ta_fp = (int*)FP(p); ! 102: int* de_fp = (int*)OLD_FP(ta_fp); ! 103: #ifdef vax ! 104: int* de_ap = (int*)OLD_AP(ta_fp); ! 105: #endif ! 106: int* pa_fp = (int*)OLD_FP(de_fp); ! 107: int x; ! 108: ! 109: t_name = name; ! 110: t_mode = (mode) ? mode : DEDICATED; ! 111: t_stacksize = (stacksize) ? stacksize : SIZE; ! 112: t_size = 0; /* avoid stack copy at initial restore */ ! 113: t_alert = 0; ! 114: s_state = RUNNING; ! 115: t_next = task_chain; ! 116: task_chain = this; ! 117: th = this; /* fudged return value -- "returned" from swap */ ! 118: ! 119: switch ((int)thistask) { ! 120: case 0: ! 121: /* initialize task system by creating "main" task */ ! 122: thistask = (task*) 1; ! 123: thistask = new task("main"); ! 124: break; ! 125: case 1: ! 126: /* create "main" task */ ! 127: usemainstack(); /* ensure that store is allocated */ ! 128: t_basep = (int*)OLD_FP(pa_fp); /* fudge, what if main ! 129: is already deeply nested ! 130: */ ! 131: t_team = new team(this); /* don't allocate stack */ ! 132: t_team->no_of_tasks = 2; /* never deallocate */ ! 133: return; ! 134: } ! 135: thistask->th = this; /* return pointer to "child" */ ! 136: thistask->t_framep = de_fp; ! 137: thistask->insert(0,this); ! 138: ! 139: switch (t_mode) { ! 140: case DEDICATED: ! 141: t_team = new team(this,t_stacksize); ! 142: t_basep = t_team->stack + t_stacksize - 1; ! 143: if (_hwm) for (x=0; x<t_stacksize; x++) p[x] = UNTOUCHED; ! 144: thistask = this; ! 145: swap_stack(t_basep,ta_fp,de_fp,pa_fp,de_ap); ! 146: case SHARED: ! 147: thistask->t_mode = SHARED; /* you cannot share on your own */ ! 148: t_basep = pa_fp; ! 149: t_team = thistask->t_team; ! 150: t_team->no_of_tasks++; ! 151: t_framep = ta_fp; ! 152: if (mode==0 && stacksize==0) ! 153: t_stacksize = thistask->t_stacksize - (thistask->t_basep - t_basep); ! 154: thistask = this; ! 155: return; ! 156: default: ! 157: task_error(E_TASKMODE,this); ! 158: } ! 159: } ! 160: ! 161: void task.save() ! 162: /* ! 163: save task's state so that ``restore'' can resume it later ! 164: by returning from the function which called "save" ! 165: - typically the scheduler ! 166: */ ! 167: { ! 168: int* x; ! 169: register* p = (int*)FP(x); ! 170: ! 171: t_framep = (int*)OLD_FP(p); ! 172: ! 173: CHECKTRAP(); ! 174: ! 175: if (t_mode == SHARED) { ! 176: register int sz; ! 177: t_size = sz = t_basep - p + 1; ! 178: p = new int[sz]; ! 179: while (p == 0) task_error(E_STORE,0); ! 180: t_savearea = &p[sz-1]; ! 181: copy_stack(t_basep,sz,t_savearea); ! 182: }; ! 183: } ! 184: ! 185: extern int rr2,rr3,rr4; ! 186: int rr2,rr3,rr4; ! 187: ! 188: swap(task*); ! 189: sswap(task*); ! 190: ! 191: void task.restore() ! 192: /* ! 193: make "this" task run after suspension by returning from the frame ! 194: denoted by "t_framep" ! 195: ! 196: the key function "swap" is written in assembly code, ! 197: it returns from the function which "save"d the task ! 198: - typically the scheduler ! 199: ! 200: "sswap" copies the stack back from the save area before "swap"ing ! 201: arguments to "sswap" are passed in rr2,rr3,rr4 to avoid overwriting them ! 202: it is equivallent to "copystack" followed by "swap". ! 203: */ ! 204: { ! 205: register sz; ! 206: ! 207: SETTRAP(); ! 208: ! 209: if ((t_mode == SHARED) && (sz=t_size)){ ! 210: register* p = t_savearea - sz + 1; ! 211: register x = (this != t_team->got_stack); ! 212: t_team->got_stack = this; ! 213: delete p; ! 214: if (x) { ! 215: rr4 = (int) t_savearea; ! 216: rr3 = sz; ! 217: rr2 = (int) t_basep; ! 218: sswap(this); ! 219: } ! 220: else ! 221: swap(this); ! 222: } ! 223: else ! 224: swap(this); ! 225: } ! 226: ! 227: void task.cancel(int val) ! 228: /* ! 229: TERMINATE and free stack space ! 230: */ ! 231: { ! 232: sched::cancel(val); ! 233: if (_hwm) t_size = curr_hwm(); ! 234: if (t_team->no_of_tasks-- == 1) delete t_team; ! 235: } ! 236: ! 237: task.~task() ! 238: /* ! 239: free stack space and remove task from task chain ! 240: */ ! 241: { ! 242: if (s_state != TERMINATED) task_error(E_TASKDEL,this); ! 243: if (this == task_chain) ! 244: task_chain = t_next; ! 245: else { ! 246: register task* t; ! 247: register task* tt; ! 248: ! 249: for (t=task_chain; tt=t->t_next; t=tt) ! 250: if (tt == this) { ! 251: t->t_next = t_next; ! 252: break; ! 253: } ! 254: } ! 255: ! 256: if (this == thistask) { ! 257: delete (int*) thistask; /* fudge: free(_that) */ ! 258: thistask = 0; ! 259: schedule(); ! 260: } ! 261: } ! 262: ! 263: void task.resultis(int val) ! 264: { ! 265: cancel(val); ! 266: if (this == thistask) schedule(); ! 267: } ! 268: ! 269: void task.sleep() ! 270: { ! 271: if (s_state == RUNNING) remove(); ! 272: if (this == thistask) schedule(); ! 273: } ! 274: ! 275: void task.delay(int d) ! 276: { ! 277: insert(d,this); ! 278: if (thistask == this) schedule(); ! 279: } ! 280: ! 281: int task.preempt() ! 282: { ! 283: if (s_state == RUNNING) { ! 284: remove(); ! 285: return s_time-clock; ! 286: } ! 287: else { ! 288: task_error(E_TASKPRE,this); ! 289: return 0; ! 290: } ! 291: } ! 292: ! 293: char* state_string(int s) ! 294: { ! 295: switch (s) { ! 296: case IDLE: return "IDLE"; ! 297: case TERMINATED: return "TERMINATED"; ! 298: case RUNNING: return "RUNNING"; ! 299: default: return 0; ! 300: } ! 301: } ! 302: ! 303: char* mode_string(int m) ! 304: { ! 305: switch(m) { ! 306: case SHARED: return "SHARED"; ! 307: case DEDICATED: return "DEDICATED"; ! 308: default: return 0; ! 309: } ! 310: } ! 311: ! 312: void task.print(int n) ! 313: /* ! 314: ``n'' values: CHAIN,VERBOSE,STACK ! 315: */ ! 316: { ! 317: char* ss = state_string(s_state); ! 318: char* ns = (t_name) ? t_name : ""; ! 319: ! 320: printf("task %s ",ns); ! 321: if (this == thistask) ! 322: printf("(is thistask):\n"); ! 323: else if (ss) ! 324: printf("(%s):\n",ss); ! 325: else ! 326: printf("(state==%d CORRUPTED):\n",s_state); ! 327: ! 328: if (n&VERBOSE) { ! 329: int res = (s_state==TERMINATED) ? (int) s_time : 0; ! 330: char* ms = mode_string(t_mode); ! 331: if (ms == 0) ms = "CORRUPTED"; ! 332: printf("\tthis==%d mode=%s alert=%d next=%d result=%d\n", ! 333: this,ms,t_alert,t_next,res); ! 334: } ! 335: ! 336: if (n&STACK) { ! 337: printf("\tstack: "); ! 338: if (s_state == TERMINATED) { ! 339: if (_hwm) printf("hwm=%d",t_size); ! 340: printf(" deleted\n"); ! 341: } ! 342: else { ! 343: int b = (int) t_basep; ! 344: int x = ((this==thistask) || t_mode==DEDICATED) ? b-(int)t_framep : t_size; ! 345: printf("max=%d current=%d",t_stacksize,x); ! 346: if (_hwm) printf(" hwm=%d",curr_hwm()); ! 347: printf(" t_base=%d, t_frame=%d, t_size=%d\n",b,t_framep,t_size); ! 348: } ! 349: } ! 350: ! 351: if (n&CHAIN) { ! 352: if (t_next) t_next->print(n); ! 353: } ! 354: } ! 355: ! 356: int task.curr_hwm() ! 357: { ! 358: int* b = t_basep; ! 359: int i; ! 360: for (i=t_stacksize-1; 0<=i && *(b-i)==UNTOUCHED; i--) ; ! 361: return i; ! 362: } ! 363: ! 364: int task.waitlist(object* a) ! 365: { ! 366: return waitvec(&a); ! 367: } ! 368: ! 369: int task.waitvec(object* * v) ! 370: /* ! 371: first determine if it is necessary to sleep(), ! 372: return hint: who caused return ! 373: */ ! 374: { ! 375: int i = 0; ! 376: int r; ! 377: object* ob; ! 378: ! 379: while (ob = v[i++]) { ! 380: t_alert = ob; ! 381: switch (ob->o_type) { ! 382: case TASK: ! 383: case TIMER: ! 384: if (((sched*)ob)->s_state == TERMINATED) goto ex; ! 385: break; ! 386: case QHEAD: ! 387: if (((qhead*)ob)->rdcount()) goto ex; ! 388: break; ! 389: case QTAIL: ! 390: if (((qtail*)ob)->rdspace()) goto ex; ! 391: break; ! 392: } ! 393: ob->remember(this); ! 394: } ! 395: if (i==2 && v[0]==(object*)thistask) task_error(E_WAIT,0); ! 396: sleep(); ! 397: ex: ! 398: i = 0; ! 399: while (ob = v[i++]) { ! 400: ob->forget(this); ! 401: if (ob == t_alert) r = i-1; ! 402: } ! 403: return r; ! 404: } ! 405: ! 406: ! 407:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.