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