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