|
|
1.1 root 1: #include "task.h"
2:
3: void setclock(long t)
4: {
5: if (clock) task_error(E_SETCLOCK,0);
6: clock = t;
7: }
8:
9: int in_error = 0;
10:
11: int task_error(int n, object* oo)
12: {
13: if (in_error)
14: exit(in_error);
15: else
16: in_error = n;
17:
18: if (error_fct) {
19: n = (*error_fct)(n,oo);
20: if (n) exit(n);
21: }
22: else {
23: print_error(n);
24: exit(n);
25: }
26: in_error = 0;
27: return 0;
28: }
29:
30: char* error_name[] = {
31: "",
32: "object.delete(): has chain",
33: "object.delete(): on chain",
34: "qhead.get(): empty",
35: "qhead.putback(): object on other queue",
36: "qhead.putback(): full",
37: "qtail.put(): object on other queue",
38: "qtail.put(): full",
39: "set_clock(): clock!=0",
40: "schedule(): clock_task not idle",
41: "schedule: terminated",
42: "schedule: running",
43: "schedule: clock<0",
44: "schedule: task or timer on other queue",
45: "histogram.new(): bad arguments",
46: "task.save(): stack overflow",
47: "new: free store exhausted",
48: "task.new(): bad mode",
49: "task.delete(): not terminated",
50: "task.preempt(): not running",
51: "timer.delete(): not terminated",
52: "schedule: bad time",
53: "schedule: bad object",
54: "queue.delete(): not empty",
55: "thistask->result()",
56: "task.wait(thistask)",
57: };
58:
59: void print_error(int n)
60: {
61:
62: register i = (n<1 || MAXERR<n) ? 0 : n;
63:
64: printf("\n\n***** task_error(%d) %s\n",n,error_name[i]);
65:
66: if (thistask) {
67: printf("thistask: ");
68: thistask->print(VERBOSE|STACK);
69: }
70: if (run_chain) {
71: printf("run_chain:\n");
72: run_chain->print(CHAIN);
73: }
74: } /* task_error */
75:
76: sched* run_chain = 0;
77: task* task_chain = 0;
78: long clock = 0;
79: task* thistask = 0;
80: task* clock_task = 0;
81: PFIO error_fct = 0;
82: /*PFIO sched_fct = 0;*/
83: PFV exit_fct = 0;
84:
85: void sched.cancel(int res)
86: {
87: if (s_state==RUNNING) remove();
88: s_state = TERMINATED;
89: s_time = res;
90: alert();
91: }
92:
93: int sched.result()
94: /* wait for termination and retrieve result */
95: {
96: if (this == (sched*)thistask) task_error(E_RESULT,0);
97: while (s_state != TERMINATED) {
98: remember(thistask);
99: thistask->sleep();
100: forget(thistask);
101: }
102:
103: return (int) s_time;
104: }
105:
106: void sched.schedule()
107: /* schedule either clock_task or front of run_chain */
108: {
109: register sched* p;
110: register long tt;
111:
112: lll:
113: if (p = run_chain) {
114: run_chain = (sched*) p->o_next;
115: p->o_next = 0;
116: }
117: else {
118: if (exit_fct) (*exit_fct)();
119: exit(0);
120: }
121:
122: tt = p->s_time;
123: if (tt != clock) {
124: if (tt < clock) task_error(E_SCHTIME,this);
125: clock = tt;
126: if (clock_task) {
127: if (clock_task->s_state != IDLE)
128: task_error(E_CLOCKIDLE,this);
129: /* clock_task preferred */
130: p->o_next = (object*) run_chain;
131: run_chain = p;
132: p = (sched*) clock_task;
133: }
134: }
135:
136: switch (p->o_type) {
137: case TIMER: /* time is up; "delete" timer & schedule next task */
138: p->s_state = TERMINATED;
139: p->alert();
140: goto lll;
141: case TASK:
142: if (p != this) {
143: if (thistask && thistask->s_state != TERMINATED)
144: thistask->save();
145: thistask = (task*) p;
146: thistask->restore();
147: }
148: break;
149: default:
150: task_error(E_SCHOBJ,this);
151: }
152: } /* schedule */
153:
154: void sched.insert(int d, object* who)
155: /*
156: schedule THIS to run in ``d'' time units
157: inserted by who
158: */
159: {
160: register sched * p;
161: register sched * pp;
162: register long tt = s_time = clock + d;
163:
164: switch (s_state) {
165: case TERMINATED:
166: task_error(E_RESTERM,this);
167: break;
168: case IDLE:
169: break;
170: case RUNNING:
171: if (this != (class sched *)thistask) task_error(E_RESRUN,this);
172: }
173:
174: if (d<0) task_error(E_NEGTIME,this);
175:
176: if (o_next) task_error(E_RESOBJ,this);
177:
178: s_state = RUNNING;
179: if (o_type == TASK) ((task *) this)->t_alert = who;
180:
181: /* run_chain ordered by s_time */
182: if (p = run_chain) {
183: if (tt < p->s_time) {
184: o_next = (object*) run_chain;
185: run_chain = this;
186: }
187: else {
188: while (pp = (sched *) p->o_next) {
189: if (tt < pp->s_time) {
190: o_next = pp;
191: p->o_next = this;
192: return;
193: }
194: else p = pp;
195: }
196: p->o_next = this;
197: }
198: }
199: else
200: run_chain = this;
201: }
202:
203: void sched.remove()
204: /* remove from run_chain and make IDLE */
205: {
206: register class sched * p;
207: register class sched * pp;
208:
209: if (p = run_chain)
210: if (p == this)
211: run_chain = (sched*) o_next;
212: else
213: for (; pp = (sched*) p->o_next; p=pp)
214: if (pp == this) {
215: p->o_next = pp->o_next;
216: goto ll;
217: }
218: ll:
219: s_state = IDLE;
220: o_next = 0;
221: }
222:
223: void sched.print(int n)
224: {
225: int m = n & ~CHAIN;
226:
227: switch (o_type) {
228: case TIMER:
229: ((timer*)this)->print(m);
230: break;
231: case TASK:
232: ((task*)this)->print(m);
233: break;
234: }
235:
236: if (n&CHAIN) {
237: if (o_next) ((sched*) o_next)->print(n);
238: }
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.