Annotation of researchv9/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: #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: 

unix.superglobalmegacorp.com

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