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: }