#include "../h/local.h" #ifdef SCCS_ID static char SCCS_ID [] = "@(#)clock.c 3.1.2.2 18:41:36 - 83/02/15 "; #endif SCCS_ID #include "../h/param.h" #include "../h/systm.h" #include "../h/callo.h" #include "../h/seg.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/proc.h" #include "../h/reg.h" #define SCHMAG 8/10 #ifdef PROF_KERNEL int sysprof[2176]; #endif /* * clock is called straight from * the real time clock interrupt. * * Functions: * reprime clock * copy *switches to display * implement callouts * maintain user/system times * maintain date * profile * lightning bolt wakeup (every second) * alarm clock signals * jab the scheduler */ #ifdef DEC clock(dev, sp, r1, nps, r0, pc, ps) #else clock(dev, stat, r0, r1, r2, r3, r4, r5, r6, asp, rf, ps, pc, nps) #endif dev_t dev; caddr_t pc; { register struct callo *p1, *p2; register struct proc *pp; int a; extern caddr_t waitloc; #ifndef DEC static int clkflag; #endif #ifdef DEC /* * restart clock */ lks->r[0] = 0115; #endif /* * display register */ #ifdef DEC display(); #else display(pc); #endif /* * callouts * if none, just continue * else update first non-zero time */ if(callout[0].c_func == NULL) goto out; p2 = &callout[0]; while(p2->c_time<=0 && p2->c_func!=NULL) p2++; p2->c_time--; /* * if ps is high, just return */ #ifdef DEC if (BASEPRI(ps)) #else if (clkflag) #endif goto out; /* * callout */ spl5(); if(callout[0].c_time <= 0) { p1 = &callout[0]; while(p1->c_func != 0 && p1->c_time <= 0) { (*p1->c_func)(p1->c_arg); p1++; } p2 = &callout[0]; while(p2->c_func = p1->c_func) { p2->c_time = p1->c_time; p2->c_arg = p1->c_arg; p1++; p2++; } } /* * lightning bolt time-out * and time of day */ out: #ifdef DEC a = dk_busy&07; #else a = dk_busy&0xf; #endif if (USERMODE(ps)) { u.u_utime++; if(u.u_prof.pr_scale) addupc(pc, &u.u_prof, 1); if(u.u_procp->p_nice > NZERO) #ifdef DEC a += 8; #else a += 16; #endif } else { #ifdef DEC a += 16; #else a += 32; #endif if (pc == waitloc) #ifdef DEC a += 8; #else a += 16; #endif #ifdef PROF_KERNEL else sysprof[(unsigned)pc >> 5]++; #endif u.u_stime++; } dk_time[a] += 1; pp = u.u_procp; #ifdef DEC if(++pp->p_cpu == 0) #else if(++pp->p_cpu > 255) #endif pp->p_cpu--; if(++lbolt >= HZ) { #ifdef DEC if (BASEPRI(ps)) #else if (clkflag) #endif return; lbolt -= HZ; ++time; #ifdef DEC spl1(); #else clkflag = 1; spl0(); #endif runrun++; wakeup((caddr_t)&lbolt); for(pp = &proc[0]; pp < procNPROC; pp++) if (pp->p_stat && pp->p_statp_time != 127) pp->p_time++; if(pp->p_clktim) if(--pp->p_clktim == 0) #ifdef SVC6 { if (pp->p_wchan == &pp->p_clktim) wakeup(&pp->p_clktim); else psignal(pp, SIGCLK); } #else psignal(pp, SIGCLK); #endif a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; if(a < 0) a = 0; if(a > 255) a = 255; pp->p_cpu = a; if(pp->p_pri >= PUSER) setpri(pp); } if(runin!=0) { runin = 0; wakeup((caddr_t)&runin); } #ifndef DEC clkflag = 0; #endif } } /* * timeout is called to arrange that * fun(arg) is called in tim/HZ seconds. * An entry is sorted into the callout * structure. The time in each structure * entry is the number of HZ's more * than the previous entry. * In this way, decrementing the * first entry has the effect of * updating all entries. * * The panic is there because there is nothing * intelligent to be done if an entry won't fit. */ timeout(fun, arg, tim) int (*fun)(); caddr_t arg; { register struct callo *p1, *p2; register int t; int s; t = tim; p1 = &callout[0]; s = spl7(); while(p1->c_func != 0 && p1->c_time <= t) { t -= p1->c_time; p1++; } if (p1 >= &calloutNCALL[-1]) panic("Timeout table overflow"); p1->c_time -= t; p2 = p1; while(p2->c_func != 0) p2++; while(p2 >= p1) { (p2+1)->c_time = p2->c_time; (p2+1)->c_func = p2->c_func; (p2+1)->c_arg = p2->c_arg; p2--; } p1->c_time = t; p1->c_func = fun; p1->c_arg = arg; splx(s); }