|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.