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