|
|
1.1 ! root 1: /* $Header: /y/coh.386/RCS/clock.c,v 1.9 93/04/14 10:06:19 root Exp $ */ ! 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 a 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: #include <sys/coherent.h> ! 49: #include <sys/con.h> ! 50: #include <sys/proc.h> ! 51: #include <sys/sched.h> ! 52: #include <sys/stat.h> ! 53: #include <sys/timeout.h> ! 54: #include <sys/mdata.h> ! 55: ! 56: int (*altclk)(); /* pointer to higher-speed clock function */ ! 57: ! 58: #ifndef _I386 ! 59: int altsel; /* if nonzero, CS for LOADABLE driver owning altclk() */ ! 60: #endif ! 61: ! 62: int clocks; ! 63: ! 64: /* ! 65: * This routine is called once every tick (1/HZ seconds). ! 66: * It gets called with the program counter that was interrupted ! 67: * and the CPL of the interrupted code (0..3). ! 68: */ ! 69: clock(pc, umode) ! 70: caddr_t pc; ! 71: { ! 72: register PROC *pp; ! 73: ! 74: /* ! 75: * Ignore clock interrupts till we are ready. ! 76: */ ! 77: if (batflag == 0) ! 78: return; ! 79: ! 80: /* ! 81: * Hook for alternate clock interrupt; ! 82: * Call polling function ("altclk") if there is one. ! 83: * ! 84: * For near function, "altsel" is 0 and "altclk" is offset. ! 85: * For far function, "altsel" is the CS selector and "altclk" ! 86: * is the offset. ! 87: * ! 88: * Since the polling function ends with a near rather than ! 89: * far return, far invocation is via ld_call() (ldas.s) which uses ! 90: * the despatch routine at CS:4 (ld.s) in any loadable driver. ! 91: */ ! 92: if (altclk) { ! 93: #ifndef _I386 ! 94: if (altsel) { /* will do far call to altclk fn */ ! 95: if (ld_call(altsel, altclk)) ! 96: return; ! 97: } else ! 98: #endif ! 99: if ((*altclk)()) ! 100: return; ! 101: } ! 102: ! 103: /* ! 104: * Update timers. Decrement time slice. ! 105: */ ! 106: utimer += 1; ! 107: clocks += 1; ! 108: timer.t_tick += 1; ! 109: quantum -= 1; ! 110: ! 111: #ifndef _I386 ! 112: /* ! 113: * Give processes their schedule values per tick. ! 114: */ ! 115: if (procq.p_lforw->p_cval > CVCLOCK) { ! 116: procq.p_lforw->p_cval -= CVCLOCK; ! 117: procq.p_cval += CVCLOCK; ! 118: } ! 119: #endif ! 120: ! 121: /* ! 122: * Tax current process and update his times. ! 123: */ ! 124: pp = SELF; ! 125: #ifndef _I386 ! 126: pp->p_cval >>= 1; ! 127: #endif ! 128: if (umode == R_USR) { ! 129: pp->p_utime++; ! 130: u.u_ppc = pc; ! 131: } else ! 132: pp->p_stime++; ! 133: } ! 134: ! 135: /* ! 136: * stand() ! 137: * ! 138: * Called when there is an interrupt or trap. ! 139: */ ! 140: stand() ! 141: { ! 142: int s; ! 143: ! 144: #ifdef TIMING ! 145: /* ! 146: * Every 500th call to stand(), dump logged intervals. ! 147: * ! 148: * Log a group of events doing ! 149: * LOGIN(label); ! 150: * ... ! 151: * LOGOUT(); ! 152: * ! 153: * If you want to group several selected events in one total, ! 154: * do LOGPAUSE() to halt between events and LOGRESUME() to ! 155: * add in the time for another event. Event count is displayed. ! 156: * For example: ! 157: * LOGIN(label); ! 158: * while (...) { ! 159: * LOGPAUSE(); ! 160: * ... stuff you don't want timed... ! 161: * LOGRESUME(); ! 162: * ... stuff you want timed... ! 163: * } ! 164: * LOGOUT(); ! 165: * ! 166: * Display is for the 3 longest intervals seen in latest logging ! 167: * period. ! 168: * ! 169: * Timing between in & out is displayed with ~1 usec resolution. ! 170: * Overhead per event is ~20 usec. ! 171: */ ! 172: static int call_ct; /* DEBUG */ ! 173: ! 174: call_ct++; ! 175: if (call_ct >= 500) { ! 176: call_ct = 0; ! 177: LOGLIST(); ! 178: } ! 179: #endif ! 180: ! 181: u.u_error = 0; ! 182: ! 183: /* ! 184: * Update the clock. ! 185: */ ! 186: while (timer.t_tick >= HZ) { ! 187: timer.t_time++; ! 188: timer.t_tick -= HZ; ! 189: outflag = 1; ! 190: } ! 191: ! 192: /* ! 193: * Check expiration of quantum. ! 194: */ ! 195: if (quantum <= 0) { ! 196: quantum = 0; ! 197: disflag = 1; ! 198: } ! 199: ! 200: /* ! 201: * Check the timed function queue if necessary. ! 202: */ ! 203: if (clocks > 0) ! 204: do { ! 205: register TIM * np; ! 206: register TIM * tp; ! 207: ! 208: /* ! 209: * Update [serviced] clock ticks since startup. ! 210: */ ! 211: lbolt++; ! 212: clocks--; ! 213: ! 214: /* ! 215: * Remove timing list from queue, creating new temporary queue. ! 216: */ ! 217: tp = (TIM *) &timq[ lbolt % nel(timq) ]; ! 218: s = sphi(); ! 219: ! 220: /* ! 221: * Scan timing list. ! 222: */ ! 223: for (np = tp->t_next; tp = np;) { ! 224: ! 225: /* ! 226: * Remember next function in timing list. ! 227: * NOTE: Must be done before function is invoked, ! 228: * since it may start a new timer. ! 229: */ ! 230: np = tp->t_next; ! 231: ! 232: /* ! 233: * Function has not timed out: leave it on timing list. ! 234: */ ! 235: if (tp->t_lbolt != lbolt) ! 236: continue; ! 237: ! 238: /* ! 239: * Remove function from timing list. ! 240: */ ! 241: if (tp->t_last->t_next = tp->t_next) ! 242: tp->t_next->t_last = tp->t_last; ! 243: tp->t_last = NULL; ! 244: ! 245: /* ! 246: * Invoke function. ! 247: */ ! 248: spl(s); ! 249: (*tp->t_func)(tp->t_farg, tp); ! 250: sphi(); ! 251: } ! 252: ! 253: spl(s); ! 254: ! 255: STREAMS_TIMEOUT (); ! 256: ! 257: } while (clocks); ! 258: ! 259: /* ! 260: * Timeout any devices. ! 261: */ ! 262: if (outflag) { ! 263: register int n; ! 264: ! 265: outflag = 0; ! 266: for (n=0; n<drvn; n++) { ! 267: if (drvl[n].d_time == 0) ! 268: continue; ! 269: s = sphi(); ! 270: dtime((dev_t)makedev(n, 0)); ! 271: spl(s); ! 272: } ! 273: } ! 274: ! 275: /* ! 276: * Do profiling. ! 277: */ ! 278: #ifdef _I386 /* profiling */ ! 279: if (u.u_pscale & ~1) { /* if scale is not zero or one */ ! 280: /* ! 281: * Treat u.u_pscale as fixed-point fraction 0xXXXX.YYYY. ! 282: * Increment the (short) profiling entry at ! 283: * base + (pc - offset) * scale ! 284: */ ! 285: register caddr_t a; ! 286: ! 287: a = (caddr_t) ((long) (u.u_pbase + pscale(u.u_ppc-u.u_pofft, ! 288: u.u_pscale)) & ~1); ! 289: if (a < u.u_pbend) ! 290: putusd(a, getusd(a)+1); ! 291: } ! 292: #else /* profiling */ ! 293: if (u.u_pscale) { ! 294: register unsigned p; ! 295: register caddr_t a; ! 296: ! 297: p = u.u_pscale; ! 298: a = (int *)u.u_pbase + ! 299: pscale((int)(u.u_ppc-u.u_pofft), p/sizeof (int)); ! 300: if (a < u.u_pbend) ! 301: putuwd(a, getuwd(a)+1); ! 302: } ! 303: #endif /* profiling */ ! 304: ! 305: /* ! 306: * Check for signals and execute them. ! 307: */ ! 308: if (SELF->p_ssig) { ! 309: actvsig(); ! 310: } ! 311: ! 312: /* ! 313: * Execute deferred functions. ! 314: */ ! 315: defend(); ! 316: ! 317: /* ! 318: * Should we dispatch? ! 319: */ ! 320: if ((SELF->p_flags&PFDISP) != 0) { ! 321: SELF->p_flags &= ~PFDISP; ! 322: disflag = 1; ! 323: if (stimer.t_last != 0) ! 324: wakeup((char *)&stimer); ! 325: } ! 326: ! 327: /* ! 328: * Redispatch. ! 329: */ ! 330: if (disflag) { ! 331: register PROC *pp; ! 332: ! 333: s=sphi(); ! 334: if ((pp=SELF)!=iprocp) ! 335: setrun(pp); ! 336: dispatch(); ! 337: spl(s); ! 338: } ! 339: ! 340: STREAMS_SCHEDULER (); ! 341: ! 342: return; ! 343: } ! 344: ! 345: #ifdef TIMING ! 346: ! 347: #define EIMAX 3 ! 348: ! 349: static int label, b_in, t_in; ! 350: static int b_pause, t_pause, e_pause, paused, timing; ! 351: ! 352: struct H_event { ! 353: int f; /* timing label */ ! 354: int b; /* delta ticks */ ! 355: int t; /* delta timer */ ! 356: int e; /* event count */ ! 357: } Ltab[EIMAX]; ! 358: ! 359: LOGIN(lab) ! 360: { ! 361: paused = 0; ! 362: b_pause = t_pause = 0; ! 363: e_pause = 1; ! 364: label = lab; ! 365: b_in = clocks + lbolt; ! 366: t_in = read_t0(); ! 367: timing = 1; ! 368: } ! 369: ! 370: LOGOUT() ! 371: { ! 372: int i; ! 373: ! 374: if (!timing) ! 375: return; ! 376: if (!paused) { ! 377: b_pause += clocks + lbolt - b_in; ! 378: t_pause += (t_in - read_t0()); ! 379: if (t_pause < 0) ! 380: t_pause += 11932; ! 381: } ! 382: for (i = 0; i < EIMAX; i++) { ! 383: if (b_pause > Ltab[i].b) { ! 384: Ltab[i].b = b_pause; ! 385: Ltab[i].t = t_pause; ! 386: Ltab[i].f = label; ! 387: Ltab[i].e = e_pause; ! 388: break; ! 389: } else if (b_pause == Ltab[i].b) { ! 390: if (t_pause > Ltab[i].t) { ! 391: Ltab[i].t = t_pause; ! 392: Ltab[i].f = label; ! 393: Ltab[i].e = e_pause; ! 394: break; ! 395: } else if (t_pause == Ltab[i].t) { ! 396: break; ! 397: } ! 398: } ! 399: } ! 400: timing = 0; ! 401: } ! 402: ! 403: LOGLIST() ! 404: { ! 405: int i, printed = 0; ! 406: ! 407: for (i = 0; i < EIMAX; i++) ! 408: if (Ltab[i].t || Ltab[i].b) { ! 409: if (printed == 0) { ! 410: printf("\npsw=%x ", read_psw()); ! 411: printed = 1; ! 412: } ! 413: printf("f=%x b=%d t=%d e=%d ", ! 414: Ltab[i].f, Ltab[i].b, Ltab[i].t, Ltab[i].e); ! 415: Ltab[i].f = Ltab[i].b = Ltab[i].t = 0; ! 416: } else ! 417: break; ! 418: } ! 419: ! 420: LOGPAUSE() ! 421: { ! 422: if (!timing) ! 423: return; ! 424: if (!paused) { ! 425: b_pause += clocks + lbolt - b_in; ! 426: t_pause += (t_in - read_t0()); ! 427: if (t_pause < 0) ! 428: t_pause += 11932; ! 429: paused = 1; ! 430: } ! 431: } ! 432: ! 433: LOGRESUME() ! 434: { ! 435: if (!timing) ! 436: return; ! 437: if (paused) { ! 438: b_in = clocks + lbolt; ! 439: t_in = read_t0(); ! 440: paused = 0; ! 441: e_pause++; ! 442: } ! 443: } ! 444: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.