|
|
1.1 ! root 1: /* $Header: /src386/STREAMS/coh.386/RCS/clock.c,v 2.3 93/08/09 13:35:15 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 5.0 ! 11: * Copyright (c) 1982, 1993. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Clock. ! 18: * The clock comes in two parts. There is the routine `clock' which ! 19: * gets called every tick at high priority. It does the minimum it ! 20: * can and returns as soon as possible. The second routine, `stand', ! 21: * gets called whenever we are about to return from an interrupt to ! 22: * user mode at low priority. It can look at flags that the clock set ! 23: * and do the things the clock really wanted to do but didn't have time. ! 24: * Stand is truly the kernel of the system. ! 25: * ! 26: * 90/08/13 Hal Snyder /usr/src/sys/coh/clock.c ! 27: * Add external altclk to allow polled device drivers. ! 28: * (extern'ed in coherent.h) ! 29: * ! 30: * 87/10/26 Allan cornish /usr/src/sys/coh/clock.c ! 31: * Timed functions are now invoked with TIM * tp as second argument. ! 32: * This facilitates the use of timed functions within loadable drivers. ! 33: * ! 34: * 87/07/07 Allan Cornish /usr/src/sys/coh/clock.c ! 35: * Clocks static variable added - incremented by clock, decremented by stand(). ! 36: * Lbolt variable added - clock ticks since startup - incremented by stand(). ! 37: * Support for multiple timing queues ported from RTX. ! 38: * ! 39: * 87/01/05 Allan Cornish /usr/src/sys/coh/clock.c ! 40: * stand() now only wakes &stimer if swap timer is active. ! 41: * ! 42: * 86/11/24 Allan Cornish /usr/src/sys/coh/clock.c ! 43: * Added support for new t_last field in tim struct. ! 44: * ! 45: * 86/11/19 Allan Cornish /usr/src/sys/coh/clock.c ! 46: * Stand() calls defend() to execute functions deferred from interrupt level. ! 47: */ ! 48: ! 49: #include <common/_gregset.h> ! 50: #include <common/_tricks.h> ! 51: ! 52: #include <kernel/sigproc.h> ! 53: #include <kernel/timeout.h> ! 54: #include <sys/coherent.h> ! 55: #include <sys/con.h> ! 56: #include <sys/proc.h> ! 57: #include <sys/sched.h> ! 58: #include <sys/stat.h> ! 59: ! 60: int (*altclk)(); /* pointer to higher-speed clock function */ ! 61: ! 62: #if ! _I386 ! 63: int altsel; /* if nonzero, CS for LOADABLE driver owning altclk() */ ! 64: #endif ! 65: ! 66: int clocks; ! 67: ! 68: #ifdef TRACER ! 69: ! 70: extern char stext; ! 71: extern char __end_text; ! 72: ! 73: #endif ! 74: ! 75: /* ! 76: * This routine is called once every tick (1/HZ seconds). ! 77: * It gets called with the program counter that was interrupted ! 78: * and the CPL of the interrupted code (0..3). ! 79: */ ! 80: clock(pc, umode) ! 81: caddr_t pc; ! 82: { ! 83: register PROC *pp; ! 84: ! 85: /* ! 86: * Ignore clock interrupts till we are ready. ! 87: */ ! 88: if (batflag == 0) ! 89: return; ! 90: ! 91: /* ! 92: * Hook for alternate clock interrupt; ! 93: * Call polling function ("altclk") if there is one. ! 94: * ! 95: * For near function, "altsel" is 0 and "altclk" is offset. ! 96: * For far function, "altsel" is the CS selector and "altclk" ! 97: * is the offset. ! 98: * ! 99: * Since the polling function ends with a near rather than ! 100: * far return, far invocation is via ld_call() (ldas.s) which uses ! 101: * the despatch routine at CS:4 (ld.s) in any loadable driver. ! 102: */ ! 103: if (altclk) { ! 104: #if ! _I386 ! 105: if (altsel) { /* will do far call to altclk fn */ ! 106: if (ld_call (altsel, altclk)) ! 107: return; ! 108: } else ! 109: #endif ! 110: if ((* altclk) ()) ! 111: return; ! 112: } ! 113: ! 114: /* ! 115: * Update timers. Decrement time slice. ! 116: */ ! 117: utimer += 1; ! 118: clocks += 1; ! 119: timer.t_tick += 1; ! 120: quantum -= 1; ! 121: ! 122: #if ! _I386 ! 123: /* ! 124: * Give processes their schedule values per tick. ! 125: */ ! 126: if (procq.p_lforw->p_cval > CVCLOCK) { ! 127: procq.p_lforw->p_cval -= CVCLOCK; ! 128: procq.p_cval += CVCLOCK; ! 129: } ! 130: #endif ! 131: ! 132: /* ! 133: * Tax current process and update his times. ! 134: */ ! 135: pp = SELF; ! 136: #if ! _I386 ! 137: pp->p_cval >>= 1; ! 138: #endif ! 139: if (umode == R_USR) { ! 140: pp->p_utime ++; ! 141: u.u_ppc = pc; ! 142: } else ! 143: pp->p_stime ++; ! 144: } ! 145: ! 146: /* ! 147: * stand() ! 148: * ! 149: * Called when there is an interrupt or trap, and the system is about to ! 150: * return to user mode (or to the idle process). ! 151: */ ! 152: ! 153: void ! 154: stand (regset) ! 155: gregset_t regset; ! 156: { ! 157: int s; ! 158: ! 159: #ifdef TIMING ! 160: /* ! 161: * Every 500th call to stand(), dump logged intervals. ! 162: * ! 163: * Log a group of events doing ! 164: * LOGIN(label); ! 165: * ... ! 166: * LOGOUT(); ! 167: * ! 168: * If you want to group several selected events in one total, ! 169: * do LOGPAUSE() to halt between events and LOGRESUME() to ! 170: * add in the time for another event. Event count is displayed. ! 171: * For example: ! 172: * LOGIN(label); ! 173: * while (...) { ! 174: * LOGPAUSE(); ! 175: * ... stuff you don't want timed... ! 176: * LOGRESUME(); ! 177: * ... stuff you want timed... ! 178: * } ! 179: * LOGOUT(); ! 180: * ! 181: * Display is for the 3 longest intervals seen in latest logging ! 182: * period. ! 183: * ! 184: * Timing between in & out is displayed with ~1 usec resolution. ! 185: * Overhead per event is ~20 usec. ! 186: */ ! 187: static int call_ct; /* DEBUG */ ! 188: ! 189: call_ct++; ! 190: if (call_ct >= 500) { ! 191: call_ct = 0; ! 192: LOGLIST(); ! 193: } ! 194: #endif ! 195: ! 196: u.u_error = 0; ! 197: ! 198: /* ! 199: * Update the clock. ! 200: */ ! 201: ! 202: while (timer.t_tick >= HZ) { ! 203: #ifdef TRACER ! 204: extern int checkTheSum (); ! 205: static int check_check; ! 206: ! 207: if (check_check ++ > 120) { ! 208: check_check = 0; ! 209: checkTheSum (); ! 210: } ! 211: #endif ! 212: timer.t_time ++; ! 213: timer.t_tick -= HZ; ! 214: outflag = 1; ! 215: } ! 216: ! 217: /* ! 218: * Check expiration of quantum. ! 219: */ ! 220: ! 221: if (quantum <= 0) { ! 222: quantum = 0; ! 223: disflag = 1; ! 224: } ! 225: ! 226: /* ! 227: * Check the timed function queue if necessary. ! 228: */ ! 229: ! 230: while (clocks) { ! 231: register TIM * np; ! 232: register TIM * tp; ! 233: ! 234: /* ! 235: * Update [serviced] clock ticks since startup. ! 236: */ ! 237: lbolt ++; ! 238: clocks --; ! 239: ! 240: /* ! 241: * Remove timing list from queue, creating new temporary queue. ! 242: */ ! 243: ! 244: tp = timq + (lbolt % __ARRAY_LENGTH (timq)); ! 245: s = sphi (); ! 246: ! 247: /* ! 248: * Scan timing list. ! 249: */ ! 250: ! 251: for (np = tp->t_next; tp = np;) { ! 252: /* ! 253: * Remember next function in timing list. ! 254: * NOTE: Must be done before function is invoked, ! 255: * since it may start a new timer. ! 256: */ ! 257: ! 258: np = tp->t_next; ! 259: ! 260: /* ! 261: * Function has not timed out: leave it on timing list. ! 262: */ ! 263: ! 264: if (tp->t_lbolt != lbolt) ! 265: continue; ! 266: ! 267: /* ! 268: * Remove function from timing list. ! 269: */ ! 270: ! 271: if (tp->t_last->t_next = tp->t_next) ! 272: tp->t_next->t_last = tp->t_last; ! 273: tp->t_last = NULL; ! 274: ! 275: /* ! 276: * Invoke function. ! 277: */ ! 278: #ifdef TRACER ! 279: if (tp->t_func < & stext || tp->t_func > & __end_text) ! 280: panic ("Bad timeout function %x in timer %x", ! 281: tp->t_func, tp); ! 282: #endif ! 283: ! 284: spl (s); ! 285: (* tp->t_func) (tp->t_farg, tp); ! 286: sphi (); ! 287: } ! 288: ! 289: spl (s); ! 290: ! 291: STREAMS_TIMEOUT (); ! 292: ! 293: } ! 294: ! 295: /* ! 296: * Timeout any devices. ! 297: */ ! 298: ! 299: if (outflag) { ! 300: register int n; ! 301: ! 302: outflag = 0; ! 303: for (n = 0 ; n < drvn ; n ++) { ! 304: if (drvl [n].d_time == 0) ! 305: continue; ! 306: s = sphi (); ! 307: dtime ((dev_t) makedev (n, 0)); ! 308: spl (s); ! 309: } ! 310: } ! 311: ! 312: /* ! 313: * Do profiling. ! 314: */ ! 315: ! 316: #if _I386 /* profiling */ ! 317: if (u.u_pscale & ~1) { /* if scale is not zero or one */ ! 318: /* ! 319: * Treat u.u_pscale as fixed-point fraction 0xXXXX.YYYY. ! 320: * Increment the (short) profiling entry at ! 321: * base + (pc - offset) * scale ! 322: */ ! 323: register caddr_t a; ! 324: ! 325: a = (caddr_t) ((long) (u.u_pbase + pscale(u.u_ppc-u.u_pofft, ! 326: u.u_pscale)) & ~1); ! 327: if (a < u.u_pbend) ! 328: putusd(a, getusd(a)+1); ! 329: } ! 330: #else /* profiling */ ! 331: if (u.u_pscale) { ! 332: register unsigned p; ! 333: register caddr_t a; ! 334: ! 335: p = u.u_pscale; ! 336: a = (int *)u.u_pbase + ! 337: pscale((int)(u.u_ppc-u.u_pofft), p/sizeof (int)); ! 338: if (a < u.u_pbend) ! 339: putuwd(a, getuwd(a)+1); ! 340: } ! 341: #endif /* profiling */ ! 342: ! 343: /* ! 344: * Check for signals and execute them; we pass in the address of the ! 345: * user's process context rather than depend on the state of the ! 346: * "u.u_regl" global idiocy. ! 347: */ ! 348: ! 349: curr_check_signals (& regset); ! 350: ! 351: ! 352: /* ! 353: * Execute deferred functions. ! 354: */ ! 355: ! 356: defend (); ! 357: ! 358: ! 359: /* ! 360: * Should we dispatch? ! 361: */ ! 362: if ((SELF->p_flags & PFDISP) != 0) { ! 363: SELF->p_flags &= ~ PFDISP; ! 364: disflag = 1; ! 365: if (stimer.t_last != 0) ! 366: wakeup ((char *)& stimer); ! 367: } ! 368: ! 369: /* ! 370: * Redispatch. ! 371: */ ! 372: if (disflag) { ! 373: register PROC *pp; ! 374: ! 375: s = sphi (); ! 376: if ((pp = SELF) != iprocp) ! 377: setrun (pp); ! 378: dispatch (); ! 379: spl (s); ! 380: } ! 381: ! 382: STREAMS_SCHEDULER (); ! 383: } ! 384: ! 385: #ifdef TIMING ! 386: ! 387: #define EIMAX 3 ! 388: ! 389: static int label, b_in, t_in; ! 390: static int b_pause, t_pause, e_pause, paused, timing; ! 391: ! 392: struct H_event { ! 393: int f; /* timing label */ ! 394: int b; /* delta ticks */ ! 395: int t; /* delta timer */ ! 396: int e; /* event count */ ! 397: } Ltab[EIMAX]; ! 398: ! 399: LOGIN(lab) ! 400: { ! 401: paused = 0; ! 402: b_pause = t_pause = 0; ! 403: e_pause = 1; ! 404: label = lab; ! 405: b_in = clocks + lbolt; ! 406: t_in = read_t0(); ! 407: timing = 1; ! 408: } ! 409: ! 410: LOGOUT() ! 411: { ! 412: int i; ! 413: ! 414: if (!timing) ! 415: return; ! 416: if (!paused) { ! 417: b_pause += clocks + lbolt - b_in; ! 418: t_pause += (t_in - read_t0()); ! 419: if (t_pause < 0) ! 420: t_pause += 11932; ! 421: } ! 422: for (i = 0; i < EIMAX; i++) { ! 423: if (b_pause > Ltab[i].b) { ! 424: Ltab[i].b = b_pause; ! 425: Ltab[i].t = t_pause; ! 426: Ltab[i].f = label; ! 427: Ltab[i].e = e_pause; ! 428: break; ! 429: } else if (b_pause == Ltab[i].b) { ! 430: if (t_pause > Ltab[i].t) { ! 431: Ltab[i].t = t_pause; ! 432: Ltab[i].f = label; ! 433: Ltab[i].e = e_pause; ! 434: break; ! 435: } else if (t_pause == Ltab[i].t) { ! 436: break; ! 437: } ! 438: } ! 439: } ! 440: timing = 0; ! 441: } ! 442: ! 443: LOGLIST() ! 444: { ! 445: int i, printed = 0; ! 446: ! 447: for (i = 0; i < EIMAX; i++) ! 448: if (Ltab[i].t || Ltab[i].b) { ! 449: if (printed == 0) { ! 450: printf("\npsw=%x ", read_psw()); ! 451: printed = 1; ! 452: } ! 453: printf("f=%x b=%d t=%d e=%d ", ! 454: Ltab[i].f, Ltab[i].b, Ltab[i].t, Ltab[i].e); ! 455: Ltab[i].f = Ltab[i].b = Ltab[i].t = 0; ! 456: } else ! 457: break; ! 458: } ! 459: ! 460: LOGPAUSE() ! 461: { ! 462: if (!timing) ! 463: return; ! 464: if (!paused) { ! 465: b_pause += clocks + lbolt - b_in; ! 466: t_pause += (t_in - read_t0()); ! 467: if (t_pause < 0) ! 468: t_pause += 11932; ! 469: paused = 1; ! 470: } ! 471: } ! 472: ! 473: LOGRESUME() ! 474: { ! 475: if (!timing) ! 476: return; ! 477: if (paused) { ! 478: b_in = clocks + lbolt; ! 479: t_in = read_t0(); ! 480: paused = 0; ! 481: e_pause++; ! 482: } ! 483: } ! 484: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.