Annotation of researchv8dc/cmd/cfront/libC/task/task.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.