|
|
1.1 root 1: #include <osfcn.h>
2: #include "task.h"
3:
4: void
5: sched::setclock(long t)
6: {
7: if (clxck) task_error(E_SETCLOCK);
8: clxck = t;
9: }
10:
11: void
12: sched::cancel(int res)
13: {
14: if (s_state==RUNNING) remove();
15: s_state = TERMINATED;
16: s_time = res;
17: alert();
18: }
19:
20: int
21: sched::result()
22: /* wait for termination and retrieve result */
23: {
24: if (this == (sched*)this_task()) ((object*)0)->task_error(E_RESULT);
25: while (s_state != TERMINATED) {
26: this_task()->sleep(this);
27: }
28:
29: return (int) s_time;
30: }
31:
32: void
33: sched::schedule()
34: /* schedule either clock_task or front of runchain.
35: This routine causes a coroutine switch by calling resume.
36: When control eventually returns to this coroutine, it does so
37: through task::restore and swap().
38: For the 68000 implementation, the exit sequence of this function must
39: match that of task::task() and swap(), so check and be sure they
40: do. Copy the exit sequence into swap if necesssary.
41: */
42: {
43: int a_dummy;
44: register sched* p;
45: register long tt;
46: register int* p1_dummy;
47: register int* p2_dummy;
48: // we must trick the compiler into thinking we really use all these registers
49: register int y, z, u, v, w;
50: w = 0; v = w; u = v; z = u; y = z; a_dummy = y;
51: p1_dummy = p2_dummy = 0;
52:
53: keep_waiting:
54: if (p = priority_sched) {
55: priority_sched = 0; // no chain here
56: p->remove(); // in case it's also on the runchain
57: p->s_state = RUNNING; // since remove sets it IDLE
58: }
59: else if (p = runchain) {
60: runchain = (sched*) p->o_next;
61: p->o_next = 0;
62: }
63: else {
64: if (keep_waiting_count) {
65: ::wait(0);
66: goto keep_waiting;
67: }
68: if (exit_fct) (*exit_fct)();
69: for (p = task::txsk_chxin; p; p = ((task*)p)->t_next) {
70: if (p->s_state == RUNNING) p->remove();
71: p->s_state = TERMINATED;
72: p->s_time = 0;
73: }
74: exit(0);
75: }
76:
77: tt = p->s_time;
78: if (tt != clxck) {
79: if (tt < clxck) task_error(E_SCHTIME);
80: clxck = tt;
81: if (clock_task) {
82: if (clock_task->s_state != IDLE)
83: task_error(E_CLOCKIDLE);
84: /* clock_task preferred -- put p back onto runchain */
85: p->o_next = (object*) runchain;
86: runchain = p;
87: p = (sched*) clock_task;
88: }
89: }
90:
91: if (p != this)
92: p->resume();
93: } /* schedule */
94:
95: void
96: sched::insert(int d, object* who)
97: /*
98: schedule THIS to run in ``d'' time units
99: inserted by who
100: */
101: {
102: register sched * p;
103: register sched * pp;
104: register long tt = s_time = clxck + d;
105:
106: switch (s_state) {
107: case TERMINATED:
108: task_error(E_RESTERM);
109: break;
110: case IDLE:
111: break;
112: case RUNNING:
113: if (this != (class sched *)this_task()) task_error(E_RESRUN);
114: }
115:
116: if (d<0) task_error(E_NEGTIME);
117:
118: if (o_next) task_error(E_RESOBJ);
119:
120: s_state = RUNNING;
121: setwho(who);
122:
123: /* runchain ordered by s_time */
124: if (p = runchain) {
125: if (tt < p->s_time) {
126: o_next = (object*) runchain;
127: runchain = this;
128: }
129: else {
130: while (pp = (sched *) p->o_next) {
131: if (tt < pp->s_time) {
132: o_next = pp;
133: p->o_next = this;
134: return;
135: }
136: else p = pp;
137: }
138: p->o_next = this;
139: }
140: }
141: else
142: runchain = this;
143: }
144:
145: void
146: sched::remove()
147: /* remove from runchain and make IDLE */
148: {
149: register class sched * p;
150: register class sched * pp;
151:
152: if (p = runchain)
153: if (p == this)
154: runchain = (sched*) o_next;
155: else
156: for (; pp = (sched*) p->o_next; p=pp)
157: if (pp == this) {
158: p->o_next = pp->o_next;
159: break;
160: }
161: s_state = IDLE;
162: o_next = 0;
163: }
164:
165:
166: void
167: sched::print(int n, int baseClass)
168: {
169: if (!baseClass)
170: printf("naked sched ");
171: if (n&CHAIN) {
172: if (o_next) ((sched*) o_next)->print(n);
173: }
174:
175: object::print(n, 1);
176: if (!baseClass)
177: task_error(E_SCHOBJ); // only derived class instances allowed
178: }
179:
180: int
181: sched::pending()
182: {
183: return s_state != TERMINATED;
184: }
185:
186: void
187: sched::resume() // this should never be called
188: {
189: task_error(E_SCHOBJ);
190: }
191:
192: void
193: sched::setwho(object*) // this should never be called
194: {
195: task_error(E_SCHOBJ);
196: }
197:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.