|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/meter.h"
4: #include "sys/callout.h"
5: #include "sys/user.h"
6: #include "sys/proc.h"
7: #include "sys/psl.h"
8: #include "sys/vm.h"
9: #include "sys/buf.h"
10: #include "sys/text.h"
11: #include "sys/vlimit.h"
12: #include "sys/mtpr.h"
13: #include "sys/clock.h"
14:
15: int queueflag;
16:
17: /*
18: * trivial kernel profiling; quite expensive in space
19: */
20: #define KMAX (200*1024) /* max kernel text */
21: #define KPSIZE (50*256) /* number of buckets */
22: #define KPROF 1
23: #if KPROF
24: long kprof[KPSIZE];
25: #endif
26:
27:
28: /*
29: * Hardclock is called straight from
30: * the real time clock interrupt.
31: * We limit the work we do at real clock interrupt time to:
32: * reloading clock
33: * decrementing time to callouts
34: * recording cpu time usage
35: * modifying priority of current process
36: * arrange for soft clock interrupt
37: * kernel pc profiling
38: *
39: * At software (softclock) interrupt time we:
40: * implement callouts
41: * maintain date
42: * lightning bolt wakeup (every second)
43: * alarm clock signals
44: * jab the scheduler
45: *
46: * On the vax softclock interrupts are implemented by
47: * software interrupts. Note that we may have multiple softclock
48: * interrupts compressed into one (due to excessive interrupt load),
49: * but that hardclock interrupts should never be lost.
50: */
51: /*ARGSUSED*/
52: hardclock(pc, ps)
53: caddr_t pc;
54: {
55: register struct callout *p1;
56: register struct proc *pp;
57: register int s, cpstate;
58:
59: /*
60: * reprime clock
61: */
62: clkreld();
63:
64: /*
65: * update callout times
66: */
67: for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next)
68: ;
69: if (p1)
70: p1->c_time--;
71: pp = u.u_procp;
72: if (USERMODE(ps)) {
73: u.u_vm.vm_utime++;
74: if (pp->p_nice > NZERO)
75: cpstate = CP_NICE;
76: else
77: cpstate = CP_USER;
78: s = 1;
79: } else {
80: #if KPROF
81: s = (long)pc - KSTART;
82: if (s < 0)
83: s = 0; /* shouldn't */
84: else if (s >= KMAX)
85: s = KMAX - 1;
86: s /= KMAX/KPSIZE;
87: kprof[s]++;
88: #endif
89: cpstate = CP_SYS;
90: if (queueflag) {
91: cpstate = CP_QUEUE;
92: s = 0;
93: } else if (noproc) {
94: if (BASEPRI(ps) == 0)
95: cpstate = CP_IDLE;
96: s = 0;
97: } else {
98: u.u_vm.vm_stime++;
99: s = 1;
100: }
101: }
102: cp_time[cpstate]++;
103: /*
104: * Adjust priority of current process.
105: */
106: if (s) {
107: pp->p_cpticks++;
108: if(++pp->p_cpu == 0)
109: --pp->p_cpu;
110: }
111: ++lbolt;
112: setsoftclock();
113: }
114:
115: #define cpuave(a,b) ((int)(((int)((a)*(b)))/((b)+1)))
116: extern double avenrun[];
117: /*
118: * Constant for decay filter for cpu usage field
119: * in process table (used by ps au).
120: */
121: static float ccpu = 0.9512294245; /* exp(-1/20) */
122:
123: /*
124: * Software clock interrupt.
125: * This routine runs at lower priority than device interrupts.
126: *
127: * Processes have their (32-bit) priority depend on their owner's ``normalised
128: * usage'' of resources. However, V9's low-level scheduler only has 127 priorities,
129: * (in fact, only 32, so that someone could use an 'ffs' instruction),
130: * so we normalise this ``sharepri'' into the 7-bit ``usrpri''. Note that
131: * the 'ffs' hack means that (after PUSER) there are only 20 real priorities
132: * for processes to run in, and that defined kernel priorities should differ
133: * by more than 4 to be meaningful.
134: */
135: /*ARGSUSED*/
136: softclock(pc, ps)
137: caddr_t pc;
138: {
139: register struct callout *p1;
140: register struct proc *pp;
141: register int a, s;
142: extern char *panicstr;
143:
144: /*
145: * Perform callouts (but not after panics)
146: */
147: if (panicstr == 0) {
148: for (;;) {
149: register caddr_t arg;
150: register int (*func)();
151:
152: s = spl7();
153: if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) {
154: splx(s);
155: break;
156: }
157: calltodo.c_next = p1->c_next;
158: arg = p1->c_arg;
159: func = p1->c_func;
160: p1->c_next = callfree;
161: callfree = p1;
162: (void) splx(s);
163: (*func)(arg);
164: }
165: }
166:
167: /*
168: * If idling and processes are waiting to swap in,
169: * check on them.
170: */
171: if (noproc && runin) {
172: runin = 0;
173: wakeup((caddr_t)&runin);
174: }
175: if (lbolt % (HZ/10) == 0) {
176: runrun++;
177: aston();
178: }
179:
180: /*
181: * Lightning bolt every second:
182: * sleep timeouts
183: * process priority recomputation
184: * process %cpu averaging
185: * p_time and p_slptime for the swapper
186: * kick swapper if processes want in
187: */
188: if (lbolt >= HZ) {
189: /* meaningless on VAX; meant for hardclock */
190: if (BASEPRI(ps))
191: return;
192: time += lbolt / HZ;
193: lbolt %= HZ;
194: wakeup((caddr_t)&lbolt);
195: for (pp = proc; pp < procNPROC; pp++)
196: if ((a=pp->p_stat)!=0 && a!=SZOMB) {
197: if (pp->p_time != 127)
198: pp->p_time++;
199: if (pp->p_clktim && --pp->p_clktim == 0)
200: psignal(pp, SIGALRM);
201: if (pp->p_tsleep && --pp->p_tsleep == 0) {
202: s = spl6();
203: switch (pp->p_stat) { /* != a if interrupted */
204:
205: case SSLEEP:
206: setrun(pp);
207: break;
208:
209: case SSTOP:
210: unsleep(pp);
211: break;
212: }
213: pp->p_flag |= STIMO;
214: splx(s);
215: }
216: if (a==SSLEEP || a==SSTOP)
217: if (pp->p_slptime != 127)
218: pp->p_slptime++;
219: /*
220: * update silly numbers for ps to print
221: */
222: if (pp->p_flag&SLOAD)
223: pp->p_pctcpu = ccpu*pp->p_pctcpu +
224: (1.0 - ccpu) * (pp->p_cpticks/(float)HZ);
225: pp->p_cpticks = 0;
226:
227: /*
228: * Update p_cpu for scheduling
229: */
230: a = cpuave(pp->p_cpu, 2*avenrun[0]);
231: if (a < 0)
232: a = 0;
233: if (a > 255)
234: a = 255;
235: pp->p_cpu = a;
236: (void) setpri(pp);
237: /*
238: * p_usrpri == new process priority
239: * now fix p_pri to match, carefully
240: */
241: s = spl6();
242: if (pp->p_pri >= PUSER && pp->p_pri != pp->p_usrpri) {
243: if ((pp != u.u_procp || noproc) && pp->p_stat == SRUN &&
244: (pp->p_flag & SLOAD)) {
245: remrq(pp);
246: pp->p_pri = pp->p_usrpri;
247: setrq(pp);
248: } else
249: pp->p_pri = pp->p_usrpri;
250: }
251: splx(s);
252: }
253: if (runin!=0) {
254: runin = 0;
255: wakeup((caddr_t)&runin);
256: }
257: }
258: if (noproc)
259: return;
260: pp = u.u_procp;
261: /*
262: * If trapped user-mode, give it a profiling tick.
263: */
264: if (USERMODE(ps) && u.u_prof.pr_scale) {
265: pp->p_flag |= SOWEUPC;
266: aston();
267: }
268: /*
269: * random statistics, apparently computed just so
270: * that programs like ps can print them? not a good reason
271: */
272: s = pp->p_rssize;
273: u.u_vm.vm_idsrss += s;
274: if (pp->p_textp) {
275: a = pp->p_textp->x_rssize;
276: s += a;
277: u.u_vm.vm_ixrss += a;
278: }
279: if (s > u.u_vm.vm_maxrss)
280: u.u_vm.vm_maxrss = s;
281: /*
282: * cpu time limit
283: */
284: if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) {
285: psignal(pp, SIGXCPU);
286: if (u.u_limit[LIM_CPU] < INFINITY - 5)
287: u.u_limit[LIM_CPU] += 5;
288: }
289: }
290:
291: /*
292: * Timeout is called to arrange that
293: * fun(arg) is called in tim/HZ seconds.
294: * An entry is linked into the callout
295: * structure. The time in each structure
296: * entry is the number of HZ's more
297: * than the previous entry.
298: * In this way, decrementing the
299: * first entry has the effect of
300: * updating all entries.
301: *
302: * The panic is there because there is nothing
303: * intelligent to be done if an entry won't fit.
304: */
305: timeout(fun, arg, tim)
306: int (*fun)();
307: caddr_t arg;
308: {
309: register struct callout *p1, *p2, *pnew;
310: register int t;
311: int s;
312:
313: t = tim;
314: s = spl7();
315: pnew = callfree;
316: if (pnew == NULL)
317: panic("timeout table overflow");
318: callfree = pnew->c_next;
319: pnew->c_arg = arg;
320: pnew->c_func = fun;
321: for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2)
322: t -= p2->c_time;
323: p1->c_next = pnew;
324: pnew->c_next = p2;
325: pnew->c_time = t;
326: if (p2)
327: p2->c_time -= t;
328: splx(s);
329: }
330:
331: /*
332: * Delay goes to sleep on a unique address for a
333: * guaranteed minimum period ticks/HZ secs.
334: * Because a timeout() can't be cancelled, the process
335: * will be unkillable while asleep. Beware of giving
336: * delay() an argument of more than a few hundred.
337: *
338: * used by one device driver and by sys nap.
339: * do we really need it?
340: */
341: delay(ticks)
342: {
343: register int x;
344: extern wakeup();
345:
346: if (ticks<=0)
347: return;
348: x = spl7();
349: timeout(wakeup, (caddr_t)u.u_procp+1, ticks);
350: sleep((caddr_t)u.u_procp+1, PZERO-1);
351: splx(x);
352: }
353:
354: /*
355: * init callouts
356: * called from main
357: */
358:
359: callinit()
360: {
361: register int i;
362:
363: callfree = callout;
364: for (i = 1; i < calloutcnt; i++)
365: callout[i-1].c_next = &callout[i];
366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.