|
|
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.