Annotation of researchv10no/cmd/cfront/libC/task/task.h, revision 1.1.1.1

1.1       root        1: /*ident        "%W%" */
                      2: /**************************************************************************
                      3:                        Copyright (c) 1984 AT&T
                      4:                          All Rights Reserved   
                      5: 
                      6:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
                      7:        
                      8:        The copyright notice above does not evidence any        
                      9:        actual or intended publication of such source code.
                     10: 
                     11: *****************************************************************************/
                     12: 
                     13: #ifndef TASKH
                     14: #define TASKH
                     15: 
                     16: /*     HEADER FILE FOR THE TASK SYSTEM         */
                     17: 
                     18: #include <signal.h>
                     19: #include <stdio.h>
                     20: 
                     21: #define SIZE           750
                     22: 
                     23: class object;
                     24: class sched;   /* : public object */
                     25: class timer;   /* : public sched  */
                     26: class task;    /* : public sched  */
                     27: class qhead;   /* : public object */
                     28: class qtail;   /* : public object */
                     29: class team;
                     30: 
                     31: /* o_type() */
                     32: typedef enum { OBJECT, TIMER, TASK, QHEAD, QTAIL } objtype;
                     33: 
                     34: /* sched::s_state */
                     35: typedef enum { IDLE=1, RUNNING=2, TERMINATED=4 } statetype;
                     36: 
                     37: /* type of stack, task::t_mode */
                     38: typedef enum { DEDICATED=1, SHARED=2 } modetype;
                     39: #if defined(_SHARED_ONLY)
                     40: #define        DEFAULT_MODE    SHARED
                     41: #else
                     42: #define        DEFAULT_MODE    DEDICATED
                     43: #endif
                     44: 
                     45: /* loc on stack */
                     46: #define UNTOUCHED      052525
                     47: 
                     48: /* error codes */
                     49: #define task_error_messages                                            \
                     50: macro_start                                                            \
                     51: macro(0,E_ERROR,"")                                                    \
                     52: macro(1,E_OLINK,"object::delete(): has chain")                         \
                     53: macro(2,E_ONEXT,"object::delete(): on chain")                          \
                     54: macro(3,E_GETEMPTY,"qhead::get(): empty")                              \
                     55: macro(4,E_PUTOBJ,"qtail::put(): object on other queue")                        \
                     56: macro(5,E_PUTFULL,"qtail::put(): full")                                        \
                     57: macro(6,E_BACKOBJ,"qhead::putback(): object on other queue")           \
                     58: macro(7,E_BACKFULL,"qhead::putback(): full")                           \
                     59: macro(8,E_SETCLOCK,"sched::setclock(): clock!=0")                      \
                     60: macro(9,E_CLOCKIDLE,"sched::schedule(): clock_task not idle")          \
                     61: macro(10,E_RESTERM,"sched::insert(): cannot schedule terminated sched")        \
                     62: macro(11,E_RESRUN,"sched::schedule(): running")                                \
                     63: macro(12,E_NEGTIME,"sched::schedule(): clock<0")                       \
                     64: macro(13,E_RESOBJ,"sched::schedule(): task or timer on other queue")   \
                     65: macro(14,E_HISTO,"histogram::histogram(): bad arguments")              \
                     66: macro(15,E_STACK,"task::restore() or task::task(): stack overflow")    \
                     67: macro(16,E_STORE,"new: free store exhausted")                          \
                     68: macro(17,E_TASKMODE,"task::task(): bad mode")                          \
                     69: macro(18,E_TASKDEL,"task::~task(): not terminated")                    \
                     70: macro(19,E_TASKPRE,"task::preempt(): not running")                     \
                     71: macro(20,E_TIMERDEL,"timer::~timer(): not terminated")                 \
                     72: macro(21,E_SCHTIME,"sched::schedule(): runchain corrupted: bad time")  \
                     73: macro(22,E_SCHOBJ,"sched object used directly (not as base)")          \
                     74: macro(23,E_QDEL,"queue::~queue(): not empty")                          \
                     75: macro(24,E_RESULT,"task::result(): thistask->result()")                        \
                     76: macro(25,E_WAIT,"task::wait(): wait for self")                         \
                     77: macro(26,E_FUNCS,"FrameLayout::FrameLayout(): function start")         \
                     78: macro(27,E_FRAMES,"FrameLayout::FrameLayout(): frame size")            \
                     79: macro(28,E_REGMASK,"task::fudge_return(): unexpected register mask")   \
                     80: macro(29,E_FUDGE_SIZE,"task::fudge_return(): frame too big")           \
                     81: macro(30,E_NO_HNDLR,"sigFunc - no handler for signal")                 \
                     82: macro(31,E_BADSIG,"illegal signal number")                             \
                     83: macro(32,E_LOSTHNDLR,"Interrupt_handler::~Interrupt_handler(): signal handler not on chain")                   \
                     84: macro_end(E_LOSTHNDLR)
                     85: #define macro_start
                     86: #define macro(num,name,string) const name = num ;
                     87: #define macro_end(last_name) const MAXERR = last_name;
                     88: task_error_messages
                     89: #undef macro_start
                     90: #undef macro
                     91: #undef macro_end
                     92: 
                     93: 
                     94: typedef int (*PFIO)(int,object*);
                     95: typedef void (*PFV)();
                     96: 
                     97: /* print flags, used as arguments to class print functions */
                     98: #define CHAIN          1
                     99: #define VERBOSE                2
                    100: #define STACK          4
                    101: 
                    102: /* DATA STRUCTURES */
                    103: /*
                    104:        object --> olink --> olink ...
                    105:           |         |         |
                    106:          ...        V         V
                    107:           |        task      task
                    108:           V
                    109:        object --> ...
                    110: */
                    111: 
                    112: class olink
                    113: /*     the building block for chains of task pointers */
                    114: {
                    115: friend object;
                    116:        olink*  l_next;
                    117:        task*   l_task;
                    118:                olink(task* t, olink* l) { l_task=t; l_next=l; };
                    119: };
                    120: 
                    121: class object
                    122: {
                    123: friend sched;
                    124: friend task;
                    125:        olink*  o_link;
                    126:        static task*    thxstxsk;
                    127: public:
                    128:        object* o_next;
                    129:        virtual objtype o_type()        { return OBJECT; }
                    130: 
                    131:                object()        { o_link=0; o_next=0; }
                    132:        virtual ~object();
                    133: 
                    134:        void    remember(task* t) {     // save for alert
                    135:                        o_link = new olink(t,o_link);
                    136:                }
                    137:        void    forget(task*);  // remove all occurrences of task from chain
                    138:        void    alert();        // prepare IDLE tasks for scheduling
                    139:        virtual int     pending();  // TRUE if this object should be waited for
                    140:        virtual void    print(int, int =0); // 1st arg VERBOSE, CHAIN, or STACK
                    141:        static int      task_error(int, object*);
                    142:                                // the central error function
                    143:        int     task_error(int);        // obsolete; use static version
                    144:        static task*    this_task()     { return thxstxsk; }
                    145:        static  PFIO    error_fct;      // user-supplied error function
                    146: };
                    147: 
                    148: // fake compatibility with previous version
                    149: #define thistask (object::this_task())
                    150: 
                    151: static void _print_error(int);
                    152: 
                    153: class sched : public object {  // only instances of subclasses are used
                    154: friend timer;
                    155: friend task;
                    156: friend object;
                    157: friend void _print_error(int n);
                    158: friend SIG_FUNC_TYP sigFunc;
                    159:        static int      keep_waiting_count;
                    160:        static sched*   runchain;    // list of ready-to-run scheds (by s_time)
                    161:        static sched*   priority_sched; // if non-zero, sched to run next
                    162:        static  long    clxck;
                    163:        static int      exit_status;
                    164:        long    s_time;         /* time to sched; result after cancel() */
                    165:        statetype       s_state;        /* IDLE, RUNNING, TERMINATED */
                    166:        void    schedule();     /* sched clock_task or front of runchain */
                    167:        virtual void    resume();
                    168:        void    insert(int,object*); /* sched for d time units, t_alert=obj */
                    169:        void    remove();       /* remove from runchain & make IDLE */
                    170: 
                    171: protected:
                    172:                sched() : s_time(0), s_state(IDLE) {}
                    173: public:
                    174: 
                    175:        static void     setclock(long);
                    176:        static long     get_clock() { return clxck; }
                    177:        static sched*   get_run_chain() { return runchain; }
                    178:        static int      get_exit_status() { return exit_status; }
                    179:        static void     set_exit_status( int i ) { exit_status = i; }
                    180:        sched*  get_priority_sched() { return priority_sched; }
                    181:        static  task*   clock_task;     // awoken at each clock tick
                    182:        long    rdtime()        { return s_time; };
                    183:        statetype       rdstate()       { return s_state; };
                    184:        int     pending()       { return s_state != TERMINATED; }
                    185:        int     keep_waiting()  { return keep_waiting_count++; }
                    186:        int     dont_wait()     { return keep_waiting_count--; }
                    187: 
                    188:        void    cancel(int);
                    189:        int     result();
                    190:        virtual void    setwho(object* t);  // who alerted me
                    191:        void    print(int, int =0);
                    192:        static  PFV     exit_fct;       // user-supplied exit function
                    193: };
                    194: // for compatibility with pre-2.0 releases,
                    195: // but conflicts with time.h
                    196: //#define clock (sched::get_clock())
                    197: inline void    setclock(long i) { sched::setclock(i); }
                    198: 
                    199: // for compatibility with pre-2.0 releases
                    200: #define run_chain (sched::get_run_chain())
                    201: 
                    202: class timer : public sched {
                    203:        void    resume();
                    204: public:
                    205:                timer(int);
                    206:                ~timer();
                    207:        void    reset(int);
                    208:        objtype o_type()        { return TIMER; }
                    209:        void    setwho(object* t)       { }  // do nothing
                    210:        void    print(int, int =0);
                    211: };
                    212: 
                    213: extern _hwm;
                    214: class task : public sched {
                    215: friend sched;
                    216:        static task*    txsk_chxin;   /* list of all tasks */
                    217:        static team*    team_to_delete; // delete this team after task switch
                    218:        void    restore(task*, int =0); /* switch to new task */
                    219:        int     curr_hwm();     /* "high water mark" */
                    220:                                /*     (how high stack has risen) */
                    221:        int     swap_stack(int*,int*); /* initialize child stack */
                    222:        void    fudge_return(int*);     //used in starting new tasks
                    223:        void    copy_share();   // used in starting shared tasks
                    224:        void    get_size();     // ditto -- saves size of active stack
                    225:        void    resume();
                    226:        /* simple check for stack overflow--not used for main task */
                    227:        void    settrap();
                    228:        void    checktrap();
                    229:        /* WARNING: t_framep, th, and t_ap are manipulated as offsets from
                    230:         * task by swap(); those, and t_basep, t_size, and t_savearea are
                    231:         * manipulated as offsets by sswap().
                    232:         * Do not insert new data members before these.
                    233:         */
                    234:        int*    t_framep;       // fp for this task when suspended
                    235:        void*   th;             /* fudge return from swap */
                    236:        int*    t_ap;           /* arg pointer for this task when suspended */
                    237:        int*    t_basep;        // addr of stack when running 
                    238:        int     t_size;         /* size of active stack (used for SHARED)
                    239:                                 * holds hwm after cancel() */
                    240:        int*    t_savearea;     // addr of stack when not running (SHARED only)
                    241:        int     t_trap;         // used for stack overflow check
                    242:        team*   t_team;         /* stack and info for sharing */
                    243: 
                    244:        modetype        t_mode;         /* DEDICATED/SHARED stack */
                    245:        int     t_stacksize;
                    246: 
                    247:        object* t_alert;        /* object that inserted you */
                    248: protected:
                    249:                task(char* name=0, modetype mode=DEFAULT_MODE, int stacksize=SIZE);
                    250: public:
                    251:                ~task();
                    252: 
                    253:        objtype o_type()        { return TASK; }
                    254:        task*   t_next;         /* insertion in "task_chain" */
                    255:        char*   t_name;
                    256: 
                    257:        static task*    get_task_chain() { return txsk_chxin; }
                    258:        int     waitvec(object**);
                    259:        int     waitlist(object* ...);
                    260:        void    wait(object* ob);
                    261: 
                    262:        void    delay(int);
                    263:        int     preempt();
                    264:        void    sleep(object* t =0);    // t is remembered
                    265:        void    resultis(int);
                    266:        void    cancel(int);
                    267:        void    setwho(object* t)       { t_alert = t; }
                    268:        void    print(int, int =0);
                    269:        object* who_alerted_me()        { return t_alert; }
                    270: };
                    271: // for compatibility
                    272: #define task_chain (task::get_task_chain())
                    273: 
                    274: // an Interrupt_handler supplies an interrupt routine that runs when the
                    275: // interrupt occurs (real time).  Also the Interrupt_handler can be waited for.
                    276: class Interrupt_handler : public object {
                    277: friend class Interrupt_alerter;
                    278: friend SIG_FUNC_TYP sigFunc;
                    279:        int     id;             // signal or interrupt number
                    280:        int     got_interrupt;  // an interrupt has been received
                    281:                                // but not alerted
                    282:        Interrupt_handler       *old;   // previous handler for this signal
                    283:        virtual void    interrupt();    // runs at real time
                    284: public:
                    285:        int     pending();      // FALSE once after interrupt
                    286:                Interrupt_handler(int sig_num);
                    287:                ~Interrupt_handler();
                    288: };
                    289: 
                    290: 
                    291: /* QUEUE MANIPULATION (see queue.c) */
                    292: /*
                    293:        qhead <--> oqueue <--> qtail   (qhead, qtail independent)
                    294:        oqueue ->> circular queue of objects
                    295: */
                    296: 
                    297: /* qh_modes */
                    298: typedef enum { EMODE, WMODE, ZMODE } qmodetype;
                    299: 
                    300: class oqueue
                    301: {
                    302: friend qhead;
                    303: friend qtail;
                    304:        int     q_max;
                    305:        int     q_count;
                    306:        object* q_ptr;
                    307:        qhead*  q_head;
                    308:        qtail*  q_tail;
                    309: 
                    310:                oqueue(int m)   { q_max=m; q_count=0; q_head=0; q_tail=0; };
                    311:                ~oqueue()       { (q_count)?object::task_error(E_QDEL,0):0; };
                    312: 
                    313:        void    print(int);
                    314: };
                    315: 
                    316: class qhead : public object
                    317: {
                    318: friend qtail;
                    319:        qmodetype       qh_mode;        /* EMODE,WMODE,ZMODE */
                    320:        oqueue*         qh_queue;
                    321: public:
                    322:                        qhead(qmodetype = WMODE, int = 10000);
                    323:                        ~qhead();
                    324: 
                    325:        objtype         o_type()        { return QHEAD; }
                    326:        object*         get();
                    327:        int             putback(object*);
                    328: 
                    329:        int             rdcount()       { return qh_queue->q_count; }
                    330:        int             rdmax()         { return qh_queue->q_max; }
                    331:        qmodetype       rdmode()        { return qh_mode; }
                    332:        qtail*          tail();
                    333: 
                    334:        qhead*          cut();
                    335:        void            splice(qtail*);
                    336: 
                    337:        void            setmode(qmodetype m)    { qh_mode = m; };
                    338:        void            setmax(int m)   { qh_queue->q_max = m; };
                    339:        int             pending()       { return rdcount() == 0; }
                    340:        void            print(int, int =0);
                    341: };
                    342: 
                    343: class qtail : public object
                    344: {
                    345: friend qhead;
                    346:        qmodetype       qt_mode;
                    347:        oqueue*         qt_queue;
                    348: public:
                    349:                        qtail(qmodetype = WMODE, int = 10000);
                    350:                        ~qtail();
                    351: 
                    352:        objtype         o_type()        { return QTAIL; }
                    353:        int             put(object*);
                    354: 
                    355:        int             rdspace()       
                    356:                        { return qt_queue->q_max - qt_queue->q_count; };
                    357:        int             rdmax()         { return qt_queue->q_max; };
                    358:        qmodetype       rdmode()        { return qt_mode; };
                    359: 
                    360:        qtail*          cut();
                    361:        void            splice(qhead*);
                    362: 
                    363:        qhead*          head();
                    364: 
                    365:        void            setmode(qmodetype m)    { qt_mode = m; };
                    366:        void            setmax(int m)   { qt_queue->q_max = m; };
                    367:        int             pending()       { return rdspace() == 0; }
                    368: 
                    369:        void            print(int, int =0);
                    370: };
                    371: 
                    372: 
                    373: struct histogram
                    374: /*
                    375:        "nbin" bins covering the range [l:r] uniformly
                    376:        nbin*binsize == r-l
                    377: */
                    378: {
                    379:        int     l, r;
                    380:        int     binsize;
                    381:        int     nbin;
                    382:        int*    h;
                    383:        long    sum;
                    384:        long    sqsum;
                    385:                histogram(int=16, int=0, int=16);
                    386: 
                    387:        void    add(int);
                    388:        void    print();
                    389: };
                    390: 
                    391: /*     the result of randint() is always >= 0  */
                    392: 
                    393: #define DRAW (randx = randx*1103515245 + 12345)
                    394: #define ABS(x) (x&0x7fffffff)
                    395: #define MASK(x) ABS(x)
                    396: 
                    397: class randint
                    398: /*     uniform distribution in the interval [0,MAXINT_AS_FLOAT] */
                    399: {
                    400:        long    randx;
                    401: public:
                    402:                randint(long s = 0)     { randx=s; }
                    403:        void    seed(long s)    { randx=s; }
                    404:        int     draw()          { return MASK(DRAW); }
                    405:        float   fdraw();
                    406: };
                    407: 
                    408: class urand : public randint
                    409: /*     uniform distribution in the interval [low,high] */
                    410: {
                    411: public:
                    412:        int     low, high;
                    413:                urand(int l, int h)     { low=l; high=h; }
                    414:        int     draw();
                    415: };
                    416: 
                    417: class erand : public randint
                    418: /*     exponential distribution random number generator */
                    419: {
                    420: public:
                    421:        int     mean;
                    422:                erand(int m) { mean=m; };
                    423:        int     draw();
                    424: };
                    425: 
                    426: // This task will alert Interrupt_handler objects.
                    427: class Interrupt_alerter : public task {
                    428: public:
                    429:                Interrupt_alerter();
                    430: };
                    431: 
                    432: extern Interrupt_alerter       interrupt_alerter;
                    433: 
                    434: #endif

unix.superglobalmegacorp.com

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