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