|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/systm.h" ! 3: #include "sys/meter.h" ! 4: #include "sys/callout.h" ! 5: #include "sys/user.h" ! 6: #include "sys/proc.h" ! 7: #include "sys/psl.h" ! 8: #include "sys/vm.h" ! 9: #include "sys/buf.h" ! 10: #include "sys/text.h" ! 11: #include "sys/vlimit.h" ! 12: #include "sys/mtpr.h" ! 13: #include "sys/clock.h" ! 14: ! 15: int queueflag; ! 16: ! 17: /* ! 18: * trivial kernel profiling; quite expensive in space ! 19: */ ! 20: #define KMAX (200*1024) /* max kernel text */ ! 21: #define KPSIZE (50*256) /* number of buckets */ ! 22: #define KPROF 1 ! 23: #if KPROF ! 24: long kprof[KPSIZE]; ! 25: #endif ! 26: ! 27: ! 28: /* ! 29: * Hardclock is called straight from ! 30: * the real time clock interrupt. ! 31: * We limit the work we do at real clock interrupt time to: ! 32: * reloading clock ! 33: * decrementing time to callouts ! 34: * recording cpu time usage ! 35: * modifying priority of current process ! 36: * arrange for soft clock interrupt ! 37: * kernel pc profiling ! 38: * ! 39: * At software (softclock) interrupt time we: ! 40: * implement callouts ! 41: * maintain date ! 42: * lightning bolt wakeup (every second) ! 43: * alarm clock signals ! 44: * jab the scheduler ! 45: * ! 46: * On the vax softclock interrupts are implemented by ! 47: * software interrupts. Note that we may have multiple softclock ! 48: * interrupts compressed into one (due to excessive interrupt load), ! 49: * but that hardclock interrupts should never be lost. ! 50: */ ! 51: /*ARGSUSED*/ ! 52: hardclock(pc, ps) ! 53: caddr_t pc; ! 54: { ! 55: register struct callout *p1; ! 56: register struct proc *pp; ! 57: register int s, cpstate; ! 58: ! 59: /* ! 60: * reprime clock ! 61: */ ! 62: clkreld(); ! 63: ! 64: /* ! 65: * update callout times ! 66: */ ! 67: for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) ! 68: ; ! 69: if (p1) ! 70: p1->c_time--; ! 71: pp = u.u_procp; ! 72: if (USERMODE(ps)) { ! 73: u.u_vm.vm_utime++; ! 74: if (pp->p_nice > NZERO) ! 75: cpstate = CP_NICE; ! 76: else ! 77: cpstate = CP_USER; ! 78: s = 1; ! 79: } else { ! 80: #if KPROF ! 81: s = (long)pc - KSTART; ! 82: if (s < 0) ! 83: s = 0; /* shouldn't */ ! 84: else if (s >= KMAX) ! 85: s = KMAX - 1; ! 86: s /= KMAX/KPSIZE; ! 87: kprof[s]++; ! 88: #endif ! 89: cpstate = CP_SYS; ! 90: if (queueflag) { ! 91: cpstate = CP_QUEUE; ! 92: s = 0; ! 93: } else if (noproc) { ! 94: if (BASEPRI(ps) == 0) ! 95: cpstate = CP_IDLE; ! 96: s = 0; ! 97: } else { ! 98: u.u_vm.vm_stime++; ! 99: s = 1; ! 100: } ! 101: } ! 102: cp_time[cpstate]++; ! 103: /* ! 104: * Adjust priority of current process. ! 105: */ ! 106: if (s) { ! 107: pp->p_cpticks++; ! 108: if(++pp->p_cpu == 0) ! 109: --pp->p_cpu; ! 110: } ! 111: ++lbolt; ! 112: setsoftclock(); ! 113: } ! 114: ! 115: #define cpuave(a,b) ((int)(((int)((a)*(b)))/((b)+1))) ! 116: extern double avenrun[]; ! 117: /* ! 118: * Constant for decay filter for cpu usage field ! 119: * in process table (used by ps au). ! 120: */ ! 121: static float ccpu = 0.9512294245; /* exp(-1/20) */ ! 122: ! 123: /* ! 124: * Software clock interrupt. ! 125: * This routine runs at lower priority than device interrupts. ! 126: * ! 127: * Processes have their (32-bit) priority depend on their owner's ``normalised ! 128: * usage'' of resources. However, V9's low-level scheduler only has 127 priorities, ! 129: * (in fact, only 32, so that someone could use an 'ffs' instruction), ! 130: * so we normalise this ``sharepri'' into the 7-bit ``usrpri''. Note that ! 131: * the 'ffs' hack means that (after PUSER) there are only 20 real priorities ! 132: * for processes to run in, and that defined kernel priorities should differ ! 133: * by more than 4 to be meaningful. ! 134: */ ! 135: /*ARGSUSED*/ ! 136: softclock(pc, ps) ! 137: caddr_t pc; ! 138: { ! 139: register struct callout *p1; ! 140: register struct proc *pp; ! 141: register int a, s; ! 142: extern char *panicstr; ! 143: ! 144: /* ! 145: * Perform callouts (but not after panics) ! 146: */ ! 147: if (panicstr == 0) { ! 148: for (;;) { ! 149: register caddr_t arg; ! 150: register int (*func)(); ! 151: ! 152: s = spl7(); ! 153: if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { ! 154: splx(s); ! 155: break; ! 156: } ! 157: calltodo.c_next = p1->c_next; ! 158: arg = p1->c_arg; ! 159: func = p1->c_func; ! 160: p1->c_next = callfree; ! 161: callfree = p1; ! 162: (void) splx(s); ! 163: (*func)(arg); ! 164: } ! 165: } ! 166: ! 167: /* ! 168: * If idling and processes are waiting to swap in, ! 169: * check on them. ! 170: */ ! 171: if (noproc && runin) { ! 172: runin = 0; ! 173: wakeup((caddr_t)&runin); ! 174: } ! 175: if (lbolt % (HZ/10) == 0) { ! 176: runrun++; ! 177: aston(); ! 178: } ! 179: ! 180: /* ! 181: * Lightning bolt every second: ! 182: * sleep timeouts ! 183: * process priority recomputation ! 184: * process %cpu averaging ! 185: * p_time and p_slptime for the swapper ! 186: * kick swapper if processes want in ! 187: */ ! 188: if (lbolt >= HZ) { ! 189: /* meaningless on VAX; meant for hardclock */ ! 190: if (BASEPRI(ps)) ! 191: return; ! 192: time += lbolt / HZ; ! 193: lbolt %= HZ; ! 194: wakeup((caddr_t)&lbolt); ! 195: for (pp = proc; pp < procNPROC; pp++) ! 196: if ((a=pp->p_stat)!=0 && a!=SZOMB) { ! 197: if (pp->p_time != 127) ! 198: pp->p_time++; ! 199: if (pp->p_clktim && --pp->p_clktim == 0) ! 200: psignal(pp, SIGALRM); ! 201: if (pp->p_tsleep && --pp->p_tsleep == 0) { ! 202: s = spl6(); ! 203: switch (pp->p_stat) { /* != a if interrupted */ ! 204: ! 205: case SSLEEP: ! 206: setrun(pp); ! 207: break; ! 208: ! 209: case SSTOP: ! 210: unsleep(pp); ! 211: break; ! 212: } ! 213: pp->p_flag |= STIMO; ! 214: splx(s); ! 215: } ! 216: if (a==SSLEEP || a==SSTOP) ! 217: if (pp->p_slptime != 127) ! 218: pp->p_slptime++; ! 219: /* ! 220: * update silly numbers for ps to print ! 221: */ ! 222: if (pp->p_flag&SLOAD) ! 223: pp->p_pctcpu = ccpu*pp->p_pctcpu + ! 224: (1.0 - ccpu) * (pp->p_cpticks/(float)HZ); ! 225: pp->p_cpticks = 0; ! 226: ! 227: /* ! 228: * Update p_cpu for scheduling ! 229: */ ! 230: a = cpuave(pp->p_cpu, 2*avenrun[0]); ! 231: if (a < 0) ! 232: a = 0; ! 233: if (a > 255) ! 234: a = 255; ! 235: pp->p_cpu = a; ! 236: (void) setpri(pp); ! 237: /* ! 238: * p_usrpri == new process priority ! 239: * now fix p_pri to match, carefully ! 240: */ ! 241: s = spl6(); ! 242: if (pp->p_pri >= PUSER && pp->p_pri != pp->p_usrpri) { ! 243: if ((pp != u.u_procp || noproc) && pp->p_stat == SRUN && ! 244: (pp->p_flag & SLOAD)) { ! 245: remrq(pp); ! 246: pp->p_pri = pp->p_usrpri; ! 247: setrq(pp); ! 248: } else ! 249: pp->p_pri = pp->p_usrpri; ! 250: } ! 251: splx(s); ! 252: } ! 253: if (runin!=0) { ! 254: runin = 0; ! 255: wakeup((caddr_t)&runin); ! 256: } ! 257: } ! 258: if (noproc) ! 259: return; ! 260: pp = u.u_procp; ! 261: /* ! 262: * If trapped user-mode, give it a profiling tick. ! 263: */ ! 264: if (USERMODE(ps) && u.u_prof.pr_scale) { ! 265: pp->p_flag |= SOWEUPC; ! 266: aston(); ! 267: } ! 268: /* ! 269: * random statistics, apparently computed just so ! 270: * that programs like ps can print them? not a good reason ! 271: */ ! 272: s = pp->p_rssize; ! 273: u.u_vm.vm_idsrss += s; ! 274: if (pp->p_textp) { ! 275: a = pp->p_textp->x_rssize; ! 276: s += a; ! 277: u.u_vm.vm_ixrss += a; ! 278: } ! 279: if (s > u.u_vm.vm_maxrss) ! 280: u.u_vm.vm_maxrss = s; ! 281: /* ! 282: * cpu time limit ! 283: */ ! 284: if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) { ! 285: psignal(pp, SIGXCPU); ! 286: if (u.u_limit[LIM_CPU] < INFINITY - 5) ! 287: u.u_limit[LIM_CPU] += 5; ! 288: } ! 289: } ! 290: ! 291: /* ! 292: * Timeout is called to arrange that ! 293: * fun(arg) is called in tim/HZ seconds. ! 294: * An entry is linked into the callout ! 295: * structure. The time in each structure ! 296: * entry is the number of HZ's more ! 297: * than the previous entry. ! 298: * In this way, decrementing the ! 299: * first entry has the effect of ! 300: * updating all entries. ! 301: * ! 302: * The panic is there because there is nothing ! 303: * intelligent to be done if an entry won't fit. ! 304: */ ! 305: timeout(fun, arg, tim) ! 306: int (*fun)(); ! 307: caddr_t arg; ! 308: { ! 309: register struct callout *p1, *p2, *pnew; ! 310: register int t; ! 311: int s; ! 312: ! 313: t = tim; ! 314: s = spl7(); ! 315: pnew = callfree; ! 316: if (pnew == NULL) ! 317: panic("timeout table overflow"); ! 318: callfree = pnew->c_next; ! 319: pnew->c_arg = arg; ! 320: pnew->c_func = fun; ! 321: for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) ! 322: t -= p2->c_time; ! 323: p1->c_next = pnew; ! 324: pnew->c_next = p2; ! 325: pnew->c_time = t; ! 326: if (p2) ! 327: p2->c_time -= t; ! 328: splx(s); ! 329: } ! 330: ! 331: /* ! 332: * Delay goes to sleep on a unique address for a ! 333: * guaranteed minimum period ticks/HZ secs. ! 334: * Because a timeout() can't be cancelled, the process ! 335: * will be unkillable while asleep. Beware of giving ! 336: * delay() an argument of more than a few hundred. ! 337: * ! 338: * used by one device driver and by sys nap. ! 339: * do we really need it? ! 340: */ ! 341: delay(ticks) ! 342: { ! 343: register int x; ! 344: extern wakeup(); ! 345: ! 346: if (ticks<=0) ! 347: return; ! 348: x = spl7(); ! 349: timeout(wakeup, (caddr_t)u.u_procp+1, ticks); ! 350: sleep((caddr_t)u.u_procp+1, PZERO-1); ! 351: splx(x); ! 352: } ! 353: ! 354: /* ! 355: * init callouts ! 356: * called from main ! 357: */ ! 358: ! 359: callinit() ! 360: { ! 361: register int i; ! 362: ! 363: callfree = callout; ! 364: for (i = 1; i < calloutcnt; i++) ! 365: callout[i-1].c_next = &callout[i]; ! 366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.