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_time.c	1.5 (2.11BSD) 2000/4/9
   7:  */
   8: 
   9: #include "param.h"
  10: #include "user.h"
  11: #include "proc.h"
  12: #include "kernel.h"
  13: #include "systm.h"
  14: 
  15: /*
  16:  * Time of day and interval timer support.
  17:  *
  18:  * These routines provide the kernel entry points to get and set
  19:  * the time-of-day.
  20:  */
  21: 
  22: gettimeofday()
  23: {
  24:     register struct a {
  25:         struct  timeval *tp;
  26:         struct  timezone *tzp;
  27:     } *uap = (struct a *)u.u_ap;
  28:     struct timeval atv;
  29:     int s;
  30:     register u_int  ms;
  31: 
  32:     if (uap->tp) {
  33:         /*
  34: 		 * We don't resolve the milliseconds on every clock tick; it's
  35: 		 * easier to do it here.  Long casts are out of paranoia.
  36: 		 */
  37:         s = splhigh(); atv = time; ms = lbolt; splx(s);
  38:         atv.tv_usec = (long)ms * mshz;
  39:         u.u_error = copyout((caddr_t)&atv, (caddr_t)(uap->tp),
  40:             sizeof(atv));
  41:         if (u.u_error)
  42:             return;
  43:     }
  44:     if (uap->tzp)
  45:         u.u_error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
  46:             sizeof (tz));
  47: }
  48: 
  49: settimeofday()
  50: {
  51:     register struct a {
  52:         struct  timeval *tv;
  53:         struct  timezone *tzp;
  54:     } *uap = (struct a *)u.u_ap;
  55:     struct timeval atv;
  56:     struct timezone atz;
  57: 
  58:     if (uap->tv) {
  59:         u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
  60:             sizeof (struct timeval));
  61:         if (u.u_error)
  62:             return;
  63:         setthetime(&atv);
  64:         if  (u.u_error)
  65:             return;
  66:     }
  67:     if (uap->tzp && suser()) {
  68:         u.u_error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
  69:             sizeof (atz));
  70:         if (u.u_error == 0)
  71:             tz = atz;
  72:     }
  73: }
  74: 
  75: setthetime(tv)
  76:     register struct timeval *tv;
  77:     {
  78:     int s;
  79: 
  80:     if  (!suser())
  81:         return;
  82: #ifdef  NOTNOW
  83: /*
  84:  * If the system is secure, we do not allow the time to be set to an
  85:  * earlier value.  The time may be slowed (using adjtime) but not set back.
  86:  *
  87:  * NOTE:  Can not do this until ntpd is updated to deal with the coarse (50, 60
  88:  *	  hz) clocks.  Ntpd wants to adjust time system clock a few microseconds
  89:  *	  at a time (which gets rounded to 0 in adjtime below). If that fails
  90:  *	  ntpd uses settimeofday to step the time backwards which obviously
  91:  *	  will fail if the next 'if' is enabled - all that does is fill up the
  92:  *	  logfiles with "can't set time" messages and the time keeps drifting.
  93: */
  94:     if  (securelevel > 0 && timercmp(tv, &time, <))
  95:         {
  96:         u.u_error = EPERM;  /* XXX */
  97:         return;
  98:         }
  99: #endif
 100: /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
 101:     boottime.tv_sec += tv->tv_sec - time.tv_sec;
 102:     s = splhigh();
 103:     time = *tv; lbolt = time.tv_usec / mshz;
 104:     splx(s);
 105: #ifdef  notyet
 106:     /*
 107: 	 * if you have a time of day board, use it here
 108: 	 */
 109:     resettodr();
 110: #endif
 111:     }
 112: 
 113: adjtime()
 114: {
 115:     register struct a {
 116:         struct timeval *delta;
 117:         struct timeval *olddelta;
 118:     } *uap = (struct a *)u.u_ap;
 119:     struct timeval atv;
 120:     register int s;
 121:     long adjust;
 122: 
 123:     if (!suser())
 124:         return;
 125:     u.u_error = copyin((caddr_t)uap->delta, (caddr_t)&atv,
 126:         sizeof (struct timeval));
 127:     if (u.u_error)
 128:         return;
 129:     adjust = (atv.tv_sec * hz) + (atv.tv_usec / mshz);
 130:     /* if unstoreable values, just set the clock */
 131:     if (adjust > 0x7fff || adjust < 0x8000) {
 132:         s = splclock();
 133:         time.tv_sec += atv.tv_sec;
 134:         lbolt += atv.tv_usec / mshz;
 135:         while (lbolt >= hz) {
 136:             lbolt -= hz;
 137:             ++time.tv_sec;
 138:         }
 139:         splx(s);
 140:         if (!uap->olddelta)
 141:             return;
 142:         atv.tv_sec = atv.tv_usec = 0;
 143:     } else {
 144:         if (!uap->olddelta) {
 145:             adjdelta = adjust;
 146:             return;
 147:         }
 148:         atv.tv_sec = adjdelta / hz;
 149:         atv.tv_usec = (adjdelta % hz) * mshz;
 150:         adjdelta = adjust;
 151:     }
 152:     (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
 153:         sizeof (struct timeval));
 154: }
 155: 
 156: getitimer()
 157: {
 158:     register struct a {
 159:         u_int   which;
 160:         struct  itimerval *itv;
 161:     } *uap = (struct a *)u.u_ap;
 162:     struct itimerval aitv;
 163:     register int s;
 164: 
 165:     if (uap->which > ITIMER_PROF) {
 166:         u.u_error = EINVAL;
 167:         return;
 168:     }
 169:     aitv.it_interval.tv_usec = 0;
 170:     aitv.it_value.tv_usec = 0;
 171:     s = splclock();
 172:     if (uap->which == ITIMER_REAL) {
 173:         register struct proc *p = u.u_procp;
 174: 
 175:         aitv.it_interval.tv_sec = p->p_realtimer.it_interval;
 176:         aitv.it_value.tv_sec = p->p_realtimer.it_value;
 177:     }
 178:     else {
 179:         register struct k_itimerval *t = &u.u_timer[uap->which - 1];
 180: 
 181:         aitv.it_interval.tv_sec = t->it_interval / hz;
 182:         aitv.it_value.tv_sec = t->it_value / hz;
 183:     }
 184:     splx(s);
 185:     u.u_error = copyout((caddr_t)&aitv, (caddr_t)uap->itv,
 186:         sizeof (struct itimerval));
 187: }
 188: 
 189: setitimer()
 190: {
 191:     register struct a {
 192:         u_int   which;
 193:         struct  itimerval *itv, *oitv;
 194:     } *uap = (struct a *)u.u_ap;
 195:     struct itimerval aitv;
 196:     register struct itimerval *aitvp;
 197:     int s;
 198: 
 199:     if (uap->which > ITIMER_PROF) {
 200:         u.u_error = EINVAL;
 201:         return;
 202:     }
 203:     aitvp = uap->itv;
 204:     if (uap->oitv) {
 205:         uap->itv = uap->oitv;
 206:         getitimer();
 207:     }
 208:     if (aitvp == 0)
 209:         return;
 210:     u.u_error = copyin((caddr_t)aitvp, (caddr_t)&aitv,
 211:         sizeof (struct itimerval));
 212:     if (u.u_error)
 213:         return;
 214:     s = splclock();
 215:     if (uap->which == ITIMER_REAL) {
 216:         register struct proc *p = u.u_procp;
 217: 
 218:         p->p_realtimer.it_value = aitv.it_value.tv_sec;
 219:         if (aitv.it_value.tv_usec)
 220:             ++p->p_realtimer.it_value;
 221:         p->p_realtimer.it_interval = aitv.it_interval.tv_sec;
 222:         if (aitv.it_interval.tv_usec)
 223:             ++p->p_realtimer.it_interval;
 224:     }
 225:     else {
 226:         register struct k_itimerval *t = &u.u_timer[uap->which - 1];
 227: 
 228:         t->it_value = aitv.it_value.tv_sec * hz;
 229:         if (aitv.it_value.tv_usec)
 230:             t->it_value += hz;
 231:         t->it_interval = aitv.it_interval.tv_sec * hz;
 232:         if (aitv.it_interval.tv_usec)
 233:             t->it_interval += hz;
 234:     }
 235:     splx(s);
 236: }
 237: 
 238: /*
 239:  * Check that a proposed value to load into the .it_value or
 240:  * .it_interval part of an interval timer is acceptable, and
 241:  * fix it to have at least minimal value (i.e. if it is less
 242:  * than the resolution of the clock, round it up.)
 243:  */
 244: itimerfix(tv)
 245:     struct timeval *tv;
 246: {
 247: 
 248:     if (tv->tv_sec < 0 || tv->tv_sec > 100000000L ||
 249:         tv->tv_usec < 0 || tv->tv_usec >= 1000000L)
 250:         return (EINVAL);
 251:     if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < (1000/hz))
 252:         tv->tv_usec = 1000/hz;
 253:     return (0);
 254: }
 255: 
 256: #ifdef NOT_CURRENTLY_IN_USE
 257: /*
 258:  * Decrement an interval timer by a specified number
 259:  * of microseconds, which must be less than a second,
 260:  * i.e. < 1000000.  If the timer expires, then reload
 261:  * it.  In this case, carry over (usec - old value) to
 262:  * reducint the value reloaded into the timer so that
 263:  * the timer does not drift.  This routine assumes
 264:  * that it is called in a context where the timers
 265:  * on which it is operating cannot change in value.
 266:  */
 267: itimerdecr(itp, usec)
 268:     register struct itimerval *itp;
 269:     int usec;
 270: {
 271: 
 272:     if (itp->it_value.tv_usec < usec) {
 273:         if (itp->it_value.tv_sec == 0) {
 274:             /* expired, and already in next interval */
 275:             usec -= itp->it_value.tv_usec;
 276:             goto expire;
 277:         }
 278:         itp->it_value.tv_usec += 1000000L;
 279:         itp->it_value.tv_sec--;
 280:     }
 281:     itp->it_value.tv_usec -= usec;
 282:     usec = 0;
 283:     if (timerisset(&itp->it_value))
 284:         return (1);
 285:     /* expired, exactly at end of interval */
 286: expire:
 287:     if (timerisset(&itp->it_interval)) {
 288:         itp->it_value = itp->it_interval;
 289:         itp->it_value.tv_usec -= usec;
 290:         if (itp->it_value.tv_usec < 0) {
 291:             itp->it_value.tv_usec += 1000000L;
 292:             itp->it_value.tv_sec--;
 293:         }
 294:     } else
 295:         itp->it_value.tv_usec = 0;      /* sec is already 0 */
 296:     return (0);
 297: }
 298: #endif /* NOT_CURRENTLY_IN_USE */
 299: 
 300: #define timevalfix  tvfix
 301: 
 302: /*
 303:  * Add and subtract routines for timevals.
 304:  * N.B.: subtract routine doesn't deal with
 305:  * results which are before the beginning,
 306:  * it just gets very confused in this case.
 307:  * Caveat emptor.
 308:  */
 309: timevaladd(t1, t2)
 310:     struct timeval *t1, *t2;
 311: {
 312: 
 313:     t1->tv_sec += t2->tv_sec;
 314:     t1->tv_usec += t2->tv_usec;
 315:     timevalfix(t1);
 316: }
 317: 
 318: #ifdef NOT_CURRENTLY_IN_USE
 319: timevalsub(t1, t2)
 320:     struct timeval *t1, *t2;
 321: {
 322: 
 323:     t1->tv_sec -= t2->tv_sec;
 324:     t1->tv_usec -= t2->tv_usec;
 325:     timevalfix(t1);
 326: }
 327: #endif
 328: 
 329: timevalfix(t1)
 330:     struct timeval *t1;
 331: {
 332: 
 333:     if (t1->tv_usec < 0) {
 334:         t1->tv_sec--;
 335:         t1->tv_usec += 1000000L;
 336:     }
 337:     if (t1->tv_usec >= 1000000L) {
 338:         t1->tv_sec++;
 339:         t1->tv_usec -= 1000000L;
 340:     }
 341: }

Defined functions

adjtime defined in line 113; used 2 times
getitimer defined in line 156; used 3 times
gettimeofday defined in line 22; used 2 times
itimerdecr defined in line 267; never used
itimerfix defined in line 244; used 1 times
setitimer defined in line 189; used 2 times
setthetime defined in line 75; used 1 times
  • in line 63
settimeofday defined in line 49; used 2 times
timevaladd defined in line 309; used 1 times
timevalfix defined in line 329; never used
timevalsub defined in line 319; never used

Defined struct's

a defined in line 191; used 10 times

Defined macros

timevalfix defined in line 300; used 2 times
Last modified: 2000-04-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3918
Valid CSS Valid XHTML 1.0 Strict