|
|
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: #include <stdio.h> ! 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: //fprintf(stderr,"task\n"); ! 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: //fprintf(stderr,"this %d name %s mode %d size %d\n",this,name,mode,stacksize); ! 120: switch ((int)thistask) { ! 121: case 0: ! 122: /* initialize task system by creating "main" task */ ! 123: thistask = (task*) 1; ! 124: thistask = new task("main"); ! 125: break; ! 126: case 1: ! 127: /* create "main" task */ ! 128: usemainstack(); /* ensure that store is allocated */ ! 129: t_basep = (int*)OLD_FP(pa_fp); /* fudge, what if main ! 130: is already deeply nested ! 131: */ ! 132: t_team = new team(this); /* don't allocate stack */ ! 133: t_team->no_of_tasks = 2; /* never deallocate */ ! 134: return; ! 135: } ! 136: thistask->th = this; /* return pointer to "child" */ ! 137: thistask->t_framep = de_fp; ! 138: thistask->insert(0,this); ! 139: ! 140: switch (t_mode) { ! 141: case DEDICATED: ! 142: t_team = new team(this,t_stacksize); ! 143: t_basep = t_team->stack + t_stacksize - 1; ! 144: if (_hwm) for (x=0; x<t_stacksize; x++) p[x] = UNTOUCHED; ! 145: thistask = this; ! 146: swap_stack(t_basep,ta_fp,de_fp,pa_fp,de_ap); ! 147: case SHARED: ! 148: thistask->t_mode = SHARED; /* you cannot share on your own */ ! 149: t_basep = pa_fp; ! 150: t_team = thistask->t_team; ! 151: t_team->no_of_tasks++; ! 152: t_framep = ta_fp; ! 153: if (mode==0 && stacksize==0) ! 154: t_stacksize = thistask->t_stacksize - (thistask->t_basep - t_basep); ! 155: thistask = this; ! 156: return; ! 157: default: ! 158: task_error(E_TASKMODE,this); ! 159: } ! 160: } ! 161: ! 162: void task::save() ! 163: /* ! 164: save task's state so that ``restore'' can resume it later ! 165: by returning from the function which called "save" ! 166: - typically the scheduler ! 167: */ ! 168: { ! 169: int* x; ! 170: register* p = (int*)FP(x); ! 171: ! 172: t_framep = (int*)OLD_FP(p); ! 173: ! 174: CHECKTRAP(); ! 175: ! 176: if (t_mode == SHARED) { ! 177: register int sz; ! 178: t_size = sz = t_basep - p + 1; ! 179: p = new int[sz]; ! 180: while (p == 0) task_error(E_STORE,0); ! 181: t_savearea = &p[sz-1]; ! 182: copy_stack(t_basep,sz,t_savearea); ! 183: }; ! 184: } ! 185: ! 186: extern int rr2,rr3,rr4; ! 187: int rr2,rr3,rr4; ! 188: ! 189: swap(task*); ! 190: sswap(task*); ! 191: ! 192: void task::restore() ! 193: /* ! 194: make "this" task run after suspension by returning from the frame ! 195: denoted by "t_framep" ! 196: ! 197: the key function "swap" is written in assembly code, ! 198: it returns from the function which "save"d the task ! 199: - typically the scheduler ! 200: ! 201: "sswap" copies the stack back from the save area before "swap"ing ! 202: arguments to "sswap" are passed in rr2,rr3,rr4 to avoid overwriting them ! 203: it is equivallent to "copystack" followed by "swap". ! 204: */ ! 205: { ! 206: register sz; ! 207: ! 208: SETTRAP(); ! 209: ! 210: if ((t_mode == SHARED) && (sz=t_size)){ ! 211: register* p = t_savearea - sz + 1; ! 212: register x = (this != t_team->got_stack); ! 213: t_team->got_stack = this; ! 214: delete p; ! 215: if (x) { ! 216: rr4 = (int) t_savearea; ! 217: rr3 = sz; ! 218: rr2 = (int) t_basep; ! 219: sswap(this); ! 220: } ! 221: else ! 222: swap(this); ! 223: } ! 224: else ! 225: swap(this); ! 226: } ! 227: ! 228: void task::cancel(int val) ! 229: /* ! 230: TERMINATE and free stack space ! 231: */ ! 232: { ! 233: sched::cancel(val); ! 234: if (_hwm) t_size = curr_hwm(); ! 235: if (t_team->no_of_tasks-- == 1) delete t_team; ! 236: } ! 237: ! 238: task::~task() ! 239: /* ! 240: free stack space and remove task from task chain ! 241: */ ! 242: { ! 243: if (s_state != TERMINATED) task_error(E_TASKDEL,this); ! 244: if (this == task_chain) ! 245: task_chain = t_next; ! 246: else { ! 247: register task* t; ! 248: register task* tt; ! 249: ! 250: for (t=task_chain; tt=t->t_next; t=tt) ! 251: if (tt == this) { ! 252: t->t_next = t_next; ! 253: break; ! 254: } ! 255: } ! 256: ! 257: if (this == thistask) { ! 258: delete (int*) thistask; /* fudge: free(_that) */ ! 259: thistask = 0; ! 260: schedule(); ! 261: } ! 262: } ! 263: ! 264: void task::resultis(int val) ! 265: { ! 266: cancel(val); ! 267: if (this == thistask) schedule(); ! 268: } ! 269: ! 270: void task::sleep() ! 271: { ! 272: if (s_state == RUNNING) remove(); ! 273: if (this == thistask) schedule(); ! 274: } ! 275: ! 276: void task::delay(int d) ! 277: { ! 278: insert(d,this); ! 279: if (thistask == this) schedule(); ! 280: } ! 281: ! 282: int task::preempt() ! 283: { ! 284: if (s_state == RUNNING) { ! 285: remove(); ! 286: return s_time-clock; ! 287: } ! 288: else { ! 289: task_error(E_TASKPRE,this); ! 290: return 0; ! 291: } ! 292: } ! 293: ! 294: char* state_string(int s) ! 295: { ! 296: switch (s) { ! 297: case IDLE: return "IDLE"; ! 298: case TERMINATED: return "TERMINATED"; ! 299: case RUNNING: return "RUNNING"; ! 300: default: return 0; ! 301: } ! 302: } ! 303: ! 304: char* mode_string(int m) ! 305: { ! 306: switch(m) { ! 307: case SHARED: return "SHARED"; ! 308: case DEDICATED: return "DEDICATED"; ! 309: default: return 0; ! 310: } ! 311: } ! 312: ! 313: void task::print(int n) ! 314: /* ! 315: ``n'' values: CHAIN,VERBOSE,STACK ! 316: */ ! 317: { ! 318: char* ss = state_string(s_state); ! 319: char* ns = (t_name) ? t_name : ""; ! 320: ! 321: printf("task %s ",ns); ! 322: if (this == thistask) ! 323: printf("(is thistask):\n"); ! 324: else if (ss) ! 325: printf("(%s):\n",ss); ! 326: else ! 327: printf("(state==%d CORRUPTED):\n",s_state); ! 328: ! 329: if (n&VERBOSE) { ! 330: int res = (s_state==TERMINATED) ? (int) s_time : 0; ! 331: char* ms = mode_string(t_mode); ! 332: if (ms == 0) ms = "CORRUPTED"; ! 333: printf("\tthis==%d mode=%s alert=%d next=%d result=%d\n", ! 334: this,ms,t_alert,t_next,res); ! 335: } ! 336: ! 337: if (n&STACK) { ! 338: printf("\tstack: "); ! 339: if (s_state == TERMINATED) { ! 340: if (_hwm) printf("hwm=%d",t_size); ! 341: printf(" deleted\n"); ! 342: } ! 343: else { ! 344: int b = (int) t_basep; ! 345: int x = ((this==thistask) || t_mode==DEDICATED) ? b-(int)t_framep : t_size; ! 346: printf("max=%d current=%d",t_stacksize,x); ! 347: if (_hwm) printf(" hwm=%d",curr_hwm()); ! 348: printf(" t_base=%d, t_frame=%d, t_size=%d\n",b,t_framep,t_size); ! 349: } ! 350: } ! 351: ! 352: if (n&CHAIN) { ! 353: if (t_next) t_next->print(n); ! 354: } ! 355: } ! 356: ! 357: int task.curr_hwm() ! 358: { ! 359: int* b = t_basep; ! 360: int i; ! 361: for (i=t_stacksize-1; 0<=i && *(b-i)==UNTOUCHED; i--) ; ! 362: return i; ! 363: } ! 364: ! 365: int task.waitlist(object* a) ! 366: { ! 367: return waitvec(&a); ! 368: } ! 369: ! 370: int task.waitvec(object* * v) ! 371: /* ! 372: first determine if it is necessary to sleep(), ! 373: return hint: who caused return ! 374: */ ! 375: { ! 376: int i = 0; ! 377: int r; ! 378: object* ob; ! 379: ! 380: while (ob = v[i++]) { ! 381: t_alert = ob; ! 382: switch (ob->o_type) { ! 383: case TASK: ! 384: case TIMER: ! 385: if (((sched*)ob)->s_state == TERMINATED) goto ex; ! 386: break; ! 387: case QHEAD: ! 388: if (((qhead*)ob)->rdcount()) goto ex; ! 389: break; ! 390: case QTAIL: ! 391: if (((qtail*)ob)->rdspace()) goto ex; ! 392: break; ! 393: } ! 394: ob->remember(this); ! 395: } ! 396: if (i==2 && v[0]==(object*)thistask) task_error(E_WAIT,0); ! 397: sleep(); ! 398: ex: ! 399: i = 0; ! 400: while (ob = v[i++]) { ! 401: ob->forget(this); ! 402: if (ob == t_alert) r = i-1; ! 403: } ! 404: return r; ! 405: } ! 406: ! 407: ! 408:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.