# 2.11BSD#431 - /usr/src/sys/sys/kern_clock.c

##### Functions

    gatherstats       X
    hardclock         X
    hzto              X
    profil            X
    softclock         X
    timeout           X
    untimeout         X

##### Variables

    dk_ndrive         X

##### struct's

    a                 X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)kern_clock.c	1.4 (2.11BSD GTE) 1997/2/14
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/psl.h"
      11: #include "../machine/seg.h"
      12:
      13: #include "user.h"
      14: #include "proc.h"
      15: #include "callout.h"
      16: #include "dk.h"
      17: #include "kernel.h"
      18: #include "systm.h"
      19:
      20: /*
      21:  * The hz hardware interval timer.
      22:  * We update the events relating to real time.
      23:  * Also gather statistics.
      24:  *
      25:  *	reprime clock
      26:  *	implement callouts
      27:  *	maintain user/system times
      28:  *	maintain date
      29:  *	profile
      30:  */
      31: /*ARGSUSED*/
      32: hardclock(dev,sp,r1,ov,nps,r0,pc,ps)
      33:     dev_t dev;
      34:     caddr_t sp, pc;
      35:     int r1, ov, nps, r0, ps;
      36: {
      37:     register struct callout *p1;
      38:     register struct proc *p;
      39:     register int needsoft = 0;
      40:     mapinfo map;
      41:
      42:     savemap(map);       /* ensure normal mapping of kernel data */
      43:
      44:     /*
      45: 	 * Update real-time timeout queue.
      46: 	 * At front of queue are some number of events which are ``due''.
      47: 	 * The time to these is <= 0 and if negative represents the
      48: 	 * number of ticks which have passed since it was supposed to happen.
      49: 	 * The rest of the q elements (times > 0) are events yet to happen,
      50: 	 * where the time for each is given as a delta from the previous.
      51: 	 * Decrementing just the first of these serves to decrement the time
      52: 	 * to all events.
      53: 	 */
      54:     p1 = calltodo.c_next;
      55:     while (p1) {
      56:         if (--p1->c_time > 0)
      57:             break;
      58:         needsoft = 1;
      59:         if (p1->c_time == 0)
      60:             break;
      61:         p1 = p1->c_next;
      62:     }
      63:
      64:     /*
      65: 	 * Charge the time out based on the mode the cpu is in.
      66: 	 * Here again we fudge for the lack of proper interval timers
      67: 	 * assuming that the current state has been around at least
      68: 	 * one tick.
      69: 	 */
      70:     if (USERMODE(ps)) {
      71:         if (u.u_prof.pr_scale)
      72:             needsoft = 1;
      73:         /*
      74: 		 * CPU was in user state.  Increment
      75: 		 * user time counter, and process process-virtual time
      76: 		 * interval timer.
      77: 		 */
      78:         u.u_ru.ru_utime++;
      79:         if (u.u_timer[ITIMER_VIRTUAL - 1].it_value &&
      80:             !--u.u_timer[ITIMER_VIRTUAL - 1].it_value) {
      81:             psignal(u.u_procp, SIGVTALRM);
      82:             u.u_timer[ITIMER_VIRTUAL - 1].it_value =
      83:                 u.u_timer[ITIMER_VIRTUAL - 1].it_interval;
      84:         }
      85:     } else {
      86:         /*
      87: 		 * CPU was in system state.
      88: 		 */
      89:         if (!noproc)
      90:             u.u_ru.ru_stime++;
      91:     }
      92:
      93:     /*
      94: 	 * If the cpu is currently scheduled to a process, then
      95: 	 * charge it with resource utilization for a tick, updating
      96: 	 * statistics which run in (user+system) virtual time,
      97: 	 * such as the cpu time limit and profiling timers.
      98: 	 * This assumes that the current process has been running
      99: 	 * the entire last tick.
     100: 	 */
     101:     if (noproc == 0) {
     102:         p = u.u_procp;
     103:         if (++p->p_cpu == 0)
     104:             p->p_cpu--;
     105:         if ((u.u_ru.ru_utime+u.u_ru.ru_stime+1) >
     106:             u.u_rlimit[RLIMIT_CPU].rlim_cur) {
     107:             psignal(p, SIGXCPU);
     108:             if (u.u_rlimit[RLIMIT_CPU].rlim_cur <
     109:                 u.u_rlimit[RLIMIT_CPU].rlim_max)
     110:                 u.u_rlimit[RLIMIT_CPU].rlim_cur += 5 * hz;
     111:         }
     112:         if (u.u_timer[ITIMER_PROF - 1].it_value &&
     113:             !--u.u_timer[ITIMER_PROF - 1].it_value) {
     114:             psignal(p, SIGPROF);
     115:             u.u_timer[ITIMER_PROF - 1].it_value =
     116:                 u.u_timer[ITIMER_PROF - 1].it_interval;
     117:         }
     118:     }
     119:
     120: #ifdef UCB_METER
     121:     gatherstats(pc,ps);
     122: #endif
     123:
     124:     /*
     125: 	 * Increment the time-of-day, process callouts at a very
     126: 	 * low cpu priority, so we don't keep the relatively  high
     127: 	 * clock interrupt priority any longer than necessary.
     128: 	 */
     129:     if (adjdelta)
     130:         if (adjdelta > 0) {
     131:             ++lbolt;
     132:             --adjdelta;
     133:         } else {
     134:             --lbolt;
     135:             ++adjdelta;
     136:         }
     137:     if (++lbolt >= hz) {
     138:         lbolt -= hz;
     139:         ++time.tv_sec;
     140:     }
     141:
     142:     if (needsoft && BASEPRI(ps)) {  /* if ps is high, just return */
     143:         (void) _splsoftclock();
     144:         softclock(pc,ps);
     145:     }
     146:     restormap(map);
     147: }
     148:
     149: #ifdef UCB_METER
     150: int dk_ndrive = DK_NDRIVE;
     151: /*
     152:  * Gather statistics on resource utilization.
     153:  *
     154:  * We make a gross assumption: that the system has been in the
     155:  * state it is in (user state, kernel state, interrupt state,
     156:  * or idle state) for the entire last time interval, and
     157:  * update statistics accordingly.
     158:  */
     159: /*ARGSUSED*/
     160: gatherstats(pc, ps)
     161:     caddr_t pc;
     162:     int ps;
     163: {
     164:     register int cpstate, s;
     165:
     166:     /*
     167: 	 * Determine what state the cpu is in.
     168: 	 */
     169:     if (USERMODE(ps)) {
     170:         /*
     171: 		 * CPU was in user state.
     172: 		 */
     173:         if (u.u_procp->p_nice > NZERO)
     174:             cpstate = CP_NICE;
     175:         else
     176:             cpstate = CP_USER;
     177:     } else {
     178:         /*
     179: 		 * CPU was in system state.  If profiling kernel
     180: 		 * increment a counter.  If no process is running
     181: 		 * then this is a system tick if we were running
     182: 		 * at a non-zero IPL (in a driver).  If a process is running,
     183: 		 * then we charge it with system time even if we were
     184: 		 * at a non-zero IPL, since the system often runs
     185: 		 * this way during processing of system calls.
     186: 		 * This is approximate, but the lack of true interval
     187: 		 * timers makes doing anything else difficult.
     188: 		 */
     189:         cpstate = CP_SYS;
     190:         if (noproc && BASEPRI(ps))
     191:             cpstate = CP_IDLE;
     192:     }
     193:     /*
     194: 	 * We maintain statistics shown by user-level statistics
     195: 	 * programs:  the amount of time in each cpu state, and
     196: 	 * the amount of time each of DK_NDRIVE ``drives'' is busy.
     197: 	 */
     198:     cp_time[cpstate]++;
     199:     for (s = 0; s < DK_NDRIVE; s++)
     200:         if (dk_busy & (1 << s))
     201:             dk_time[s]++;
     202: }
     203: #endif UCB_METER
     204:
     205: /*
     206:  * Software priority level clock interrupt.
     207:  * Run periodic events from timeout queue.
     208:  */
     209: softclock(pc, ps)
     210:     caddr_t pc;
     211:     int ps;
     212: {
     213:     for (;;) {
     214:         register struct callout *p1;
     215:         register caddr_t arg;
     216:         register int (*func)();
     217:         register int a, s;
     218:
     219:         s = splhigh();
     220:         if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) {
     221:             splx(s);
     222:             break;
     223:         }
     224:         arg = p1->c_arg; func = p1->c_func; a = p1->c_time;
     225:         calltodo.c_next = p1->c_next;
     226:         p1->c_next = callfree;
     227:         callfree = p1;
     228:         splx(s);
     229: #ifdef INET
     230:         if (ISSUPERADD(func))
     231:             KScall(KERNELADD(func), sizeof(arg) + sizeof(a),
     232:                 arg, a);
     233:         else
     234: #endif
     235:         (*func)(arg, a);
     236:     }
     237:     /*
     238: 	 * If trapped user-mode and profiling, give it
     239: 	 * a profiling tick.
     240: 	 */
     241:     if (USERMODE(ps)) {
     242:         register struct proc *p = u.u_procp;
     243:
     244:         if (u.u_prof.pr_scale)
     245:             addupc(pc, &u.u_prof, 1);
     246:         /*
     247: 		 * Check to see if process has accumulated
     248: 		 * more than 10 minutes of user time.  If so
     249: 		 * reduce priority to give others a chance.
     250: 		 */
     251:
     252:         if (p->p_uid && p->p_nice == NZERO &&
     253:             u.u_ru.ru_utime > 10L * 60L * hz) {
     254:             p->p_nice = NZERO+4;
     255:                 (void) setpri(p);
     256:         }
     257:     }
     258: }
     259:
     260: /*
     261:  * Arrange that (*fun)(arg) is called in t/hz seconds.
     262:  */
     263: timeout(fun, arg, t)
     264:     int (*fun)();
     265:     caddr_t arg;
     266:     register int t;
     267: {
     268:     register struct callout *p1, *p2, *pnew;
     269:     register int s = splclock();
     270:
     271:     if (t <= 0)
     272:         t = 1;
     273:     pnew = callfree;
     274:     if (pnew == NULL)
     275:         panic("timeout table overflow");
     276:     callfree = pnew->c_next;
     277:     pnew->c_arg = arg;
     278:     pnew->c_func = fun;
     279:     for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2)
     280:         if (p2->c_time > 0)
     281:             t -= p2->c_time;
     282:     p1->c_next = pnew;
     283:     pnew->c_next = p2;
     284:     pnew->c_time = t;
     285:     if (p2)
     286:         p2->c_time -= t;
     287:     splx(s);
     288: }
     289:
     290: /*
     291:  * untimeout is called to remove a function timeout call
     292:  * from the callout structure.
     293:  */
     294: untimeout(fun, arg)
     295:     int (*fun)();
     296:     caddr_t arg;
     297: {
     298:     register struct callout *p1, *p2;
     299:     register int s;
     300:
     301:     s = splclock();
     302:     for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) {
     303:         if (p2->c_func == fun && p2->c_arg == arg) {
     304:             if (p2->c_next && p2->c_time > 0)
     305:                 p2->c_next->c_time += p2->c_time;
     306:             p1->c_next = p2->c_next;
     307:             p2->c_next = callfree;
     308:             callfree = p2;
     309:             break;
     310:         }
     311:     }
     312:     splx(s);
     313: }
     314:
     315: profil()
     316: {
     317:     register struct a {
     318:         short   *bufbase;
     319:         unsigned bufsize;
     320:         unsigned pcoffset;
     321:         unsigned pcscale;
     322:     } *uap = (struct a *)u.u_ap;
     323:     register struct uprof *upp = &u.u_prof;
     324:
     325:     upp->pr_base = uap->bufbase;
     326:     upp->pr_size = uap->bufsize;
     327:     upp->pr_off = uap->pcoffset;
     328:     upp->pr_scale = uap->pcscale;
     329: }
     330:
     331: /*
     332:  * Compute number of hz until specified time.
     333:  * Used to compute third argument to timeout() from an
     334:  * absolute time.
     335:  */
     336: hzto(tv)
     337:     register struct timeval *tv;
     338: {
     339:     register long ticks;
     340:     register long sec;
     341:     register int s = splhigh();
     342:
     343:     /*
     344: 	 * If number of milliseconds will fit in 32 bit arithmetic,
     345: 	 * then compute number of milliseconds to time and scale to
     346: 	 * ticks.  Otherwise just compute number of hz in time, rounding
     347: 	 * times greater than representible to maximum value.
     348: 	 *
     349: 	 * Delta times less than 25 days can be computed ``exactly''.
     350: 	 * Maximum value for any timeout in 10ms ticks is 250 days.
     351: 	 */
     352:     sec = tv->tv_sec - time.tv_sec;
     353:     if (sec <= 0x7fffffff / 1000 - 1000)
     354:         ticks = ((tv->tv_sec - time.tv_sec) * 1000 +
     355:             (tv->tv_usec - time.tv_usec) / 1000) / (1000/hz);
     356:     else if (sec <= 0x7fffffff / hz)
     357:         ticks = sec * hz;
     358:     else
     359:         ticks = 0x7fffffff;
     360:     splx(s);
     361: #ifdef pdp11
     362:     /* stored in an "int", so 16-bit max */
     363:     if (ticks > 0x7fff)
     364:         ticks = 0x7fff;
     365: #endif
     366:     return ((int)ticks);
     367: }

