1*9757Ssam /* kern_time.c 5.12 82/12/17 */ 27424Sroot 3*9757Ssam #include "../machine/reg.h" 4*9757Ssam 57424Sroot #include "../h/param.h" 68034Sroot #include "../h/dir.h" /* XXX */ 77424Sroot #include "../h/user.h" 88034Sroot #include "../h/kernel.h" 97424Sroot #include "../h/inode.h" 107424Sroot #include "../h/proc.h" 117424Sroot 128103Sroot /* 138103Sroot * Time of day and interval timer support. 148146Sroot * 158146Sroot * These routines provide the kernel entry points to get and set 168146Sroot * the time-of-day and per-process interval timers. Subroutines 178146Sroot * here provide support for adding and subtracting timeval structures 188146Sroot * and decrementing interval timers, optionally reloading the interval 198146Sroot * timers when they expire. 208103Sroot */ 218103Sroot 228034Sroot gettimeofday() 237424Sroot { 248034Sroot register struct a { 258034Sroot struct timeval *tp; 268034Sroot struct timezone *tzp; 278034Sroot } *uap = (struct a *)u.u_ap; 288034Sroot struct timeval atv; 298103Sroot int s; 307500Sroot 318103Sroot s = spl7(); atv = time; splx(s); 328034Sroot if (copyout((caddr_t)&atv, (caddr_t)uap->tp, sizeof (atv))) { 338034Sroot u.u_error = EFAULT; 348034Sroot return; 358034Sroot } 368034Sroot if (uap->tzp == 0) 378034Sroot return; 388103Sroot /* SHOULD HAVE PER-PROCESS TIMEZONE */ 398625Sroot if (copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz))) { 408034Sroot u.u_error = EFAULT; 418034Sroot return; 428034Sroot } 437500Sroot } 447500Sroot 458034Sroot settimeofday() 467500Sroot { 478034Sroot register struct a { 488103Sroot struct timeval *tv; 498103Sroot struct timezone *tzp; 508034Sroot } *uap = (struct a *)u.u_ap; 518034Sroot struct timeval atv; 528034Sroot struct timezone atz; 537500Sroot 548034Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (struct timeval))) { 558034Sroot u.u_error = EFAULT; 568034Sroot return; 578034Sroot } 588103Sroot setthetime(&atv); 598103Sroot if (uap->tzp && suser()) { 608034Sroot if (copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof (atz))) { 618034Sroot u.u_error = EFAULT; 628034Sroot return; 638034Sroot } 648034Sroot } 657500Sroot } 667500Sroot 678103Sroot setthetime(tv) 688103Sroot struct timeval *tv; 698103Sroot { 708103Sroot int s; 718103Sroot 728103Sroot if (!suser()) 738103Sroot return; 748146Sroot /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 758103Sroot boottime.tv_sec += tv->tv_sec - time.tv_sec; 768103Sroot s = spl7(); time = *tv; splx(s); 779007Sroot resettodr(); 788103Sroot } 798103Sroot 808146Sroot /* 818146Sroot * Get value of an interval timer. The process virtual and 828146Sroot * profiling virtual time timers are kept in the u. area, since 838146Sroot * they can be swapped out. These are kept internally in the 848146Sroot * way they are specified externally: in time until they expire. 858146Sroot * 868146Sroot * The real time interval timer is kept in the process table slot 878146Sroot * for the process, and its value (it_value) is kept as an 888146Sroot * absolute time rather than as a delta, so that it is easy to keep 898146Sroot * periodic real-time signals from drifting. 908146Sroot * 918146Sroot * Virtual time timers are processed in the hardclock() routine of 928146Sroot * kern_clock.c. The real time timer is processed by a timeout 938146Sroot * routine, called from the softclock() routine. Since a callout 948146Sroot * may be delayed in real time due to interrupt processing in the system, 958146Sroot * it is possible for the real time timeout routine (realitexpire, given below), 968146Sroot * to be delayed in real time past when it is supposed to occur. It 978146Sroot * does not suffice, therefore, to reload the real timer .it_value from the 988146Sroot * real time timers .it_interval. Rather, we compute the next time in 998146Sroot * absolute time the timer should go off. 1008146Sroot */ 1018034Sroot getitimer() 1028034Sroot { 1037424Sroot register struct a { 1048034Sroot u_int which; 1058034Sroot struct itimerval *itv; 1068034Sroot } *uap = (struct a *)u.u_ap; 1078114Sroot struct itimerval aitv; 1088034Sroot int s; 1097424Sroot 1108034Sroot if (uap->which > 2) { 1118034Sroot u.u_error = EINVAL; 1128034Sroot return; 1137424Sroot } 1148034Sroot s = spl7(); 1158114Sroot if (uap->which == ITIMER_REAL) { 1168146Sroot /* 1178146Sroot * Convert from absoulte to relative time in .it_value 1188146Sroot * part of real time timer. If time for real time timer 1198146Sroot * has passed return 0, else return difference between 1208146Sroot * current time and time for the timer to go off. 1218146Sroot */ 1228114Sroot aitv = u.u_procp->p_realtimer; 1238114Sroot if (timerisset(&aitv.it_value)) 1248114Sroot if (timercmp(&aitv.it_value, &time, <)) 1258114Sroot timerclear(&aitv.it_value); 1268114Sroot else 1278114Sroot timevalsub(&aitv.it_value, &time); 1288114Sroot } else 1298114Sroot aitv = u.u_timer[uap->which]; 1308114Sroot splx(s); 1318625Sroot if (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 1328625Sroot sizeof (struct itimerval))) 1337424Sroot u.u_error = EFAULT; 1348034Sroot splx(s); 1357424Sroot } 1367424Sroot 1378034Sroot setitimer() 1387424Sroot { 1397424Sroot register struct a { 1408034Sroot u_int which; 1418103Sroot struct itimerval *itv, *oitv; 1428034Sroot } *uap = (struct a *)u.u_ap; 1438034Sroot struct itimerval aitv; 1448034Sroot int s; 1458114Sroot register struct proc *p = u.u_procp; 1467424Sroot 1478034Sroot if (uap->which > 2) { 1488034Sroot u.u_error = EINVAL; 1498103Sroot return; 1507424Sroot } 1518034Sroot if (copyin((caddr_t)uap->itv, (caddr_t)&aitv, 1528034Sroot sizeof (struct itimerval))) { 1538034Sroot u.u_error = EFAULT; 1548103Sroot return; 1558034Sroot } 1568103Sroot if (uap->oitv) { 1578103Sroot uap->itv = uap->oitv; 1588103Sroot getitimer(); 1598103Sroot } 1608103Sroot if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) { 1618103Sroot u.u_error = EINVAL; 1628103Sroot return; 1638103Sroot } 1648103Sroot s = spl7(); 1658114Sroot if (uap->which == ITIMER_REAL) { 1668625Sroot untimeout(realitexpire, (caddr_t)p); 1678114Sroot if (timerisset(&aitv.it_value)) { 1688114Sroot timevaladd(&aitv.it_value, &time); 1698625Sroot timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value)); 1708114Sroot } 1718114Sroot p->p_realtimer = aitv; 1728114Sroot } else 1738103Sroot u.u_timer[uap->which] = aitv; 1748034Sroot splx(s); 1757424Sroot } 1767424Sroot 1778146Sroot /* 1788146Sroot * Real interval timer expired: 1798146Sroot * send process whose timer expired an alarm signal. 1808146Sroot * If time is not set up to reload, then just return. 1818146Sroot * Else compute next time timer should go off which is > current time. 1828146Sroot * This is where delay in processing this timeout causes multiple 1838146Sroot * SIGALRM calls to be compressed into one. 1848146Sroot */ 1858146Sroot realitexpire(p) 1868114Sroot register struct proc *p; 1878114Sroot { 1888114Sroot int s; 1898114Sroot 1908114Sroot psignal(p, SIGALRM); 1918114Sroot if (!timerisset(&p->p_realtimer.it_interval)) { 1928114Sroot timerclear(&p->p_realtimer.it_value); 1938114Sroot return; 1948114Sroot } 1958114Sroot for (;;) { 1968114Sroot s = spl7(); 1978114Sroot timevaladd(&p->p_realtimer.it_value, 1988114Sroot &p->p_realtimer.it_interval); 1998114Sroot if (timercmp(&p->p_realtimer.it_value, &time, >)) { 2008625Sroot timeout(realitexpire, (caddr_t)p, 2018625Sroot hzto(&p->p_realtimer.it_value)); 2028114Sroot splx(s); 2038114Sroot return; 2048114Sroot } 2058114Sroot splx(s); 2068114Sroot } 2078114Sroot } 2088114Sroot 2098146Sroot /* 2108146Sroot * Check that a proposed value to load into the .it_value or 2118146Sroot * .it_interval part of an interval timer is acceptable, and 2128146Sroot * fix it to have at least minimal value (i.e. if it is less 2138146Sroot * than the resolution of the clock, round it up.) 2148146Sroot */ 2158103Sroot itimerfix(tv) 2168103Sroot struct timeval *tv; 2177424Sroot { 2188034Sroot 2198114Sroot if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 2208114Sroot tv->tv_usec < 0 || tv->tv_usec >= 1000000) 2218103Sroot return (EINVAL); 2228103Sroot if (tv->tv_sec == 0 && tv->tv_usec < tick) 2238103Sroot tv->tv_usec = tick; 2248103Sroot return (0); 2258034Sroot } 2268034Sroot 2278146Sroot /* 2288146Sroot * Decrement an interval timer by a specified number 2298146Sroot * of microseconds, which must be less than a second, 2308146Sroot * i.e. < 1000000. If the timer expires, then reload 2318146Sroot * it. In this case, carry over (usec - old value) to 2328146Sroot * reducint the value reloaded into the timer so that 2338146Sroot * the timer does not drift. This routine assumes 2348146Sroot * that it is called in a context where the timers 2358146Sroot * on which it is operating cannot change in value. 2368146Sroot */ 2378034Sroot itimerdecr(itp, usec) 2388034Sroot register struct itimerval *itp; 2398034Sroot int usec; 2408034Sroot { 2418034Sroot 2428103Sroot if (itp->it_value.tv_usec < usec) { 2438103Sroot if (itp->it_value.tv_sec == 0) { 2448146Sroot /* expired, and already in next interval */ 2458103Sroot usec -= itp->it_value.tv_usec; 2468034Sroot goto expire; 2478103Sroot } 2488103Sroot itp->it_value.tv_usec += 1000000; 2498103Sroot itp->it_value.tv_sec--; 2508034Sroot } 2518103Sroot itp->it_value.tv_usec -= usec; 2528103Sroot usec = 0; 2538103Sroot if (timerisset(&itp->it_value)) 2548034Sroot return (1); 2558146Sroot /* expired, exactly at end of interval */ 2568034Sroot expire: 2578103Sroot if (timerisset(&itp->it_interval)) { 2588103Sroot itp->it_value = itp->it_interval; 2598103Sroot itp->it_value.tv_usec -= usec; 2608103Sroot if (itp->it_value.tv_usec < 0) { 2618103Sroot itp->it_value.tv_usec += 1000000; 2628103Sroot itp->it_value.tv_sec--; 2638103Sroot } 2648103Sroot } else 2658146Sroot itp->it_value.tv_usec = 0; /* sec is already 0 */ 2668034Sroot return (0); 2678034Sroot } 2688034Sroot 2698146Sroot /* 2708146Sroot * Add and subtract routines for timevals. 2718146Sroot * N.B.: subtract routine doesn't deal with 2728146Sroot * results which are before the beginning, 2738146Sroot * it just gets very confused in this case. 2748146Sroot * Caveat emptor. 2758146Sroot */ 2768146Sroot timevaladd(t1, t2) 2778146Sroot struct timeval *t1, *t2; 2788146Sroot { 2798146Sroot 2808146Sroot t1->tv_sec += t2->tv_sec; 2818146Sroot t1->tv_usec += t2->tv_usec; 2828146Sroot timevalfix(t1); 2838146Sroot } 2848146Sroot 2858146Sroot timevalsub(t1, t2) 2868146Sroot struct timeval *t1, *t2; 2878146Sroot { 2888146Sroot 2898146Sroot t1->tv_sec -= t2->tv_sec; 2908146Sroot t1->tv_usec -= t2->tv_usec; 2918146Sroot timevalfix(t1); 2928146Sroot } 2938146Sroot 2948146Sroot timevalfix(t1) 2958146Sroot struct timeval *t1; 2968146Sroot { 2978146Sroot 2988146Sroot if (t1->tv_usec < 0) { 2998146Sroot t1->tv_sec--; 3008146Sroot t1->tv_usec += 1000000; 3018146Sroot } 3028146Sroot if (t1->tv_usec >= 1000000) { 3038146Sroot t1->tv_sec++; 3048146Sroot t1->tv_usec -= 1000000; 3058146Sroot } 3068146Sroot } 3078146Sroot 3088034Sroot #ifndef NOCOMPAT 3098034Sroot otime() 3108034Sroot { 3118034Sroot 3128034Sroot u.u_r.r_time = time.tv_sec; 3138034Sroot } 3148034Sroot 3158103Sroot ostime() 3168103Sroot { 3178103Sroot register struct a { 3188103Sroot int time; 3198103Sroot } *uap = (struct a *)u.u_ap; 3208103Sroot struct timeval tv; 3218103Sroot 3228103Sroot tv.tv_sec = uap->time; 3238103Sroot tv.tv_usec = 0; 3248103Sroot setthetime(&tv); 3258103Sroot } 3268103Sroot 3278146Sroot /* from old timeb.h */ 3288146Sroot struct timeb { 3298146Sroot time_t time; 3308146Sroot u_short millitm; 3318146Sroot short timezone; 3328146Sroot short dstflag; 3338146Sroot }; 3348034Sroot 3358034Sroot oftime() 3368034Sroot { 3377424Sroot register struct a { 3388034Sroot struct timeb *tp; 3397424Sroot } *uap; 3408146Sroot struct timeb tb; 3417424Sroot 3427424Sroot uap = (struct a *)u.u_ap; 3438034Sroot (void) spl7(); 3448146Sroot tb.time = time.tv_sec; 3458146Sroot tb.millitm = time.tv_usec / 1000; 3468034Sroot (void) spl0(); 3478146Sroot tb.timezone = tz.tz_minuteswest; 3488146Sroot tb.dstflag = tz.tz_dsttime; 3498446Sroot if (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)) < 0) 3507424Sroot u.u_error = EFAULT; 3517424Sroot } 3528146Sroot 3538120Sroot oalarm() 3548120Sroot { 3558120Sroot register struct a { 3568120Sroot int deltat; 3578120Sroot } *uap = (struct a *)u.u_ap; 3588120Sroot register struct proc *p = u.u_procp; 3598120Sroot int s = spl7(); 3608120Sroot 3618625Sroot untimeout(realitexpire, (caddr_t)p); 3628120Sroot timerclear(&p->p_realtimer.it_interval); 3638120Sroot u.u_r.r_val1 = 0; 3648120Sroot if (timerisset(&p->p_realtimer.it_value) && 3658120Sroot timercmp(&p->p_realtimer.it_value, &time, >)) 3668120Sroot u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec; 3678120Sroot if (uap->deltat == 0) { 3688120Sroot splx(s); 3698120Sroot return; 3708120Sroot } 3718120Sroot p->p_realtimer.it_value = time; 3728120Sroot p->p_realtimer.it_value.tv_sec += uap->deltat; 3738625Sroot timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 3748120Sroot splx(s); 3758120Sroot } 3768146Sroot #endif 377