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