xref: /csrg-svn/sys/kern/kern_clock.c (revision 9)
1*9Sbill /*	kern_clock.c	3.1	10/14/12	*/
2*9Sbill 
3*9Sbill #include "../h/param.h"
4*9Sbill #include "../h/systm.h"
5*9Sbill #include "../h/callo.h"
6*9Sbill #include "../h/seg.h"
7*9Sbill #include "../h/dir.h"
8*9Sbill #include "../h/user.h"
9*9Sbill #include "../h/proc.h"
10*9Sbill #include "../h/reg.h"
11*9Sbill #include "../h/psl.h"
12*9Sbill #include "../h/vm.h"
13*9Sbill #include "../h/buf.h"
14*9Sbill #include "../h/text.h"
15*9Sbill 
16*9Sbill #define	SCHMAG	9/10
17*9Sbill 
18*9Sbill 
19*9Sbill /*
20*9Sbill  * clock is called straight from
21*9Sbill  * the real time clock interrupt.
22*9Sbill  *
23*9Sbill  * Functions:
24*9Sbill  *	implement callouts
25*9Sbill  *	maintain user/system times
26*9Sbill  *	maintain date
27*9Sbill  *	profile
28*9Sbill  *	lightning bolt wakeup (every second)
29*9Sbill  *	alarm clock signals
30*9Sbill  *	jab the scheduler
31*9Sbill  */
32*9Sbill #ifdef KPROF
33*9Sbill short	kcount[20000];
34*9Sbill #endif
35*9Sbill 
36*9Sbill clock(pc, ps)
37*9Sbill caddr_t pc;
38*9Sbill {
39*9Sbill 	register struct callo *p1, *p2;
40*9Sbill 	register struct proc *pp;
41*9Sbill 	register int s;
42*9Sbill 	int a;
43*9Sbill 
44*9Sbill 	/*
45*9Sbill 	 * reprime clock
46*9Sbill 	 */
47*9Sbill 	clkreld();
48*9Sbill 
49*9Sbill 	/*
50*9Sbill 	 * callouts
51*9Sbill 	 * else update first non-zero time
52*9Sbill 	 */
53*9Sbill 
54*9Sbill 	if(callout[0].c_func == NULL)
55*9Sbill 		goto out;
56*9Sbill 	p2 = &callout[0];
57*9Sbill 	while(p2->c_time<=0 && p2->c_func!=NULL)
58*9Sbill 		p2++;
59*9Sbill 	p2->c_time--;
60*9Sbill 
61*9Sbill 	/*
62*9Sbill 	 * if ps is high, just return
63*9Sbill 	 */
64*9Sbill 	if (BASEPRI(ps))
65*9Sbill 		goto out;
66*9Sbill 
67*9Sbill 	/*
68*9Sbill 	 * callout
69*9Sbill 	 */
70*9Sbill 
71*9Sbill 	if(callout[0].c_time <= 0) {
72*9Sbill 		p1 = &callout[0];
73*9Sbill 		while(p1->c_func != 0 && p1->c_time <= 0) {
74*9Sbill 			(*p1->c_func)(p1->c_arg);
75*9Sbill 			p1++;
76*9Sbill 		}
77*9Sbill 		p2 = &callout[0];
78*9Sbill 		while(p2->c_func = p1->c_func) {
79*9Sbill 			p2->c_time = p1->c_time;
80*9Sbill 			p2->c_arg = p1->c_arg;
81*9Sbill 			p1++;
82*9Sbill 			p2++;
83*9Sbill 		}
84*9Sbill 	}
85*9Sbill 
86*9Sbill 	/*
87*9Sbill 	 * lightning bolt time-out
88*9Sbill 	 * and time of day
89*9Sbill 	 */
90*9Sbill out:
91*9Sbill 	if (!noproc) {
92*9Sbill 		s = u.u_procp->p_rssize;
93*9Sbill 		u.u_vm.vm_idsrss += s;
94*9Sbill 		if (u.u_procp->p_textp) {
95*9Sbill 			register int xrss = u.u_procp->p_textp->x_rssize;
96*9Sbill 
97*9Sbill 			s += xrss;
98*9Sbill 			u.u_vm.vm_ixrss += xrss;
99*9Sbill 		}
100*9Sbill 		if (s > u.u_vm.vm_maxrss)
101*9Sbill 			u.u_vm.vm_maxrss = s;
102*9Sbill 	}
103*9Sbill 	a = dk_busy&07;
104*9Sbill 	if (USERMODE(ps)) {
105*9Sbill 		u.u_vm.vm_utime++;
106*9Sbill 		if(u.u_procp->p_nice > NZERO)
107*9Sbill 			a += 8;
108*9Sbill 	} else {
109*9Sbill 		a += 16;
110*9Sbill 		if (noproc)
111*9Sbill 			a += 8;
112*9Sbill 		else
113*9Sbill 			u.u_vm.vm_stime++;
114*9Sbill 	}
115*9Sbill 	dk_time[a]++;
116*9Sbill 	if (!noproc) {
117*9Sbill 		pp = u.u_procp;
118*9Sbill 		if(++pp->p_cpu == 0)
119*9Sbill 			pp->p_cpu--;
120*9Sbill 		if(pp->p_cpu % 16 == 0) {
121*9Sbill 			VOID setpri(pp);
122*9Sbill 			if (pp->p_pri >= PUSER)
123*9Sbill 				pp->p_pri = pp->p_usrpri;
124*9Sbill 		}
125*9Sbill 	}
126*9Sbill 	++lbolt;
127*9Sbill 	if (lbolt % (HZ/4) == 0) {
128*9Sbill 		vmpago();
129*9Sbill 		runrun++;
130*9Sbill 	}
131*9Sbill 	if (lbolt >= HZ) {
132*9Sbill 		if (BASEPRI(ps))
133*9Sbill 			return;
134*9Sbill 		lbolt -= HZ;
135*9Sbill 		++time;
136*9Sbill 		VOID spl1();
137*9Sbill 		runrun++;
138*9Sbill 		wakeup((caddr_t)&lbolt);
139*9Sbill 		for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
140*9Sbill 		if (pp->p_stat && pp->p_stat<SZOMB) {
141*9Sbill 			if(pp->p_time != 127)
142*9Sbill 				pp->p_time++;
143*9Sbill 			if(pp->p_clktim)
144*9Sbill 				if(--pp->p_clktim == 0)
145*9Sbill 					psignal(pp, SIGCLK);
146*9Sbill 			if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
147*9Sbill 				if (pp->p_slptime != 127)
148*9Sbill 					pp->p_slptime++;
149*9Sbill 			if(pp->p_flag&SLOAD) {
150*9Sbill 				ave(pp->p_aveflt, pp->p_faults, 5);
151*9Sbill 				pp->p_faults = 0;
152*9Sbill 			}
153*9Sbill 			a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
154*9Sbill 			if(a < 0)
155*9Sbill 				a = 0;
156*9Sbill 			if(a > 255)
157*9Sbill 				a = 255;
158*9Sbill 			pp->p_cpu = a;
159*9Sbill 			VOID setpri(pp);
160*9Sbill 			s = spl6();
161*9Sbill 			if(pp->p_pri >= PUSER) {
162*9Sbill 				if ((pp != u.u_procp || noproc) &&
163*9Sbill 				    pp->p_stat == SRUN &&
164*9Sbill 				    (pp->p_flag & SLOAD) &&
165*9Sbill 				    pp->p_pri != pp->p_usrpri) {
166*9Sbill 					remrq(pp);
167*9Sbill 					pp->p_pri = pp->p_usrpri;
168*9Sbill 					setrq(pp);
169*9Sbill 				} else
170*9Sbill 					pp->p_pri = pp->p_usrpri;
171*9Sbill 			}
172*9Sbill 			splx(s);
173*9Sbill 		}
174*9Sbill 		vmmeter();
175*9Sbill 		if(runin!=0) {
176*9Sbill 			runin = 0;
177*9Sbill 			wakeup((caddr_t)&runin);
178*9Sbill 		}
179*9Sbill 		/*
180*9Sbill 		 * If there are pages that have been cleaned,
181*9Sbill 		 * jolt the pageout daemon to process them.
182*9Sbill 		 * We do this here so that these pages will be
183*9Sbill 		 * freed if there is an abundance of memory and the
184*9Sbill 		 * daemon would not be awakened otherwise.
185*9Sbill 		 */
186*9Sbill 		if (bclnlist != NULL)
187*9Sbill 			wakeup((caddr_t)&proc[2]);
188*9Sbill #ifdef ERNIE
189*9Sbill 		if (USERMODE(ps)) {
190*9Sbill 			pp = u.u_procp;
191*9Sbill 			if (pp->p_uid)
192*9Sbill 				if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
193*9Sbill 					pp->p_nice = NZERO+4;
194*9Sbill 			VOID setpri(pp);
195*9Sbill 			pp->p_pri = pp->p_usrpri;
196*9Sbill 		}
197*9Sbill #endif
198*9Sbill 	}
199*9Sbill 	if (USERMODE(ps)) {
200*9Sbill 		/*
201*9Sbill 		 * We do this last since it
202*9Sbill 		 * may block on a page fault in user space.
203*9Sbill 		 */
204*9Sbill 		if (u.u_prof.pr_scale)
205*9Sbill 			addupc(pc, &u.u_prof, 1);
206*9Sbill 	}
207*9Sbill #ifdef KPROF
208*9Sbill 	else if (!noproc) {
209*9Sbill 		register int indx = ((int)pc & 0x7fffffff) / 8;
210*9Sbill 
211*9Sbill 		if (indx >= 0 && indx < 20000)
212*9Sbill 			kcount[indx]++;
213*9Sbill 	}
214*9Sbill #endif
215*9Sbill }
216*9Sbill 
217*9Sbill /*
218*9Sbill  * timeout is called to arrange that
219*9Sbill  * fun(arg) is called in tim/HZ seconds.
220*9Sbill  * An entry is sorted into the callout
221*9Sbill  * structure. The time in each structure
222*9Sbill  * entry is the number of HZ's more
223*9Sbill  * than the previous entry.
224*9Sbill  * In this way, decrementing the
225*9Sbill  * first entry has the effect of
226*9Sbill  * updating all entries.
227*9Sbill  *
228*9Sbill  * The panic is there because there is nothing
229*9Sbill  * intelligent to be done if an entry won't fit.
230*9Sbill  */
231*9Sbill timeout(fun, arg, tim)
232*9Sbill int (*fun)();
233*9Sbill caddr_t arg;
234*9Sbill {
235*9Sbill 	register struct callo *p1, *p2;
236*9Sbill 	register int t;
237*9Sbill 	int s;
238*9Sbill 
239*9Sbill 	t = tim;
240*9Sbill 	p1 = &callout[0];
241*9Sbill 	s = spl7();
242*9Sbill 	while(p1->c_func != 0 && p1->c_time <= t) {
243*9Sbill 		t -= p1->c_time;
244*9Sbill 		p1++;
245*9Sbill 	}
246*9Sbill 	if (p1 >= &callout[NCALL-1])
247*9Sbill 		panic("Timeout table overflow");
248*9Sbill 	p1->c_time -= t;
249*9Sbill 	p2 = p1;
250*9Sbill 	while(p2->c_func != 0)
251*9Sbill 		p2++;
252*9Sbill 	while(p2 >= p1) {
253*9Sbill 		(p2+1)->c_time = p2->c_time;
254*9Sbill 		(p2+1)->c_func = p2->c_func;
255*9Sbill 		(p2+1)->c_arg = p2->c_arg;
256*9Sbill 		p2--;
257*9Sbill 	}
258*9Sbill 	p1->c_time = t;
259*9Sbill 	p1->c_func = fun;
260*9Sbill 	p1->c_arg = arg;
261*9Sbill 	splx(s);
262*9Sbill }
263