xref: /csrg-svn/sys/kern/kern_clock.c (revision 101)
1*101Sbill /*	kern_clock.c	3.2	10/14/12	*/
29Sbill 
39Sbill #include "../h/param.h"
49Sbill #include "../h/systm.h"
59Sbill #include "../h/callo.h"
69Sbill #include "../h/seg.h"
79Sbill #include "../h/dir.h"
89Sbill #include "../h/user.h"
99Sbill #include "../h/proc.h"
109Sbill #include "../h/reg.h"
119Sbill #include "../h/psl.h"
129Sbill #include "../h/vm.h"
139Sbill #include "../h/buf.h"
149Sbill #include "../h/text.h"
159Sbill 
169Sbill #define	SCHMAG	9/10
179Sbill 
189Sbill 
199Sbill /*
209Sbill  * clock is called straight from
219Sbill  * the real time clock interrupt.
229Sbill  *
239Sbill  * Functions:
249Sbill  *	implement callouts
259Sbill  *	maintain user/system times
269Sbill  *	maintain date
279Sbill  *	profile
289Sbill  *	lightning bolt wakeup (every second)
299Sbill  *	alarm clock signals
309Sbill  *	jab the scheduler
319Sbill  */
329Sbill #ifdef KPROF
339Sbill short	kcount[20000];
349Sbill #endif
359Sbill 
369Sbill clock(pc, ps)
379Sbill caddr_t pc;
389Sbill {
399Sbill 	register struct callo *p1, *p2;
409Sbill 	register struct proc *pp;
419Sbill 	register int s;
429Sbill 	int a;
439Sbill 
449Sbill 	/*
459Sbill 	 * reprime clock
469Sbill 	 */
479Sbill 	clkreld();
489Sbill 
499Sbill 	/*
509Sbill 	 * callouts
519Sbill 	 * else update first non-zero time
529Sbill 	 */
539Sbill 
549Sbill 	if(callout[0].c_func == NULL)
559Sbill 		goto out;
569Sbill 	p2 = &callout[0];
579Sbill 	while(p2->c_time<=0 && p2->c_func!=NULL)
589Sbill 		p2++;
599Sbill 	p2->c_time--;
609Sbill 
619Sbill 	/*
629Sbill 	 * if ps is high, just return
639Sbill 	 */
649Sbill 	if (BASEPRI(ps))
659Sbill 		goto out;
669Sbill 
679Sbill 	/*
689Sbill 	 * callout
699Sbill 	 */
709Sbill 
719Sbill 	if(callout[0].c_time <= 0) {
729Sbill 		p1 = &callout[0];
739Sbill 		while(p1->c_func != 0 && p1->c_time <= 0) {
749Sbill 			(*p1->c_func)(p1->c_arg);
759Sbill 			p1++;
769Sbill 		}
779Sbill 		p2 = &callout[0];
789Sbill 		while(p2->c_func = p1->c_func) {
799Sbill 			p2->c_time = p1->c_time;
809Sbill 			p2->c_arg = p1->c_arg;
819Sbill 			p1++;
829Sbill 			p2++;
839Sbill 		}
849Sbill 	}
859Sbill 
869Sbill 	/*
879Sbill 	 * lightning bolt time-out
889Sbill 	 * and time of day
899Sbill 	 */
909Sbill out:
919Sbill 	if (!noproc) {
929Sbill 		s = u.u_procp->p_rssize;
939Sbill 		u.u_vm.vm_idsrss += s;
949Sbill 		if (u.u_procp->p_textp) {
959Sbill 			register int xrss = u.u_procp->p_textp->x_rssize;
969Sbill 
979Sbill 			s += xrss;
989Sbill 			u.u_vm.vm_ixrss += xrss;
999Sbill 		}
1009Sbill 		if (s > u.u_vm.vm_maxrss)
1019Sbill 			u.u_vm.vm_maxrss = s;
1029Sbill 	}
1039Sbill 	a = dk_busy&07;
1049Sbill 	if (USERMODE(ps)) {
1059Sbill 		u.u_vm.vm_utime++;
1069Sbill 		if(u.u_procp->p_nice > NZERO)
1079Sbill 			a += 8;
1089Sbill 	} else {
1099Sbill 		a += 16;
1109Sbill 		if (noproc)
1119Sbill 			a += 8;
1129Sbill 		else
1139Sbill 			u.u_vm.vm_stime++;
1149Sbill 	}
1159Sbill 	dk_time[a]++;
1169Sbill 	if (!noproc) {
1179Sbill 		pp = u.u_procp;
1189Sbill 		if(++pp->p_cpu == 0)
1199Sbill 			pp->p_cpu--;
1209Sbill 		if(pp->p_cpu % 16 == 0) {
1219Sbill 			VOID setpri(pp);
1229Sbill 			if (pp->p_pri >= PUSER)
1239Sbill 				pp->p_pri = pp->p_usrpri;
1249Sbill 		}
1259Sbill 	}
1269Sbill 	++lbolt;
1279Sbill 	if (lbolt % (HZ/4) == 0) {
1289Sbill 		vmpago();
1299Sbill 		runrun++;
1309Sbill 	}
1319Sbill 	if (lbolt >= HZ) {
1329Sbill 		if (BASEPRI(ps))
1339Sbill 			return;
1349Sbill 		lbolt -= HZ;
1359Sbill 		++time;
1369Sbill 		VOID spl1();
1379Sbill 		runrun++;
1389Sbill 		wakeup((caddr_t)&lbolt);
1399Sbill 		for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
1409Sbill 		if (pp->p_stat && pp->p_stat<SZOMB) {
1419Sbill 			if(pp->p_time != 127)
1429Sbill 				pp->p_time++;
1439Sbill 			if(pp->p_clktim)
1449Sbill 				if(--pp->p_clktim == 0)
145*101Sbill 					if (pp->p_flag & STIMO) {
146*101Sbill 						s = spl6();
147*101Sbill 						if (pp->p_stat == SSLEEP)
148*101Sbill 							setrun(pp);
149*101Sbill 						pp->p_flag &= ~STIMO;
150*101Sbill 						splx(s);
151*101Sbill 					} else
152*101Sbill 						psignal(pp, SIGCLK);
1539Sbill 			if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
1549Sbill 				if (pp->p_slptime != 127)
1559Sbill 					pp->p_slptime++;
1569Sbill 			if(pp->p_flag&SLOAD) {
1579Sbill 				ave(pp->p_aveflt, pp->p_faults, 5);
1589Sbill 				pp->p_faults = 0;
1599Sbill 			}
1609Sbill 			a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
1619Sbill 			if(a < 0)
1629Sbill 				a = 0;
1639Sbill 			if(a > 255)
1649Sbill 				a = 255;
1659Sbill 			pp->p_cpu = a;
1669Sbill 			VOID setpri(pp);
1679Sbill 			s = spl6();
1689Sbill 			if(pp->p_pri >= PUSER) {
1699Sbill 				if ((pp != u.u_procp || noproc) &&
1709Sbill 				    pp->p_stat == SRUN &&
1719Sbill 				    (pp->p_flag & SLOAD) &&
1729Sbill 				    pp->p_pri != pp->p_usrpri) {
1739Sbill 					remrq(pp);
1749Sbill 					pp->p_pri = pp->p_usrpri;
1759Sbill 					setrq(pp);
1769Sbill 				} else
1779Sbill 					pp->p_pri = pp->p_usrpri;
1789Sbill 			}
1799Sbill 			splx(s);
1809Sbill 		}
1819Sbill 		vmmeter();
1829Sbill 		if(runin!=0) {
1839Sbill 			runin = 0;
1849Sbill 			wakeup((caddr_t)&runin);
1859Sbill 		}
1869Sbill 		/*
1879Sbill 		 * If there are pages that have been cleaned,
1889Sbill 		 * jolt the pageout daemon to process them.
1899Sbill 		 * We do this here so that these pages will be
1909Sbill 		 * freed if there is an abundance of memory and the
1919Sbill 		 * daemon would not be awakened otherwise.
1929Sbill 		 */
1939Sbill 		if (bclnlist != NULL)
1949Sbill 			wakeup((caddr_t)&proc[2]);
1959Sbill #ifdef ERNIE
1969Sbill 		if (USERMODE(ps)) {
1979Sbill 			pp = u.u_procp;
1989Sbill 			if (pp->p_uid)
1999Sbill 				if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
2009Sbill 					pp->p_nice = NZERO+4;
2019Sbill 			VOID setpri(pp);
2029Sbill 			pp->p_pri = pp->p_usrpri;
2039Sbill 		}
2049Sbill #endif
2059Sbill 	}
2069Sbill 	if (USERMODE(ps)) {
2079Sbill 		/*
2089Sbill 		 * We do this last since it
2099Sbill 		 * may block on a page fault in user space.
2109Sbill 		 */
2119Sbill 		if (u.u_prof.pr_scale)
2129Sbill 			addupc(pc, &u.u_prof, 1);
2139Sbill 	}
2149Sbill #ifdef KPROF
2159Sbill 	else if (!noproc) {
2169Sbill 		register int indx = ((int)pc & 0x7fffffff) / 8;
2179Sbill 
2189Sbill 		if (indx >= 0 && indx < 20000)
2199Sbill 			kcount[indx]++;
2209Sbill 	}
2219Sbill #endif
2229Sbill }
2239Sbill 
2249Sbill /*
2259Sbill  * timeout is called to arrange that
2269Sbill  * fun(arg) is called in tim/HZ seconds.
2279Sbill  * An entry is sorted into the callout
2289Sbill  * structure. The time in each structure
2299Sbill  * entry is the number of HZ's more
2309Sbill  * than the previous entry.
2319Sbill  * In this way, decrementing the
2329Sbill  * first entry has the effect of
2339Sbill  * updating all entries.
2349Sbill  *
2359Sbill  * The panic is there because there is nothing
2369Sbill  * intelligent to be done if an entry won't fit.
2379Sbill  */
2389Sbill timeout(fun, arg, tim)
2399Sbill int (*fun)();
2409Sbill caddr_t arg;
2419Sbill {
2429Sbill 	register struct callo *p1, *p2;
2439Sbill 	register int t;
2449Sbill 	int s;
2459Sbill 
2469Sbill 	t = tim;
2479Sbill 	p1 = &callout[0];
2489Sbill 	s = spl7();
2499Sbill 	while(p1->c_func != 0 && p1->c_time <= t) {
2509Sbill 		t -= p1->c_time;
2519Sbill 		p1++;
2529Sbill 	}
2539Sbill 	if (p1 >= &callout[NCALL-1])
2549Sbill 		panic("Timeout table overflow");
2559Sbill 	p1->c_time -= t;
2569Sbill 	p2 = p1;
2579Sbill 	while(p2->c_func != 0)
2589Sbill 		p2++;
2599Sbill 	while(p2 >= p1) {
2609Sbill 		(p2+1)->c_time = p2->c_time;
2619Sbill 		(p2+1)->c_func = p2->c_func;
2629Sbill 		(p2+1)->c_arg = p2->c_arg;
2639Sbill 		p2--;
2649Sbill 	}
2659Sbill 	p1->c_time = t;
2669Sbill 	p1->c_func = fun;
2679Sbill 	p1->c_arg = arg;
2689Sbill 	splx(s);
2699Sbill }
270