|
|
1.1 ! root 1: /* $Header: /x/usr/src/sys/coh/RCS/clock.c,v 1.2 91/06/20 14:12:44 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/uproc.h> ! 55: #include <sys/mdata.h> ! 56: ! 57: int (*altclk)(); /* pointer to higher-speed clock function */ ! 58: int altsel; /* if nonzero, CS for LOADABLE driver owning altclk() */ ! 59: ! 60: static int clocks; ! 61: ! 62: /* ! 63: * This routine is called once every tick (1/HZ seconds). ! 64: * It gets called with the programme counter that was interrupted ! 65: * a flag telling whether we were in user or kernel mode and the ! 66: * previous priority we were in. ! 67: */ ! 68: clock(pc, umode) ! 69: vaddr_t pc; ! 70: { ! 71: register PROC *pp; ! 72: /* ! 73: * Ignore clock interrupts till we are ready. ! 74: */ ! 75: if (batflag == 0) ! 76: return; ! 77: ! 78: /* ! 79: * Hook for alternate clock interrupt; ! 80: * Call polling function ("altclk") if there is one. ! 81: * ! 82: * For near function, "altsel" is 0 and "altclk" is offset. ! 83: * For far function, "altsel" is the CS selector and "altclk" ! 84: * is the offset. ! 85: * ! 86: * Since the polling function ends with a near rather than ! 87: * far return, far invocation is via ld_call() (ldas.s) which uses ! 88: * the despatch routine at CS:4 (ld.s) in any loadable driver. ! 89: */ ! 90: if (altclk) { ! 91: if (altsel) { /* will do far call to altclk fn */ ! 92: if (ld_call(altsel, altclk)) ! 93: return; ! 94: } else ! 95: if ((*altclk)()) ! 96: return; ! 97: } ! 98: ! 99: /* ! 100: * Update timers. Decrement time slice. ! 101: */ ! 102: utimer += 1; ! 103: clocks += 1; ! 104: timer.t_tick += 1; ! 105: quantum -= 1; ! 106: ! 107: /* ! 108: * Give processes their schedule values per tick. ! 109: */ ! 110: if (procq.p_lforw->p_cval > CVCLOCK) { ! 111: procq.p_lforw->p_cval -= CVCLOCK; ! 112: procq.p_cval += CVCLOCK; ! 113: } ! 114: ! 115: /* ! 116: * Tax current process and update his times. ! 117: */ ! 118: pp = SELF; ! 119: pp->p_cval >>= 1; ! 120: if (umode == 0) ! 121: pp->p_stime++; ! 122: else { ! 123: pp->p_utime++; ! 124: u.u_ppc = pc; ! 125: } ! 126: } ! 127: ! 128: /* ! 129: * Do everything the clock wanted to do but couldn't as it would have ! 130: * taken too long. ! 131: * Also perform any system bookkeeping required at regular intervals. ! 132: */ ! 133: stand() ! 134: { ! 135: int s; ! 136: ! 137: u.u_error = 0; ! 138: ! 139: /* ! 140: * Update the clock. ! 141: */ ! 142: while (timer.t_tick >= HZ) { ! 143: timer.t_time++; ! 144: timer.t_tick -= HZ; ! 145: outflag = 1; ! 146: } ! 147: ! 148: /* ! 149: * Check expiration of quantum. ! 150: */ ! 151: if (quantum <= 0) { ! 152: quantum = 0; ! 153: disflag = 1; ! 154: } ! 155: ! 156: /* ! 157: * Check the timed function queue if necessary. ! 158: */ ! 159: if ( clocks > 0 ) ! 160: do { ! 161: register TIM * np; ! 162: register TIM * tp; ! 163: ! 164: /* ! 165: * Update [serviced] clock ticks since startup. ! 166: */ ! 167: lbolt++; ! 168: ! 169: /* ! 170: * Remove timing list from queue, creating new temporary queue. ! 171: */ ! 172: tp = (TIM *) &timq[ lbolt % nel(timq) ]; ! 173: s = sphi(); ! 174: ! 175: /* ! 176: * Scan timing list. ! 177: */ ! 178: for ( np = tp->t_next; tp = np; ) { ! 179: ! 180: /* ! 181: * Remember next function in timing list. ! 182: * NOTE: Must be done before function is invoked, ! 183: * since it may start a new timer. ! 184: */ ! 185: np = tp->t_next; ! 186: ! 187: /* ! 188: * Function has not timed out: leave it on timing list. ! 189: */ ! 190: if ( tp->t_lbolt != lbolt ) ! 191: continue; ! 192: ! 193: /* ! 194: * Remove function from timing list. ! 195: */ ! 196: if ( tp->t_last->t_next = tp->t_next ) ! 197: tp->t_next->t_last = tp->t_last; ! 198: tp->t_last = NULL; ! 199: ! 200: /* ! 201: * Invoke function. ! 202: */ ! 203: spl(s); ! 204: (*tp->t_func)( tp->t_farg, tp ); ! 205: sphi(); ! 206: } ! 207: ! 208: spl( s ); ! 209: ! 210: } while ( --clocks > 0 ); ! 211: ! 212: /* ! 213: * Timeout any devices. ! 214: */ ! 215: if (outflag) { ! 216: register int n; ! 217: ! 218: outflag = 0; ! 219: for (n=0; n<drvn; n++) { ! 220: if (drvl[n].d_time == 0) ! 221: continue; ! 222: s = sphi(); ! 223: dtime((dev_t)makedev(n, 0)); ! 224: spl(s); ! 225: } ! 226: } ! 227: ! 228: /* ! 229: * Do profiling. ! 230: */ ! 231: if (u.u_pscale != 0) { ! 232: register unsigned p; ! 233: register vaddr_t a; ! 234: ! 235: p = u.u_pscale; ! 236: a = (int *)u.u_pbase + ! 237: pscale(u.u_ppc-u.u_pofft, p/sizeof (int)); ! 238: if (a < u.u_pbend) ! 239: putuwd(a, getuwd(a)+1); ! 240: } ! 241: ! 242: /* ! 243: * Check for signals and execute them. ! 244: */ ! 245: if (SELF->p_ssig) ! 246: actvsig(); ! 247: ! 248: /* ! 249: * Execute deferred functions. ! 250: */ ! 251: defend(); ! 252: ! 253: /* ! 254: * Should we dispatch? ! 255: */ ! 256: if ((SELF->p_flags&PFDISP) != 0) { ! 257: SELF->p_flags &= ~PFDISP; ! 258: disflag = 1; ! 259: if ( stimer.t_last != 0 ) ! 260: wakeup((char *)&stimer); ! 261: } ! 262: ! 263: #ifdef QWAKEUP ! 264: /* ! 265: * Dispatch pending wakeups. ! 266: */ ! 267: while (ntowake) ! 268: wakeup2(); ! 269: ! 270: #endif ! 271: /* ! 272: * Redispatch. ! 273: * This used to be a function call in tsave, ! 274: * expanded in line here. ! 275: */ ! 276: if (disflag) { ! 277: register PROC *pp; ! 278: ! 279: #ifndef QWAKEUP ! 280: s=sphi(); ! 281: #endif ! 282: if ((pp=SELF)!=iprocp) ! 283: setrun(pp); ! 284: dispatch(); ! 285: #ifndef QWAKEUP ! 286: spl(s); ! 287: #endif ! 288: } ! 289: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.