1 /* kern_synch.c 4.25 82/12/17 */ 2 3 #include "../machine/pte.h" 4 5 #include "../h/param.h" 6 #include "../h/systm.h" 7 #include "../h/dir.h" 8 #include "../h/user.h" 9 #include "../h/proc.h" 10 #include "../h/file.h" 11 #include "../h/inode.h" 12 #include "../h/vm.h" 13 #ifdef MUSH 14 #include "../h/quota.h" 15 #include "../h/share.h" 16 #endif 17 #include "../h/kernel.h" 18 #include "../h/buf.h" 19 20 #ifdef vax 21 #include "../vax/mtpr.h" /* XXX */ 22 #endif 23 /* 24 * Force switch among equal priority processes every 100ms. 25 */ 26 roundrobin() 27 { 28 29 runrun++; 30 aston(); 31 timeout(roundrobin, (caddr_t)0, hz / 10); 32 } 33 34 /* constants to digital decay and forget 90% of usage in 5*loadav time */ 35 #undef ave 36 #define ave(a,b) ((int)(((int)(a*b))/(b+1))) 37 int nrscale = 2; 38 double ccpu = 0.95122942450071400909; /* exp(-1/20) */ 39 40 /* 41 * Recompute process priorities, once a second 42 */ 43 schedcpu() 44 { 45 register struct proc *p; 46 register int s, a; 47 48 wakeup((caddr_t)&lbolt); 49 for (p = proc; p < procNPROC; p++) if (p->p_stat && p->p_stat!=SZOMB) { 50 #ifdef MUSH 51 if (p->p_quota->q_uid) 52 p->p_quota->q_cost += 53 shconsts.sc_click * p->p_rssize; 54 #endif 55 if (p->p_time != 127) 56 p->p_time++; 57 if (p->p_stat==SSLEEP || p->p_stat==SSTOP) 58 if (p->p_slptime != 127) 59 p->p_slptime++; 60 if (p->p_flag&SLOAD) 61 p->p_pctcpu = ccpu * p->p_pctcpu + 62 (1.0 - ccpu) * (p->p_cpticks/(float)hz); 63 p->p_cpticks = 0; 64 #ifdef MUSH 65 a = ave((p->p_cpu & 0377), avenrun[0]*nrscale) + 66 p->p_nice - NZERO + p->p_quota->q_nice; 67 #else 68 a = ave((p->p_cpu & 0377), avenrun[0]*nrscale) + 69 p->p_nice - NZERO; 70 #endif 71 if (a < 0) 72 a = 0; 73 if (a > 255) 74 a = 255; 75 p->p_cpu = a; 76 (void) setpri(p); 77 s = spl6(); /* prevent state changes */ 78 if (p->p_pri >= PUSER) { 79 if ((p != u.u_procp || noproc) && 80 p->p_stat == SRUN && 81 (p->p_flag & SLOAD) && 82 p->p_pri != p->p_usrpri) { 83 remrq(p); 84 p->p_pri = p->p_usrpri; 85 setrq(p); 86 } else 87 p->p_pri = p->p_usrpri; 88 } 89 splx(s); 90 } 91 vmmeter(); 92 if (runin!=0) { 93 runin = 0; 94 wakeup((caddr_t)&runin); 95 } 96 if (bclnlist != NULL) 97 wakeup((caddr_t)&proc[2]); 98 timeout(schedcpu, (caddr_t)0, hz); 99 } 100 101 #define SQSIZE 0100 /* Must be power of 2 */ 102 #define HASH(x) (( (int) x >> 5) & (SQSIZE-1)) 103 struct proc *slpque[SQSIZE]; 104 105 /* 106 * Give up the processor till a wakeup occurs 107 * on chan, at which time the process 108 * enters the scheduling queue at priority pri. 109 * The most important effect of pri is that when 110 * pri<=PZERO a signal cannot disturb the sleep; 111 * if pri>PZERO signals will be processed. 112 * Callers of this routine must be prepared for 113 * premature return, and check that the reason for 114 * sleeping has gone away. 115 */ 116 sleep(chan, pri) 117 caddr_t chan; 118 int pri; 119 { 120 register struct proc *rp, **hp; 121 register s; 122 123 rp = u.u_procp; 124 s = spl6(); 125 if (chan==0 || rp->p_stat != SRUN || rp->p_rlink) 126 panic("sleep"); 127 rp->p_wchan = chan; 128 rp->p_slptime = 0; 129 rp->p_pri = pri; 130 hp = &slpque[HASH(chan)]; 131 rp->p_link = *hp; 132 *hp = rp; 133 if (pri > PZERO) { 134 if (ISSIG(rp)) { 135 if (rp->p_wchan) 136 unsleep(rp); 137 rp->p_stat = SRUN; 138 (void) spl0(); 139 goto psig; 140 } 141 if (rp->p_wchan == 0) 142 goto out; 143 rp->p_stat = SSLEEP; 144 (void) spl0(); 145 u.u_ru.ru_nvcsw++; 146 swtch(); 147 if (ISSIG(rp)) 148 goto psig; 149 } else { 150 rp->p_stat = SSLEEP; 151 (void) spl0(); 152 u.u_ru.ru_nvcsw++; 153 swtch(); 154 } 155 out: 156 splx(s); 157 return; 158 159 /* 160 * If priority was low (>PZERO) and 161 * there has been a signal, execute non-local goto through 162 * u.u_qsave, aborting the system call in progress (see trap.c) 163 * (or finishing a tsleep, see below) 164 */ 165 psig: 166 longjmp(&u.u_qsave); 167 /*NOTREACHED*/ 168 } 169 170 /* 171 * Remove a process from its wait queue 172 */ 173 unsleep(p) 174 register struct proc *p; 175 { 176 register struct proc **hp; 177 register s; 178 179 s = spl6(); 180 if (p->p_wchan) { 181 hp = &slpque[HASH(p->p_wchan)]; 182 while (*hp != p) 183 hp = &(*hp)->p_link; 184 *hp = p->p_link; 185 p->p_wchan = 0; 186 } 187 splx(s); 188 } 189 190 /* 191 * Wake up all processes sleeping on chan. 192 */ 193 wakeup(chan) 194 register caddr_t chan; 195 { 196 register struct proc *p, **q, **h; 197 int s; 198 199 s = spl6(); 200 h = &slpque[HASH(chan)]; 201 restart: 202 for (q = h; p = *q; ) { 203 if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP) 204 panic("wakeup"); 205 if (p->p_wchan==chan) { 206 p->p_wchan = 0; 207 *q = p->p_link; 208 p->p_slptime = 0; 209 if (p->p_stat == SSLEEP) { 210 /* OPTIMIZED INLINE EXPANSION OF setrun(p) */ 211 p->p_stat = SRUN; 212 if (p->p_flag & SLOAD) 213 setrq(p); 214 if (p->p_pri < curpri) { 215 runrun++; 216 aston(); 217 } 218 if ((p->p_flag&SLOAD) == 0) { 219 if (runout != 0) { 220 runout = 0; 221 wakeup((caddr_t)&runout); 222 } 223 wantin++; 224 } 225 /* END INLINE EXPANSION */ 226 goto restart; 227 } 228 } else 229 q = &p->p_link; 230 } 231 splx(s); 232 } 233 234 /* 235 * Initialize the (doubly-linked) run queues 236 * to be empty. 237 */ 238 rqinit() 239 { 240 register int i; 241 242 for (i = 0; i < NQS; i++) 243 qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; 244 } 245 246 /* 247 * Set the process running; 248 * arrange for it to be swapped in if necessary. 249 */ 250 setrun(p) 251 register struct proc *p; 252 { 253 register int s; 254 255 s = spl6(); 256 switch (p->p_stat) { 257 258 case 0: 259 case SWAIT: 260 case SRUN: 261 case SZOMB: 262 default: 263 panic("setrun"); 264 265 case SSTOP: 266 case SSLEEP: 267 unsleep(p); /* e.g. when sending signals */ 268 break; 269 270 case SIDL: 271 break; 272 } 273 p->p_stat = SRUN; 274 if (p->p_flag & SLOAD) 275 setrq(p); 276 splx(s); 277 if (p->p_pri < curpri) { 278 runrun++; 279 aston(); 280 } 281 if ((p->p_flag&SLOAD) == 0) { 282 if (runout != 0) { 283 runout = 0; 284 wakeup((caddr_t)&runout); 285 } 286 wantin++; 287 } 288 } 289 290 /* 291 * Set user priority. 292 * The rescheduling flag (runrun) 293 * is set if the priority is better 294 * than the currently running process. 295 */ 296 setpri(pp) 297 register struct proc *pp; 298 { 299 register int p; 300 301 p = (pp->p_cpu & 0377)/4; 302 p += PUSER + 2*(pp->p_nice - NZERO); 303 if (pp->p_rssize > pp->p_maxrss && freemem < desfree) 304 p += 2*4; /* effectively, nice(4) */ 305 if (p > 127) 306 p = 127; 307 if (p < curpri) { 308 runrun++; 309 aston(); 310 } 311 pp->p_usrpri = p; 312 return (p); 313 } 314