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