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