#### Defined functions

gatherstats defined in line 160; used 1 times

- in line 121

hardclock defined in line 32; used 1 times

- in /usr/src/sys/pdp/scb.s line 325

hzto defined in line 336; used 1 times

- in /usr/src/sys/sys/sys_generic.c line 404

profil defined in line 315; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 88, 154

softclock defined in line 209; used 1 times

- in line 144

timeout defined in line 263; used 26 times

- in /usr/src/sys/pdp/net_mac.h line 180-182(2)
- in /usr/src/sys/pdpuba/br.c line 224, 326
- in /usr/src/sys/pdpuba/dh.c line 142, 638
- in /usr/src/sys/pdpuba/dr.c line 75, 315
- in /usr/src/sys/pdpuba/dz.c line 111, 439, 560-561(2), 577
- in /usr/src/sys/pdpuba/lp.c line 94, 285, 296
- in /usr/src/sys/pdpuba/ra.c line 377, 419
- in /usr/src/sys/pdpuba/tm.c line 169, 586
- in /usr/src/sys/pdpuba/tmscp.c line 662, 707, 836
- in /usr/src/sys/sys/kern_synch.c line 72, 146
- in /usr/src/sys/sys/tty.c line 1303

untimeout defined in line 294; used 3 times

- in /usr/src/sys/pdpuba/tmscp.c line 709, 839
- in /usr/src/sys/sys/kern_synch.c line 186

#### Defined variables

dk_ndrive defined in line 150; never used

#### Defined struct's

a defined in line 317; used 2 times

- in line 322(2)

Last modified: 1997-02-15 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 940 |