1 /* 10/14/12 4.1 kern_clock.c */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dk.h" 6 #include "../h/callo.h" 7 #include "../h/seg.h" 8 #include "../h/dir.h" 9 #include "../h/user.h" 10 #include "../h/proc.h" 11 #include "../h/reg.h" 12 #include "../h/psl.h" 13 #include "../h/vm.h" 14 #include "../h/buf.h" 15 #include "../h/text.h" 16 #include "../h/vlimit.h" 17 #include "../h/mtpr.h" 18 #include "../h/clock.h" 19 20 #include "../conf/dh.h" 21 #include "../conf/dz.h" 22 23 #define SCHMAG 9/10 24 25 /* 26 * Constant for decay filter for cpu usage. 27 */ 28 double ccpu = 0.95122942450071400909; /* exp(-1/20) */ 29 30 /* 31 * Clock is called straight from 32 * the real time clock interrupt. 33 * 34 * Functions: 35 * implement callouts 36 * maintain user/system times 37 * maintain date 38 * profile 39 * lightning bolt wakeup (every second) 40 * alarm clock signals 41 * jab the scheduler 42 */ 43 #ifdef KPROF 44 unsigned short kcount[20000]; 45 #endif 46 47 /* 48 * We handle regular calls to the dh and dz silo input processors 49 * without using timeouts to save a little time. 50 */ 51 int rintvl = 0; /* every 1/60'th of sec check receivers */ 52 int rcnt; 53 54 clock(pc, ps) 55 caddr_t pc; 56 { 57 register struct callo *p1, *p2; 58 register struct proc *pp; 59 register int s; 60 int a, cpstate, i; 61 62 /* 63 * reprime clock 64 */ 65 clkreld(); 66 67 /* 68 * callouts 69 * else update first non-zero time 70 */ 71 72 if(callout[0].c_func == NULL) 73 goto out; 74 p2 = &callout[0]; 75 while(p2->c_time<=0 && p2->c_func!=NULL) 76 p2++; 77 p2->c_time--; 78 79 /* 80 * if ps is high, just return 81 */ 82 if (BASEPRI(ps)) 83 goto out; 84 85 /* 86 * callout 87 */ 88 89 if(callout[0].c_time <= 0) { 90 p1 = &callout[0]; 91 while(p1->c_func != 0 && p1->c_time <= 0) { 92 (*p1->c_func)(p1->c_arg); 93 p1++; 94 } 95 p2 = &callout[0]; 96 while(p2->c_func = p1->c_func) { 97 p2->c_time = p1->c_time; 98 p2->c_arg = p1->c_arg; 99 p1++; 100 p2++; 101 } 102 } 103 104 /* 105 * lightning bolt time-out 106 * and time of day 107 */ 108 out: 109 110 /* 111 * In order to not take input character interrupts to use 112 * the input silo on DZ's we have to guarantee to echo 113 * characters regularly. This means that we have to 114 * call the timer routines predictably. Since blocking 115 * in these routines is at spl5(), we have to make spl5() 116 * really spl6() blocking off the clock to put this code 117 * here. Note also that it is critical that we run spl5() 118 * (i.e. really spl6()) in the receiver interrupt routines 119 * so we can't enter them recursively and transpose characters. 120 */ 121 if (rcnt >= rintvl) { 122 #if NDH11 > 0 123 dhtimer(); 124 #endif 125 #if NDZ11 > 0 126 dztimer(); 127 #endif 128 rcnt = 0; 129 } else 130 rcnt++; 131 if (!noproc) { 132 s = u.u_procp->p_rssize; 133 u.u_vm.vm_idsrss += s; 134 if (u.u_procp->p_textp) { 135 register int xrss = u.u_procp->p_textp->x_rssize; 136 137 s += xrss; 138 u.u_vm.vm_ixrss += xrss; 139 } 140 if (s > u.u_vm.vm_maxrss) 141 u.u_vm.vm_maxrss = s; 142 if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) { 143 psignal(u.u_procp, SIGXCPU); 144 if (u.u_limit[LIM_CPU] < INFINITY - 5) 145 u.u_limit[LIM_CPU] += 5; 146 } 147 } 148 if (USERMODE(ps)) { 149 u.u_vm.vm_utime++; 150 if(u.u_procp->p_nice > NZERO) 151 cpstate = CP_NICE; 152 else 153 cpstate = CP_USER; 154 } else { 155 cpstate = CP_SYS; 156 if (noproc) 157 cpstate = CP_IDLE; 158 else 159 u.u_vm.vm_stime++; 160 } 161 cp_time[cpstate]++; 162 for (i = 0; i < DK_NDRIVE; i++) 163 if (dk_busy&(1<<i)) 164 dk_time[i]++; 165 if (!noproc) { 166 pp = u.u_procp; 167 pp->p_cpticks++; 168 if(++pp->p_cpu == 0) 169 pp->p_cpu--; 170 if(pp->p_cpu % 16 == 0) { 171 (void) setpri(pp); 172 if (pp->p_pri >= PUSER) 173 pp->p_pri = pp->p_usrpri; 174 } 175 } 176 ++lbolt; 177 if (lbolt % (HZ/4) == 0) { 178 vmpago(); 179 runrun++; 180 } 181 if (lbolt >= HZ) { 182 extern int hangcnt; 183 184 if (BASEPRI(ps)) 185 return; 186 lbolt -= HZ; 187 ++time; 188 (void) spl1(); 189 /* 190 * machdep.c:unhang uses hangcnt to make sure uba 191 * doesn't forget to interrupt (this has been observed). 192 * This prevents an accumulation of < 5 second uba failures 193 * from summing to a uba reset. 194 */ 195 if (hangcnt) 196 hangcnt--; 197 runrun++; 198 wakeup((caddr_t)&lbolt); 199 for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 200 if (pp->p_stat && pp->p_stat!=SZOMB) { 201 if(pp->p_time != 127) 202 pp->p_time++; 203 if(pp->p_clktim) 204 if(--pp->p_clktim == 0) 205 if (pp->p_flag & STIMO) { 206 s = spl6(); 207 switch (pp->p_stat) { 208 209 case SSLEEP: 210 setrun(pp); 211 break; 212 213 case SSTOP: 214 unsleep(pp); 215 break; 216 } 217 pp->p_flag &= ~STIMO; 218 splx(s); 219 } else 220 psignal(pp, SIGALRM); 221 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 222 if (pp->p_slptime != 127) 223 pp->p_slptime++; 224 if (pp->p_flag&SLOAD) 225 pp->p_pctcpu = ccpu * pp->p_pctcpu + 226 (1.0 - ccpu) * (pp->p_cpticks/(float)HZ); 227 pp->p_cpticks = 0; 228 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 229 if(a < 0) 230 a = 0; 231 if(a > 255) 232 a = 255; 233 pp->p_cpu = a; 234 (void) setpri(pp); 235 s = spl6(); 236 if(pp->p_pri >= PUSER) { 237 if ((pp != u.u_procp || noproc) && 238 pp->p_stat == SRUN && 239 (pp->p_flag & SLOAD) && 240 pp->p_pri != pp->p_usrpri) { 241 remrq(pp); 242 pp->p_pri = pp->p_usrpri; 243 setrq(pp); 244 } else 245 pp->p_pri = pp->p_usrpri; 246 } 247 splx(s); 248 } 249 vmmeter(); 250 if(runin!=0) { 251 runin = 0; 252 wakeup((caddr_t)&runin); 253 } 254 /* 255 * If there are pages that have been cleaned, 256 * jolt the pageout daemon to process them. 257 * We do this here so that these pages will be 258 * freed if there is an abundance of memory and the 259 * daemon would not be awakened otherwise. 260 */ 261 if (bclnlist != NULL) 262 wakeup((caddr_t)&proc[2]); 263 if (USERMODE(ps)) { 264 pp = u.u_procp; 265 #ifdef ERNIE 266 if (pp->p_uid) 267 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 268 pp->p_nice = NZERO+4; 269 (void) setpri(pp); 270 pp->p_pri = pp->p_usrpri; 271 #endif 272 } 273 } 274 if (!BASEPRI(ps)) 275 unhang(); 276 if (USERMODE(ps)) { 277 /* 278 * We do this last since it 279 * may block on a page fault in user space. 280 */ 281 if (u.u_prof.pr_scale) 282 addupc(pc, &u.u_prof, 1); 283 } 284 #ifdef KPROF 285 else if (!noproc) { 286 register int indx = ((int)pc & 0x7fffffff) / 4; 287 288 if (indx >= 0 && indx < 20000) 289 if (++kcount[indx] == 0) 290 --kcount[indx]; 291 } 292 #endif 293 } 294 295 /* 296 * timeout is called to arrange that 297 * fun(arg) is called in tim/HZ seconds. 298 * An entry is sorted into the callout 299 * structure. The time in each structure 300 * entry is the number of HZ's more 301 * than the previous entry. 302 * In this way, decrementing the 303 * first entry has the effect of 304 * updating all entries. 305 * 306 * The panic is there because there is nothing 307 * intelligent to be done if an entry won't fit. 308 */ 309 timeout(fun, arg, tim) 310 int (*fun)(); 311 caddr_t arg; 312 { 313 register struct callo *p1, *p2; 314 register int t; 315 int s; 316 317 t = tim; 318 p1 = &callout[0]; 319 s = spl7(); 320 while(p1->c_func != 0 && p1->c_time <= t) { 321 t -= p1->c_time; 322 p1++; 323 } 324 if (p1 >= &callout[NCALL-1]) 325 panic("Timeout table overflow"); 326 p1->c_time -= t; 327 p2 = p1; 328 while(p2->c_func != 0) 329 p2++; 330 while(p2 >= p1) { 331 (p2+1)->c_time = p2->c_time; 332 (p2+1)->c_func = p2->c_func; 333 (p2+1)->c_arg = p2->c_arg; 334 p2--; 335 } 336 p1->c_time = t; 337 p1->c_func = fun; 338 p1->c_arg = arg; 339 splx(s); 340 } 341