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