1: /*
   2:  * Copyright (c) 1982, 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_time.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "../machine/reg.h"
  10: 
  11: #include "param.h"
  12: #include "dir.h"        /* XXX */
  13: #include "user.h"
  14: #include "kernel.h"
  15: #include "inode.h"
  16: #include "proc.h"
  17: 
  18: /*
  19:  * Time of day and interval timer support.
  20:  *
  21:  * These routines provide the kernel entry points to get and set
  22:  * the time-of-day and per-process interval timers.  Subroutines
  23:  * here provide support for adding and subtracting timeval structures
  24:  * and decrementing interval timers, optionally reloading the interval
  25:  * timers when they expire.
  26:  */
  27: 
  28: gettimeofday()
  29: {
  30:     register struct a {
  31:         struct  timeval *tp;
  32:         struct  timezone *tzp;
  33:     } *uap = (struct a *)u.u_ap;
  34:     struct timeval atv;
  35: 
  36:     microtime(&atv);
  37:     u.u_error = copyout((caddr_t)&atv, (caddr_t)uap->tp, sizeof (atv));
  38:     if (u.u_error)
  39:         return;
  40:     if (uap->tzp == 0)
  41:         return;
  42:     /* SHOULD HAVE PER-PROCESS TIMEZONE */
  43:     u.u_error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz));
  44: }
  45: 
  46: settimeofday()
  47: {
  48:     register struct a {
  49:         struct  timeval *tv;
  50:         struct  timezone *tzp;
  51:     } *uap = (struct a *)u.u_ap;
  52:     struct timeval atv;
  53:     struct timezone atz;
  54: 
  55:     u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
  56:         sizeof (struct timeval));
  57:     if (u.u_error)
  58:         return;
  59:     setthetime(&atv);
  60:     if (uap->tzp && suser()) {
  61:         u.u_error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
  62:             sizeof (atz));
  63:         if (u.u_error == 0)
  64:             tz = atz;
  65:     }
  66: }
  67: 
  68: setthetime(tv)
  69:     struct timeval *tv;
  70: {
  71:     int s;
  72: 
  73:     if (!suser())
  74:         return;
  75: /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
  76:     boottime.tv_sec += tv->tv_sec - time.tv_sec;
  77:     s = splhigh(); time = *tv; splx(s);
  78:     resettodr();
  79: }
  80: 
  81: extern  int tickadj;            /* "standard" clock skew, us./tick */
  82: int tickdelta;          /* current clock skew, us. per tick */
  83: long    timedelta;          /* unapplied time correction, us. */
  84: long    bigadj = 1000000;       /* use 10x skew above bigadj us. */
  85: 
  86: adjtime()
  87: {
  88:     register struct a {
  89:         struct timeval *delta;
  90:         struct timeval *olddelta;
  91:     } *uap = (struct a *)u.u_ap;
  92:     struct timeval atv, oatv;
  93:     register long ndelta;
  94:     int s;
  95: 
  96:     if (!suser())
  97:         return;
  98:     u.u_error = copyin((caddr_t)uap->delta, (caddr_t)&atv,
  99:         sizeof (struct timeval));
 100:     if (u.u_error)
 101:         return;
 102:     ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
 103:     if (timedelta == 0)
 104:         if (ndelta > bigadj)
 105:             tickdelta = 10 * tickadj;
 106:         else
 107:             tickdelta = tickadj;
 108:     if (ndelta % tickdelta)
 109:         ndelta = ndelta / tickadj * tickadj;
 110: 
 111:     s = splclock();
 112:     if (uap->olddelta) {
 113:         oatv.tv_sec = timedelta / 1000000;
 114:         oatv.tv_usec = timedelta % 1000000;
 115:     }
 116:     timedelta = ndelta;
 117:     splx(s);
 118: 
 119:     if (uap->olddelta)
 120:         (void) copyout((caddr_t)&oatv, (caddr_t)uap->olddelta,
 121:             sizeof (struct timeval));
 122: }
 123: 
 124: /*
 125:  * Get value of an interval timer.  The process virtual and
 126:  * profiling virtual time timers are kept in the u. area, since
 127:  * they can be swapped out.  These are kept internally in the
 128:  * way they are specified externally: in time until they expire.
 129:  *
 130:  * The real time interval timer is kept in the process table slot
 131:  * for the process, and its value (it_value) is kept as an
 132:  * absolute time rather than as a delta, so that it is easy to keep
 133:  * periodic real-time signals from drifting.
 134:  *
 135:  * Virtual time timers are processed in the hardclock() routine of
 136:  * kern_clock.c.  The real time timer is processed by a timeout
 137:  * routine, called from the softclock() routine.  Since a callout
 138:  * may be delayed in real time due to interrupt processing in the system,
 139:  * it is possible for the real time timeout routine (realitexpire, given below),
 140:  * to be delayed in real time past when it is supposed to occur.  It
 141:  * does not suffice, therefore, to reload the real timer .it_value from the
 142:  * real time timers .it_interval.  Rather, we compute the next time in
 143:  * absolute time the timer should go off.
 144:  */
 145: getitimer()
 146: {
 147:     register struct a {
 148:         u_int   which;
 149:         struct  itimerval *itv;
 150:     } *uap = (struct a *)u.u_ap;
 151:     struct itimerval aitv;
 152:     int s;
 153: 
 154:     if (uap->which > 2) {
 155:         u.u_error = EINVAL;
 156:         return;
 157:     }
 158:     s = splclock();
 159:     if (uap->which == ITIMER_REAL) {
 160:         /*
 161: 		 * Convert from absoulte to relative time in .it_value
 162: 		 * part of real time timer.  If time for real time timer
 163: 		 * has passed return 0, else return difference between
 164: 		 * current time and time for the timer to go off.
 165: 		 */
 166:         aitv = u.u_procp->p_realtimer;
 167:         if (timerisset(&aitv.it_value))
 168:             if (timercmp(&aitv.it_value, &time, <))
 169:                 timerclear(&aitv.it_value);
 170:             else
 171:                 timevalsub(&aitv.it_value, &time);
 172:     } else
 173:         aitv = u.u_timer[uap->which];
 174:     splx(s);
 175:     u.u_error = copyout((caddr_t)&aitv, (caddr_t)uap->itv,
 176:         sizeof (struct itimerval));
 177:     splx(s);
 178: }
 179: 
 180: setitimer()
 181: {
 182:     register struct a {
 183:         u_int   which;
 184:         struct  itimerval *itv, *oitv;
 185:     } *uap = (struct a *)u.u_ap;
 186:     struct itimerval aitv, *aitvp;
 187:     int s;
 188:     register struct proc *p = u.u_procp;
 189: 
 190:     if (uap->which > 2) {
 191:         u.u_error = EINVAL;
 192:         return;
 193:     }
 194:     aitvp = uap->itv;
 195:     if (uap->oitv) {
 196:         uap->itv = uap->oitv;
 197:         getitimer();
 198:     }
 199:     if (aitvp == 0)
 200:         return;
 201:     u.u_error = copyin((caddr_t)aitvp, (caddr_t)&aitv,
 202:         sizeof (struct itimerval));
 203:     if (u.u_error)
 204:         return;
 205:     if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) {
 206:         u.u_error = EINVAL;
 207:         return;
 208:     }
 209:     s = splclock();
 210:     if (uap->which == ITIMER_REAL) {
 211:         untimeout(realitexpire, (caddr_t)p);
 212:         if (timerisset(&aitv.it_value)) {
 213:             timevaladd(&aitv.it_value, &time);
 214:             timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
 215:         }
 216:         p->p_realtimer = aitv;
 217:     } else
 218:         u.u_timer[uap->which] = aitv;
 219:     splx(s);
 220: }
 221: 
 222: /*
 223:  * Real interval timer expired:
 224:  * send process whose timer expired an alarm signal.
 225:  * If time is not set up to reload, then just return.
 226:  * Else compute next time timer should go off which is > current time.
 227:  * This is where delay in processing this timeout causes multiple
 228:  * SIGALRM calls to be compressed into one.
 229:  */
 230: realitexpire(p)
 231:     register struct proc *p;
 232: {
 233:     int s;
 234: 
 235:     psignal(p, SIGALRM);
 236:     if (!timerisset(&p->p_realtimer.it_interval)) {
 237:         timerclear(&p->p_realtimer.it_value);
 238:         return;
 239:     }
 240:     for (;;) {
 241:         s = splclock();
 242:         timevaladd(&p->p_realtimer.it_value,
 243:             &p->p_realtimer.it_interval);
 244:         if (timercmp(&p->p_realtimer.it_value, &time, >)) {
 245:             timeout(realitexpire, (caddr_t)p,
 246:                 hzto(&p->p_realtimer.it_value));
 247:             splx(s);
 248:             return;
 249:         }
 250:         splx(s);
 251:     }
 252: }
 253: 
 254: /*
 255:  * Check that a proposed value to load into the .it_value or
 256:  * .it_interval part of an interval timer is acceptable, and
 257:  * fix it to have at least minimal value (i.e. if it is less
 258:  * than the resolution of the clock, round it up.)
 259:  */
 260: itimerfix(tv)
 261:     struct timeval *tv;
 262: {
 263: 
 264:     if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
 265:         tv->tv_usec < 0 || tv->tv_usec >= 1000000)
 266:         return (EINVAL);
 267:     if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
 268:         tv->tv_usec = tick;
 269:     return (0);
 270: }
 271: 
 272: /*
 273:  * Decrement an interval timer by a specified number
 274:  * of microseconds, which must be less than a second,
 275:  * i.e. < 1000000.  If the timer expires, then reload
 276:  * it.  In this case, carry over (usec - old value) to
 277:  * reducint the value reloaded into the timer so that
 278:  * the timer does not drift.  This routine assumes
 279:  * that it is called in a context where the timers
 280:  * on which it is operating cannot change in value.
 281:  */
 282: itimerdecr(itp, usec)
 283:     register struct itimerval *itp;
 284:     int usec;
 285: {
 286: 
 287:     if (itp->it_value.tv_usec < usec) {
 288:         if (itp->it_value.tv_sec == 0) {
 289:             /* expired, and already in next interval */
 290:             usec -= itp->it_value.tv_usec;
 291:             goto expire;
 292:         }
 293:         itp->it_value.tv_usec += 1000000;
 294:         itp->it_value.tv_sec--;
 295:     }
 296:     itp->it_value.tv_usec -= usec;
 297:     usec = 0;
 298:     if (timerisset(&itp->it_value))
 299:         return (1);
 300:     /* expired, exactly at end of interval */
 301: expire:
 302:     if (timerisset(&itp->it_interval)) {
 303:         itp->it_value = itp->it_interval;
 304:         itp->it_value.tv_usec -= usec;
 305:         if (itp->it_value.tv_usec < 0) {
 306:             itp->it_value.tv_usec += 1000000;
 307:             itp->it_value.tv_sec--;
 308:         }
 309:     } else
 310:         itp->it_value.tv_usec = 0;      /* sec is already 0 */
 311:     return (0);
 312: }
 313: 
 314: /*
 315:  * Add and subtract routines for timevals.
 316:  * N.B.: subtract routine doesn't deal with
 317:  * results which are before the beginning,
 318:  * it just gets very confused in this case.
 319:  * Caveat emptor.
 320:  */
 321: timevaladd(t1, t2)
 322:     struct timeval *t1, *t2;
 323: {
 324: 
 325:     t1->tv_sec += t2->tv_sec;
 326:     t1->tv_usec += t2->tv_usec;
 327:     timevalfix(t1);
 328: }
 329: 
 330: timevalsub(t1, t2)
 331:     struct timeval *t1, *t2;
 332: {
 333: 
 334:     t1->tv_sec -= t2->tv_sec;
 335:     t1->tv_usec -= t2->tv_usec;
 336:     timevalfix(t1);
 337: }
 338: 
 339: timevalfix(t1)
 340:     struct timeval *t1;
 341: {
 342: 
 343:     if (t1->tv_usec < 0) {
 344:         t1->tv_sec--;
 345:         t1->tv_usec += 1000000;
 346:     }
 347:     if (t1->tv_usec >= 1000000) {
 348:         t1->tv_sec++;
 349:         t1->tv_usec -= 1000000;
 350:     }
 351: }

Defined functions

adjtime defined in line 86; used 2 times
getitimer defined in line 145; used 3 times
gettimeofday defined in line 28; used 2 times
itimerdecr defined in line 282; used 2 times
itimerfix defined in line 260; used 3 times
realitexpire defined in line 230; used 4 times
setitimer defined in line 180; used 2 times
setthetime defined in line 68; used 2 times
settimeofday defined in line 46; used 2 times
timevalfix defined in line 339; used 2 times
timevalsub defined in line 330; used 2 times

Defined variables

bigadj defined in line 84; used 1 times
tickdelta defined in line 82; used 3 times
timedelta defined in line 83; used 4 times

Defined struct's

a defined in line 182; used 10 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1516
Valid CSS Valid XHTML 1.0 Strict