1: /*
   2:  *	SCCS id	@(#)clock.c	2.1 (Berkeley)	9/1/83
   3:  */
   4: 
   5: #include "param.h"
   6: #include <sys/systm.h>
   7: #include <sys/callout.h>
   8: #include <sys/seg.h>
   9: #include <sys/dir.h>
  10: #include <sys/user.h>
  11: #include <sys/proc.h>
  12: #include <sys/reg.h>
  13: #ifdef UCB_METER
  14: #include <sys/text.h>
  15: #include <sys/vm.h>
  16: #endif
  17: #ifdef UCB_NET
  18:     /*
  19: 	 * shifted to keep "make depend" from finding these for now...
  20: 	 */
  21: #	include <sys/protosw.h>
  22: #	include <sys/socket.h>
  23: #	include "../net/if.h"
  24: #	include "../net/in_systm.h"
  25: #endif
  26: 
  27: #ifdef UCB_FRCSWAP
  28: extern int  idleflg;    /* If set, allow incore forks and expands */
  29:                 /* Set before idle(), cleared in clock.c */
  30: #endif
  31: 
  32: #ifdef  UCB_NET
  33: /*
  34:  * Protoslow is like lbolt, but for slow protocol timeouts, counting
  35:  * up to (hz/PR_SLOWHZ), then causing a pfslowtimo().
  36:  * Protofast is like lbolt, but for fast protocol timeouts, counting
  37:  * up to (hz/PR_FASTHZ), then causing a pffasttimo().
  38:  */
  39: int protoslow;
  40: int protofast;
  41: int ifnetslow;
  42: int     netoff;
  43: #endif
  44: 
  45: #define SCHMAG  8/10
  46: 
  47: /*
  48:  * clock is called straight from
  49:  * the real time clock interrupt.
  50:  *
  51:  * Functions:
  52:  *	reprime clock
  53:  *	copy *switches to display
  54:  *	implement callouts
  55:  *	maintain user/system times
  56:  *	maintain date
  57:  *	profile
  58:  *	lightning bolt wakeup (every second)
  59:  *	alarm clock signals
  60:  *	jab the scheduler
  61:  */
  62: 
  63: /*ARGSUSED*/
  64: #ifdef  MENLO_KOV
  65: clock(dev, sp, r1, ov, nps, r0, pc, ps)
  66: #else
  67: clock(dev, sp, r1, nps, r0, pc, ps)
  68: #endif
  69: dev_t dev;
  70: caddr_t pc;
  71: {
  72:     register a;
  73:     mapinfo map;
  74:     extern caddr_t waitloc;
  75:     extern char *panicstr;
  76: 
  77:     /*
  78: 	 * restart clock
  79: 	 */
  80:     if(lks)
  81:         *lks = 0115;
  82:     /*
  83: 	 * ensure normal mapping of kernel data
  84: 	 */
  85:     savemap(map);
  86: 
  87: #ifdef  DISPLAY
  88:     /*
  89: 	 * display register
  90: 	 */
  91:     display();
  92: #endif
  93: 
  94:     /*
  95: 	 * callouts
  96: 	 * never after panics
  97: 	 * if none, just continue
  98: 	 * else update first non-zero time
  99: 	 */
 100:     if (panicstr == (char *) 0) {
 101:         register struct callout *p1, *p2;
 102: 
 103:         if(callout[0].c_func == NULL)
 104:             goto out;
 105:         p2 = &callout[0];
 106:         while(p2->c_time<=0 && p2->c_func!=NULL)
 107:             p2++;
 108:         p2->c_time--;
 109: 
 110: #ifdef  UCB_NET
 111:         /*
 112: 		 * Time moves on for protocols.
 113: 		 */
 114:         if(!netoff) {
 115:             --protoslow; --protofast; --ifnetslow;
 116:             if(protoslow<=0 || protofast<=0 || ifnetslow<=0)
 117:                 schednetisr(NETISR_CLOCK);
 118:         }
 119: #endif
 120: 
 121:         /*
 122: 		 * if ps is high, just return
 123: 		 */
 124:         if (!BASEPRI(ps))
 125:             goto out;
 126: 
 127:         /*
 128: 		 * callout
 129: 		 */
 130:         if(callout[0].c_time <= 0) {
 131:             p1 = &callout[0];
 132:             while(p1->c_func != 0 && p1->c_time <= 0) {
 133:                 (*p1->c_func)(p1->c_arg);
 134:                 p1++;
 135:             }
 136:             p2 = &callout[0];
 137:             while(p2->c_func = p1->c_func) {
 138:                 p2->c_time = p1->c_time;
 139:                 p2->c_arg = p1->c_arg;
 140:                 p1++;
 141:                 p2++;
 142:             }
 143:         }
 144:     }
 145: out:
 146: 
 147:     a = (dk_busy != 0);
 148:     if (USERMODE(ps)) {
 149:         u.u_utime++;
 150:         if(u.u_prof.pr_scale)
 151:             addupc(pc, &u.u_prof, 1);
 152:         if(u.u_procp->p_nice > NZERO)
 153:             a += 2;
 154:     } else {
 155:         a += 4;
 156:         if (pc == waitloc)
 157:             a += 2;
 158:         u.u_stime++;
 159:     }
 160:     sy_time[a] += 1;
 161:     dk_time[dk_busy & ((1 << ndisk) - 1)] += 1;
 162:     {
 163:       register struct proc *pp;
 164:       pp = u.u_procp;
 165:       if(++pp->p_cpu == 0)
 166:         pp->p_cpu--;
 167:     }
 168:     /*
 169: 	 * lightning bolt time-out
 170: 	 * and time of day
 171: 	 */
 172:     if ((++lbolt >= hz) && (BASEPRI(ps))) {
 173:         register struct proc *pp;
 174: 
 175:         lbolt -= hz;
 176: #ifdef  UCB_FRCSWAP
 177:         idleflg = 0;
 178: #endif
 179:         ++time;
 180:         (void) _spl1();
 181: #if defined(UCB_LOAD) || defined(UCB_METER)
 182:         meter();
 183: #endif
 184:         runrun++;
 185:         wakeup((caddr_t)&lbolt);
 186:         for(pp = &proc[0]; pp <= maxproc; pp++)
 187:         if (pp->p_stat && pp->p_stat<SZOMB) {
 188:             if(pp->p_time != 127)
 189:                 pp->p_time++;
 190: #ifdef  UCB_METER
 191:             if (pp->p_stat == SSLEEP || pp->p_stat == SSTOP)
 192:                 if (pp->p_slptime != 127)
 193:                     pp->p_slptime++;
 194: #endif	UCB_METER
 195:             if (pp->p_clktim && --pp->p_clktim == 0)
 196: #ifdef  UCB_NET
 197:                 /*
 198: 				 * If process has clock counting down, and it
 199: 				 * expires, set it running (if this is a
 200: 				 * tsleep()), or give it an SIGALRM (if the user
 201: 				 * process is using alarm signals.
 202: 				 */
 203:                 if (pp->p_flag & STIMO) {
 204:                     a = spl6();
 205:                     switch (pp->p_stat) {
 206: 
 207:                     case SSLEEP:
 208:                         setrun(pp);
 209:                         break;
 210: 
 211:                     case SSTOP:
 212:                         unsleep(pp);
 213:                         break;
 214:                     }
 215:                     pp->p_flag &= ~STIMO;
 216:                     splx(a);
 217:                 } else
 218: #endif
 219:                     psignal(pp, SIGALRM);
 220:             a = (pp->p_cpu & 0377) * SCHMAG + pp->p_nice - NZERO;
 221:             if(a < 0)
 222:                 a = 0;
 223:             if(a > 255)
 224:                 a = 255;
 225:             pp->p_cpu = a;
 226:             if(pp->p_pri >= PUSER)
 227:                 setpri(pp);
 228:         }
 229:         if(runin!=0) {
 230:             runin = 0;
 231:             wakeup((caddr_t)&runin);
 232:         }
 233:     }
 234:     restormap(map);
 235: }
 236: 
 237: /*
 238:  * timeout is called to arrange that
 239:  * fun(arg) is called in tim/hz seconds.
 240:  * An entry is sorted into the callout
 241:  * structure. The time in each structure
 242:  * entry is the number of hz's more
 243:  * than the previous entry.
 244:  * In this way, decrementing the
 245:  * first entry has the effect of
 246:  * updating all entries.
 247:  *
 248:  * The panic is there because there is nothing
 249:  * intelligent to be done if an entry won't fit.
 250:  */
 251: timeout(fun, arg, tim)
 252: int (*fun)();
 253: caddr_t arg;
 254: {
 255:     register struct callout *p1, *p2;
 256:     register int t;
 257:     int s;
 258: 
 259:     t = tim;
 260:     p1 = &callout[0];
 261:     s = spl7();
 262:     while(p1->c_func != 0 && p1->c_time <= t) {
 263:         t -= p1->c_time;
 264:         p1++;
 265:     }
 266:     p1->c_time -= t;
 267:     p2 = p1;
 268:     while(p2->c_func != 0)
 269:         p2++;
 270:     if (p2 >= callNCALL)
 271:         panic("Timeout table overflow");
 272:     while(p2 >= p1) {
 273:         (p2+1)->c_time = p2->c_time;
 274:         (p2+1)->c_func = p2->c_func;
 275:         (p2+1)->c_arg = p2->c_arg;
 276:         p2--;
 277:     }
 278:     p1->c_time = t;
 279:     p1->c_func = fun;
 280:     p1->c_arg = arg;
 281:     splx(s);
 282:     return;
 283: }
 284: 
 285: #if defined(UCB_LOAD) || defined(UCB_METER)
 286: /*
 287:  * Count up various things once a second
 288:  */
 289: short avenrun[3];   /* internal load average in psuedo-floating point */
 290: #define ave(smooth,new,time)  (smooth) = (((time)-1) * (smooth) + (new))/ (time)
 291: 
 292: #define ctok(cliks) (((cliks) >> 4) & 07777)    /* clicks to KB */
 293: 
 294: meter()
 295: {
 296: #ifdef UCB_METER
 297:     register unsigned *cp, *rp;
 298:     register long *sp;
 299: 
 300:     ave(avefree, ctok(freemem), 5);
 301: #endif
 302: 
 303:     if (time % 5 == 0) {
 304:         vmtotal();
 305: #ifdef UCB_METER
 306:         cp = &cnt.v_first; rp = &rate.v_first; sp = &sum.vs_first;
 307:         while (cp <= &cnt.v_last) {
 308:             *rp = *cp;
 309:             *sp += *cp;
 310:             *cp = 0;
 311:             rp++, cp++, sp++;
 312:         }
 313: #endif
 314:     }
 315: }
 316: 
 317: vmtotal()
 318: {
 319:     extern  char    counted[];
 320:     register struct proc *p;
 321:     register struct text *xq;
 322:     register nrun = 0;
 323: #ifdef UCB_METER
 324:     int nt;
 325: 
 326:     total.t_vmtxt = 0;
 327:     total.t_avmtxt = 0;
 328:     total.t_rmtxt = 0;
 329:     total.t_armtxt = 0;
 330:     for (xq = text; xq < textNTEXT; xq++) {
 331:         counted[xq-text]=0;
 332:         if (xq->x_iptr) {
 333:             total.t_vmtxt += xq->x_size;
 334:             if (xq->x_ccount)
 335:                 total.t_rmtxt += xq->x_size;
 336:         }
 337:     }
 338:     total.t_vm = 0;
 339:     total.t_avm = 0;
 340:     total.t_rm = 0;
 341:     total.t_arm = 0;
 342:     total.t_rq = 0;
 343:     total.t_dw = 0;
 344:     total.t_sl = 0;
 345:     total.t_sw = 0;
 346: #endif
 347:     for (p = &proc[1]; p <= maxproc; p++) {
 348:         if (p->p_stat) {
 349: #ifdef UCB_METER
 350: #ifndef VIRUS_VFORK
 351:             total.t_vm += p->p_size;
 352:             if (p->p_flag & SLOAD)
 353:                 total.t_rm += p->p_size;
 354: #else
 355:             total.t_vm += p->p_dsize + p->p_ssize + USIZE;
 356:             if (p->p_flag & SLOAD)
 357:                 total.t_rm += p->p_dsize + p->p_ssize + USIZE;
 358: #endif
 359: #endif
 360:             switch (p->p_stat) {
 361: 
 362:             case SSLEEP:
 363:             case SSTOP:
 364:                 if (p->p_pri <= PZERO)
 365:                     nrun++;
 366: #ifdef UCB_METER
 367:                 if (p->p_flag & SLOAD) {
 368:                     if (p->p_pri <= PZERO)
 369:                         total.t_dw++;
 370:                     else if (p->p_slptime < MAXSLP)
 371:                         total.t_sl++;
 372:                 } else if (p->p_slptime < MAXSLP)
 373:                     total.t_sw++;
 374:                 if (p->p_slptime < MAXSLP)
 375:                     goto active;
 376: #endif
 377:                 break;
 378: 
 379:             case SRUN:
 380:             case SIDL:
 381:                 nrun++;
 382: #ifdef UCB_METER
 383:                 if (p->p_flag & SLOAD)
 384:                     total.t_rq++;
 385:                 else
 386:                     total.t_sw++;
 387: active:
 388: #ifndef VIRUS_VFORK
 389:                 total.t_avm += p->p_size;
 390:                 if (p->p_flag & SLOAD)
 391:                     total.t_arm += p->p_size;
 392: #else
 393:                 total.t_avm += p->p_dsize + p->p_ssize + USIZE;
 394:                 if (p->p_flag & SLOAD)
 395:                     total.t_arm +=
 396:                         p->p_dsize + p->p_ssize + USIZE;
 397: #endif
 398:                 if (p->p_textp) {
 399:                     total.t_avmtxt += p->p_textp->x_size;
 400:                     nt = p->p_textp-text;
 401:                     if (counted[nt]==0) {
 402:                         counted[nt]=1;
 403:                         if (p->p_textp->x_ccount)
 404:                             total.t_armtxt +=
 405:                                 p->p_textp->x_size;
 406:                     }
 407:                 }
 408: #endif
 409:                 break;
 410:             }
 411:         }
 412:     }
 413: #ifdef UCB_METER
 414:     total.t_vm += total.t_vmtxt;
 415:     total.t_avm += total.t_avmtxt;
 416:     total.t_rm += total.t_rmtxt;
 417:     total.t_arm += total.t_armtxt;
 418:     total.t_free = avefree;
 419: #endif
 420:     loadav(avenrun, nrun);
 421: }
 422: 
 423: /*
 424:  * Compute Tenex style load average.  This code is adapted from similar
 425:  * code by Bill Joy on the Vax system.  The major change is that we
 426:  * avoid floating point since not all pdp-11's have it.  This makes
 427:  * the code quite hard to read - it was derived with some algebra.
 428:  *
 429:  * "floating point" numbers here are stored in a 16 bit short, with
 430:  * 8 bits on each side of the decimal point.  Some partial products
 431:  * will have 16 bits to the right.
 432:  */
 433: 
 434:     /*
 435: 	 * The Vax algorithm is:
 436: 	 *
 437: 	 * /*
 438: 	 *  * Constants for averages over 1, 5, and 15 minutes
 439: 	 *  * when sampling at 5 second intervals.
 440: 	 *  * /
 441: 	 * double	cexp[3] = {
 442: 	 * 	0.9200444146293232,	/* exp(-1/12) * /
 443: 	 * 	0.9834714538216174,	/* exp(-1/60) * /
 444: 	 * 	0.9944598480048967,	/* exp(-1/180) * /
 445: 	 * };
 446: 	 *
 447: 	 * /*
 448: 	 *  * Compute a tenex style load average of a quantity on
 449: 	 *  * 1, 5 and 15 minute intervals.
 450: 	 *  * /
 451: 	 * loadav(avg, n)
 452: 	 * 	register double *avg;
 453: 	 * 	int n;
 454: 	 * {
 455: 	 * 	register int i;
 456: 	 *
 457: 	 * 	for (i = 0; i < 3; i++)
 458: 	 * 		avg[i] = cexp[i] * avg[i] + n * (1.0 - cexp[i]);
 459: 	 * }
 460: 	 */
 461: 
 462: long cexp[3] = {
 463:     0353,   /* 256*exp(-1/12) */
 464:     0373,   /* 256*exp(-1/60) */
 465:     0376,   /* 256*exp(-1/180) */
 466: };
 467: 
 468: loadav(avg, n)
 469:     register short *avg;
 470:     register n;
 471: {
 472:     register int i;
 473: 
 474:     for (i = 0; i < 3; i++)
 475:         avg[i] = (cexp[i] * (avg[i]-(n<<8)) + (((long)n)<<16)) >> 8;
 476: }
 477: #endif

Defined functions

clock defined in line 65; used 4 times
loadav defined in line 468; used 1 times
meter defined in line 294; used 1 times
vmtotal defined in line 317; used 1 times

Defined variables

avenrun defined in line 289; used 1 times
cexp defined in line 462; used 1 times
ifnetslow defined in line 41; used 2 times
netoff defined in line 42; used 1 times
protofast defined in line 40; used 2 times
protoslow defined in line 39; used 2 times

Defined macros

SCHMAG defined in line 45; used 1 times
ave defined in line 290; used 1 times
ctok defined in line 292; used 1 times
Last modified: 1983-09-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1101
Valid CSS Valid XHTML 1.0 Strict