|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.4 ! root 5: Copyright 1992,1993 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: #include "mint.h"
14:
15:
16:
17: /*
18:
19: * We initialize proc_clock to a very large value so that we don't have
20:
21: * to worry about unexpected process switches while starting up
22:
23: */
24:
25:
26:
27: short proc_clock = 0x7fff;
28:
29:
30:
31: /* used by filesystems for time/date stamps; updated once per second */
32:
33: short timestamp, datestamp;
34:
35:
36:
37: extern short in_kernel; /* in main.c */
38:
39:
40:
41: static void unnapme P_((PROC *));
42:
43:
44:
45: /*
46:
47: * addtimeout(long delta, void (*func)()): schedule a timeout for the current
48:
49: * process, to take place in "delta" milliseconds. "func" specifies a
50:
51: * function to be called at that time; the function is passed as a parameter
52:
53: * the process for which the timeout was specified (i.e. the value of
54:
55: * curproc at the time addtimeout() was called; note that this is probably
56:
57: * *not* the current process when the timeout occurs).
58:
59: */
60:
61:
62:
63: TIMEOUT *tlist;
64:
65:
66:
67: #define newtimeout() (TIMEOUT *)kmalloc(SIZEOF(TIMEOUT))
68:
69: #define disposetimeout(t) kfree(t)
70:
71:
72:
1.1.1.4 ! root 73: TIMEOUT * ARGS_ON_STACK
1.1 root 74:
75: addtimeout(delta, func)
76:
77: long delta;
78:
79: void (*func) P_((PROC *));
80:
81: {
82:
83: TIMEOUT *t, **prev, *cur;
84:
85:
86:
87: t = newtimeout();
88:
89:
90:
91: /* BUG: we should have some fallback mechanism for timeouts when the
92:
93: kernel memory is exhausted
94:
95: */
96:
97: assert(t);
98:
99:
100:
101: t->proc = curproc;
102:
103: t->func = func;
104:
105:
106:
107: cur = tlist;
108:
109: prev = &tlist;
110:
111: while (cur) {
112:
113: if (cur->when >= delta) {
114:
115: cur->when -= delta;
116:
117: t->next = cur;
118:
119: t->when = delta;
120:
121: *prev = t;
122:
123: return t;
124:
125: }
126:
127: delta -= cur->when;
128:
129: prev = &cur->next;
130:
131: cur = cur->next;
132:
133: }
134:
135: assert(delta >= 0);
136:
137: t->when = delta;
138:
139: t->next = cur;
140:
141: *prev = t;
142:
143: return t;
144:
145: }
146:
147:
148:
149: /*
150:
151: * cancelalltimeouts(): cancels all pending timeouts for the current
152:
153: * process
154:
155: */
156:
157:
158:
1.1.1.4 ! root 159: void ARGS_ON_STACK
1.1 root 160:
161: cancelalltimeouts()
162:
163: {
164:
165: TIMEOUT *cur, **prev, *old;
166:
167: long delta;
168:
169:
170:
171: cur = tlist;
172:
173: prev = &tlist;
174:
175: while (cur) {
176:
177: if (cur->proc == curproc) {
178:
179: delta = cur->when;
180:
181: old = cur;
182:
183: *prev = cur = cur->next;
184:
185: if (cur) cur->when += delta;
186:
187: disposetimeout(old);
188:
189: }
190:
191: else {
192:
193: prev = &cur->next;
194:
195: cur = cur->next;
196:
197: }
198:
199: }
200:
201: }
202:
203:
204:
205: /*
206:
207: * Cancel a specific timeout. If the timeout isn't on the list, or isn't
208:
209: * for this process, we do nothing; otherwise, we cancel the time out
210:
211: * and then free the memory it used. *NOTE*: it's very possible (indeed
212:
213: * likely) that "this" was already removed from the list and disposed of
214:
215: * by the timeout processing routines, so it's important that we check
216:
217: * for it's presence in the list and do absolutely nothing if we don't
218:
219: * find it there!
220:
221: */
222:
223:
224:
1.1.1.4 ! root 225: void ARGS_ON_STACK
1.1 root 226:
227: canceltimeout(this)
228:
229: TIMEOUT *this;
230:
231: {
232:
233: TIMEOUT *cur, **prev;
234:
235:
236:
237: prev = &tlist;
238:
239: for (cur = tlist; cur; cur = cur->next) {
240:
241: if (cur == this && cur->proc == curproc) {
242:
243: *prev = cur->next;
244:
245: if (cur->next) {
246:
247: cur->next->when += this->when;
248:
249: }
250:
251: disposetimeout(this);
252:
253: break;
254:
255: }
256:
257: prev = &cur->next;
258:
259: }
260:
261: }
262:
263:
264:
265: /*
266:
267: * timeout: called every 20 ms or so by GEMDOS, this routine
268:
269: * is responsible for maintaining process times and such.
270:
271: * it should also decrement the "proc_clock" variable, but
272:
273: * should *not* take any action when it reaches 0 (the state of the
274:
275: * stack is too uncertain, and time is too critical). Instead,
276:
277: * a vbl routine checks periodically and if "proc_clock" is 0
278:
279: * suspends the current process
280:
281: */
282:
283:
284:
285: volatile int our_clock = 1000;
286:
287:
288:
1.1.1.2 root 289: void ARGS_ON_STACK
1.1 root 290:
291: timeout()
292:
293: {
294:
295: int ms; /* time between ticks */
296:
297:
298:
299: ms = *((short *)0x442L);
300:
301: if (proc_clock > 0)
302:
303: proc_clock--;
304:
305:
306:
307: our_clock -= ms;
308:
309: if (tlist) {
310:
311: tlist->when -= ms;
312:
313: }
314:
315: }
316:
317:
318:
319: /*
320:
321: * sleep() calls this routine to check on alarms and other sorts
322:
323: * of time-outs on every context switch.
324:
325: */
326:
327:
328:
329: void
330:
331: checkalarms()
332:
333: {
334:
335: extern long searchtime; /* in dosdir.c */
336:
337: PROC *p;
338:
339: long delta;
340:
341: void (*evnt) P_((PROC *));
342:
343: TIMEOUT *old;
344:
345:
346:
347: /* do the once per second things */
348:
349: while (our_clock < 0) {
350:
351: our_clock += 1000;
352:
353: timestamp = Tgettime();
354:
355: datestamp = Tgetdate();
356:
357: searchtime++;
358:
359: reset_priorities();
360:
361: }
362:
363:
364:
365: /* see if there are outstanding timeout requests to do */
366:
367: while (tlist && ((delta = tlist->when) <= 0)) {
368:
369: p = tlist->proc;
370:
1.1.1.2 root 371: TRACE(("doing timeout code for pid %d", p->pid));
1.1 root 372:
373: evnt = tlist->func;
374:
375: old = tlist;
376:
377: tlist = tlist->next;
378:
379: disposetimeout(old);
380:
381: /* call the timeout function */
382:
383: (*evnt)(p);
384:
385:
386:
387: /* if delta < 0, it's possible that the time has come for the next timeout
388:
389: to occur */
390:
391: if (tlist)
392:
393: tlist->when += delta;
394:
395: }
396:
397: }
398:
399:
400:
401: /*
402:
403: * nap(n): nap for n milliseconds. Used in loops where we're waiting for
404:
405: * an event. If we expect the event *very* soon, we should use yield
406:
407: * instead.
408:
409: * NOTE: we may not sleep for exactly n milliseconds; signals can wake
410:
411: * us earlier, and the vagaries of process scheduling may cause us to
412:
413: * oversleep...
414:
415: */
416:
417:
418:
419: static void
420:
421: unnapme(p)
422:
423: PROC *p;
424:
425: {
426:
1.1.1.2 root 427: if (p->wait_q == SELECT_Q && p->wait_cond == (long)nap) {
1.1 root 428:
1.1.1.3 root 429: short sr = spl7();
430:
1.1 root 431: rm_q(SELECT_Q, p);
432:
433: add_q(READY_Q, p);
434:
1.1.1.3 root 435: spl(sr);
436:
1.1 root 437: p->wait_cond = 0;
438:
439: }
440:
441: }
442:
443:
444:
1.1.1.2 root 445: void ARGS_ON_STACK
1.1 root 446:
447: nap(n)
448:
449: unsigned n;
450:
451: {
452:
453: TIMEOUT *t;
454:
455:
456:
457: t = addtimeout((long)n, unnapme);
458:
1.1.1.2 root 459: sleep(SELECT_Q, (long)nap);
1.1 root 460:
461: canceltimeout(t);
462:
463: }
464:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.