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