xref: /csrg-svn/sys/kern/kern_clock.c (revision 8112)
1*8112Sroot /*	kern_clock.c	4.39	82/09/08	*/
29Sbill 
39Sbill #include "../h/param.h"
49Sbill #include "../h/systm.h"
5329Sbill #include "../h/dk.h"
62768Swnj #include "../h/callout.h"
79Sbill #include "../h/dir.h"
89Sbill #include "../h/user.h"
98028Sroot #include "../h/kernel.h"
109Sbill #include "../h/proc.h"
119Sbill #include "../h/psl.h"
129Sbill #include "../h/vm.h"
139Sbill #include "../h/text.h"
147490Skre #ifdef MUSH
157490Skre #include "../h/quota.h"
167490Skre #include "../h/share.h"
177490Skre #endif
189Sbill 
191943Swnj #include "dh.h"
201943Swnj #include "dz.h"
217305Ssam #include "ps.h"
221559Sbill 
237388Sroot #ifdef GPROF
247388Sroot extern	int profiling;
257388Sroot extern	char *s_lowpc;
267388Sroot extern	u_long s_textsize;
277388Sroot extern	u_short *kcount;
284968Swnj #endif
299Sbill 
308097Sroot #define	bumptime(tp)	\
318097Sroot 	(tp)->tv_usec += tick; \
328097Sroot 	if ((tp)->tv_usec >= 1000000) { \
338097Sroot 		(tp)->tv_usec -= 1000000; \
348097Sroot 		(tp)->tv_sec++; \
358097Sroot 	}
365247Sroot 
372609Swnj /*ARGSUSED*/
382442Swnj hardclock(pc, ps)
392450Swnj 	caddr_t pc;
409Sbill {
412768Swnj 	register struct callout *p1;
428097Sroot 	register struct proc *p;
432442Swnj 	register int s, cpstate;
447490Skre 	extern double avenrun[];
459Sbill 
467305Ssam #if NPS > 0
477305Ssam 	psextsync(pc, ps);
487305Ssam #endif
497305Ssam 
508097Sroot /* update callout times */
513542Swnj 	for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next)
52*8112Sroot 		--p1->c_time;
533542Swnj 	if (p1)
54*8112Sroot 		--p1->c_time;
55138Sbill 
568097Sroot /* charge process for resource usage... statistically! */
579Sbill 	if (!noproc) {
589Sbill 		s = u.u_procp->p_rssize;
598097Sroot 		u.u_ru.ru_idrss += s; u.u_ru.ru_isrss += 0;	/* XXX */
609Sbill 		if (u.u_procp->p_textp) {
619Sbill 			register int xrss = u.u_procp->p_textp->x_rssize;
629Sbill 
639Sbill 			s += xrss;
648028Sroot 			u.u_ru.ru_ixrss += xrss;
659Sbill 		}
668028Sroot 		if (s > u.u_ru.ru_maxrss)
678028Sroot 			u.u_ru.ru_maxrss = s;
688028Sroot 		if ((u.u_ru.ru_utime.tv_sec+u.u_ru.ru_stime.tv_sec+1) >
698028Sroot 		    u.u_rlimit[RLIMIT_CPU].rlim_cur) {
70375Sbill 			psignal(u.u_procp, SIGXCPU);
718028Sroot 			if (u.u_rlimit[RLIMIT_CPU].rlim_cur <
728028Sroot 			    u.u_rlimit[RLIMIT_CPU].rlim_max)
738028Sroot 				u.u_rlimit[RLIMIT_CPU].rlim_cur += 5;
74375Sbill 		}
758097Sroot 		if (timerisset(&u.u_timer[ITIMER_PROF].it_value) &&
768097Sroot 		    itimerdecr(&u.u_timer[ITIMER_PROF], tick) == 0)
778097Sroot 			psignal(u.u_procp, SIGPROF);
789Sbill 	}
798097Sroot 
808097Sroot /* charge for cpu */
819Sbill 	if (USERMODE(ps)) {
828097Sroot 		bumptime(&u.u_ru.ru_utime);
838097Sroot 		if (timerisset(&u.u_timer[ITIMER_VIRTUAL].it_value) &&
848097Sroot 		    itimerdecr(&u.u_timer[ITIMER_VIRTUAL], tick) == 0)
858097Sroot 			psignal(u.u_procp, SIGVTALRM);
868028Sroot 		if (u.u_procp->p_nice > NZERO)
87305Sbill 			cpstate = CP_NICE;
88305Sbill 		else
89305Sbill 			cpstate = CP_USER;
909Sbill 	} else {
917388Sroot #ifdef GPROF
927388Sroot 		int k = pc - s_lowpc;
937388Sroot 		if (profiling < 2 && k < s_textsize)
947388Sroot 			kcount[k / sizeof (*kcount)]++;
954968Swnj #endif
96305Sbill 		cpstate = CP_SYS;
977315Ssam 		if (noproc) {
987315Ssam 			if ((ps&PSL_IPL) != 0)
997315Ssam 				cpstate = CP_IDLE;
1008028Sroot 		} else {
1018097Sroot 			bumptime(&u.u_ru.ru_stime);
1028028Sroot 		}
1039Sbill 	}
1048097Sroot 
1058097Sroot /* iostat statistics */
1061408Sbill 	cp_time[cpstate]++;
1072442Swnj 	for (s = 0; s < DK_NDRIVE; s++)
1082442Swnj 		if (dk_busy&(1<<s))
1092442Swnj 			dk_time[s]++;
1108097Sroot 
1118097Sroot /* adjust priority of current process */
1129Sbill 	if (!noproc) {
1138097Sroot 		p = u.u_procp;
1148097Sroot 		p->p_cpticks++;
1158097Sroot 		if (++p->p_cpu == 0)
1168097Sroot 			p->p_cpu--;
1177490Skre #ifdef MUSH
1188097Sroot 		p->p_quota->q_cost += (p->p_nice > NZERO ?
1198097Sroot 		    (shconsts.sc_tic * ((2*NZERO)-p->p_nice)) / NZERO :
1207490Skre 		    shconsts.sc_tic) * (((int)avenrun[0]+2)/3);
1217490Skre #endif
1228097Sroot 		if (p->p_cpu % 4 == 0) {
1238097Sroot 			(void) setpri(p);
1248097Sroot 			if (p->p_pri >= PUSER)
1258097Sroot 				p->p_pri = p->p_usrpri;
1269Sbill 		}
1279Sbill 	}
1288097Sroot 	bumptime(&time);
1292442Swnj 	setsoftclock();
1302442Swnj }
1312442Swnj 
1322609Swnj /*ARGSUSED*/
1332442Swnj softclock(pc, ps)
1342450Swnj 	caddr_t pc;
1352442Swnj {
1363615Sroot 	register struct callout *p1;
1372442Swnj 	register int a, s;
1383542Swnj 	caddr_t arg;
1393542Swnj 	int (*func)();
1402442Swnj 
1418097Sroot 	if (panicstr)
1428097Sroot 		goto nocallout;
1438097Sroot 	for (;;) {
1448097Sroot 		s = spl7();
1458097Sroot 		if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) {
1468097Sroot 			splx(s);
1478097Sroot 			break;
1482442Swnj 		}
1498097Sroot 		calltodo.c_next = p1->c_next;
1508097Sroot 		arg = p1->c_arg;
1518097Sroot 		func = p1->c_func;
152*8112Sroot 		a = p1->c_time;
1538097Sroot 		p1->c_next = callfree;
1548097Sroot 		callfree = p1;
1558097Sroot 		(void) splx(s);
156*8112Sroot 		(*func)(arg, a);
1572442Swnj 	}
1588097Sroot nocallout:
1592442Swnj 
1602647Swnj #if NDH > 0
1612442Swnj 	s = spl5(); dhtimer(); splx(s);
1622442Swnj #endif
1632647Swnj #if NDZ > 0
1642442Swnj 	s = spl5(); dztimer(); splx(s);
1652442Swnj #endif
1662442Swnj 
1678097Sroot /* if nothing to do, try swapin */
1682450Swnj 	if (noproc && runin) {
1692450Swnj 		runin = 0;
1702450Swnj 		wakeup((caddr_t)&runin);
1712450Swnj 	}
1729Sbill }
1739Sbill 
1749Sbill /*
1758097Sroot  * Arrange that (*fun)(arg) is called in tim/hz seconds.
1769Sbill  */
1779Sbill timeout(fun, arg, tim)
1782450Swnj 	int (*fun)();
1792450Swnj 	caddr_t arg;
1808097Sroot 	int tim;
1819Sbill {
1823542Swnj 	register struct callout *p1, *p2, *pnew;
1839Sbill 	register int t;
1849Sbill 	int s;
1859Sbill 
1869Sbill 	t = tim;
1879Sbill 	s = spl7();
1883542Swnj 	pnew = callfree;
1893542Swnj 	if (pnew == NULL)
1903542Swnj 		panic("timeout table overflow");
1913542Swnj 	callfree = pnew->c_next;
1923542Swnj 	pnew->c_arg = arg;
1933542Swnj 	pnew->c_func = fun;
1943542Swnj 	for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2)
1953542Swnj 		t -= p2->c_time;
1963542Swnj 	p1->c_next = pnew;
1973542Swnj 	pnew->c_next = p2;
1983542Swnj 	pnew->c_time = t;
1993542Swnj 	if (p2)
2003542Swnj 		p2->c_time -= t;
2019Sbill 	splx(s);
2029Sbill }
2037305Ssam 
2047305Ssam /*
2057305Ssam  * untimeout is called to remove a function timeout call
2067305Ssam  * from the callout structure.
2077305Ssam  */
2088097Sroot untimeout(fun, arg)
2097305Ssam 	int (*fun)();
2107305Ssam 	caddr_t arg;
2117305Ssam {
2127305Ssam 	register struct callout *p1, *p2;
2137305Ssam 	register int s;
2147305Ssam 
2157305Ssam 	s = spl7();
2167305Ssam 	for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) {
2177305Ssam 		if (p2->c_func == fun && p2->c_arg == arg) {
218*8112Sroot 			if (p2->c_next && p2->c_time > 0)
2197305Ssam 				p2->c_next->c_time += p2->c_time;
2207305Ssam 			p1->c_next = p2->c_next;
2217305Ssam 			p2->c_next = callfree;
2227305Ssam 			callfree = p2;
2237305Ssam 			break;
2247305Ssam 		}
2257305Ssam 	}
2267305Ssam 	splx(s);
2277305Ssam }
228*8112Sroot 
229*8112Sroot hzto(tv)
230*8112Sroot 	struct timeval *tv;
231*8112Sroot {
232*8112Sroot 	register int ticks;
233*8112Sroot 	int s = spl7();
234*8112Sroot 
235*8112Sroot 	ticks = ((tv->tv_sec - time.tv_sec) * 1000 +
236*8112Sroot 		(tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000);
237*8112Sroot 	splx(s);
238*8112Sroot 	return (ticks);
239*8112Sroot }
240