From aa2615055535bde302dfd736eb4f32660e7e162a Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Sat, 11 Sep 1982 20:12:25 -0800 Subject: [PATCH] cleanup with comments SCCS-vsn: sys/kern/kern_time.c 5.7 --- usr/src/sys/kern/kern_time.c | 172 +++++++++++++++++++++++++---------- 1 file changed, 123 insertions(+), 49 deletions(-) diff --git a/usr/src/sys/kern/kern_time.c b/usr/src/sys/kern/kern_time.c index a8a32cd4cb..8419fe00e1 100644 --- a/usr/src/sys/kern/kern_time.c +++ b/usr/src/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* kern_time.c 5.6 82/09/08 */ +/* kern_time.c 5.7 82/09/11 */ #include "../h/param.h" #include "../h/dir.h" /* XXX */ @@ -10,6 +10,12 @@ /* * Time of day and interval timer support. + * + * These routines provide the kernel entry points to get and set + * the time-of-day and per-process interval timers. Subroutines + * here provide support for adding and subtracting timeval structures + * and decrementing interval timers, optionally reloading the interval + * timers when they expire. */ gettimeofday() @@ -65,43 +71,33 @@ setthetime(tv) if (!suser()) return; +/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ boottime.tv_sec += tv->tv_sec - time.tv_sec; s = spl7(); time = *tv; splx(s); clockset(); } -timevaladd(t1, t2) - struct timeval *t1, *t2; -{ - - t1->tv_sec += t2->tv_sec; - t1->tv_usec += t2->tv_usec; - timevalfix(t1); -} - -timevalsub(t1, t2) - struct timeval *t1, *t2; -{ - - t1->tv_sec -= t2->tv_sec; - t1->tv_usec -= t2->tv_usec; - timevalfix(t1); -} - -timevalfix(t1) - struct timeval *t1; -{ - - if (t1->tv_usec < 0) { - t1->tv_sec--; - t1->tv_usec += 1000000; - } - if (t1->tv_usec >= 1000000) { - t1->tv_sec++; - t1->tv_usec -= 1000000; - } -} - +/* + * Get value of an interval timer. The process virtual and + * profiling virtual time timers are kept in the u. area, since + * they can be swapped out. These are kept internally in the + * way they are specified externally: in time until they expire. + * + * The real time interval timer is kept in the process table slot + * for the process, and its value (it_value) is kept as an + * absolute time rather than as a delta, so that it is easy to keep + * periodic real-time signals from drifting. + * + * Virtual time timers are processed in the hardclock() routine of + * kern_clock.c. The real time timer is processed by a timeout + * routine, called from the softclock() routine. Since a callout + * may be delayed in real time due to interrupt processing in the system, + * it is possible for the real time timeout routine (realitexpire, given below), + * to be delayed in real time past when it is supposed to occur. It + * does not suffice, therefore, to reload the real timer .it_value from the + * real time timers .it_interval. Rather, we compute the next time in + * absolute time the timer should go off. + */ getitimer() { register struct a { @@ -117,6 +113,12 @@ getitimer() } s = spl7(); if (uap->which == ITIMER_REAL) { + /* + * Convert from absoulte to relative time in .it_value + * part of real time timer. If time for real time timer + * has passed return 0, else return difference between + * current time and time for the timer to go off. + */ aitv = u.u_procp->p_realtimer; if (timerisset(&aitv.it_value)) if (timercmp(&aitv.it_value, &time, <)) @@ -160,10 +162,10 @@ setitimer() } s = spl7(); if (uap->which == ITIMER_REAL) { - untimeout(unrto, p); + untimeout(realitexpire, p); if (timerisset(&aitv.it_value)) { timevaladd(&aitv.it_value, &time); - timeout(unrto, p, hzto(&aitv.it_value)); + timeout(realitexpire, p, hzto(&aitv.it_value)); } p->p_realtimer = aitv; } else @@ -171,7 +173,15 @@ setitimer() splx(s); } -unrto(p) +/* + * Real interval timer expired: + * send process whose timer expired an alarm signal. + * If time is not set up to reload, then just return. + * Else compute next time timer should go off which is > current time. + * This is where delay in processing this timeout causes multiple + * SIGALRM calls to be compressed into one. + */ +realitexpire(p) register struct proc *p; { int s; @@ -186,7 +196,8 @@ unrto(p) timevaladd(&p->p_realtimer.it_value, &p->p_realtimer.it_interval); if (timercmp(&p->p_realtimer.it_value, &time, >)) { - timeout(unrto, p, hzto(&p->p_realtimer.it_value)); + timeout(realitexpire, + p, hzto(&p->p_realtimer.it_value)); splx(s); return; } @@ -194,6 +205,12 @@ unrto(p) } } +/* + * Check that a proposed value to load into the .it_value or + * .it_interval part of an interval timer is acceptable, and + * fix it to have at least minimal value (i.e. if it is less + * than the resolution of the clock, round it up.) + */ itimerfix(tv) struct timeval *tv; { @@ -206,6 +223,16 @@ itimerfix(tv) return (0); } +/* + * Decrement an interval timer by a specified number + * of microseconds, which must be less than a second, + * i.e. < 1000000. If the timer expires, then reload + * it. In this case, carry over (usec - old value) to + * reducint the value reloaded into the timer so that + * the timer does not drift. This routine assumes + * that it is called in a context where the timers + * on which it is operating cannot change in value. + */ itimerdecr(itp, usec) register struct itimerval *itp; int usec; @@ -213,6 +240,7 @@ itimerdecr(itp, usec) if (itp->it_value.tv_usec < usec) { if (itp->it_value.tv_sec == 0) { + /* expired, and already in next interval */ usec -= itp->it_value.tv_usec; goto expire; } @@ -223,6 +251,7 @@ itimerdecr(itp, usec) usec = 0; if (timerisset(&itp->it_value)) return (1); + /* expired, exactly at end of interval */ expire: if (timerisset(&itp->it_interval)) { itp->it_value = itp->it_interval; @@ -232,10 +261,49 @@ expire: itp->it_value.tv_sec--; } } else - itp->it_value.tv_usec = 0; + itp->it_value.tv_usec = 0; /* sec is already 0 */ return (0); } +/* + * Add and subtract routines for timevals. + * N.B.: subtract routine doesn't deal with + * results which are before the beginning, + * it just gets very confused in this case. + * Caveat emptor. + */ +timevaladd(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec += t2->tv_sec; + t1->tv_usec += t2->tv_usec; + timevalfix(t1); +} + +timevalsub(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec -= t2->tv_sec; + t1->tv_usec -= t2->tv_usec; + timevalfix(t1); +} + +timevalfix(t1) + struct timeval *t1; +{ + + if (t1->tv_usec < 0) { + t1->tv_sec--; + t1->tv_usec += 1000000; + } + if (t1->tv_usec >= 1000000) { + t1->tv_sec++; + t1->tv_usec -= 1000000; + } +} + #ifndef NOCOMPAT otime() { @@ -255,26 +323,32 @@ ostime() setthetime(&tv); } -#include "../h/timeb.h" +/* from old timeb.h */ +struct timeb { + time_t time; + u_short millitm; + short timezone; + short dstflag; +}; oftime() { register struct a { struct timeb *tp; } *uap; - struct timeb t; + struct timeb tb; uap = (struct a *)u.u_ap; (void) spl7(); - t.time = time.tv_sec; - t.millitm = time.tv_usec / 1000; + tb.time = time.tv_sec; + tb.millitm = time.tv_usec / 1000; (void) spl0(); - t.timezone = tz.tz_minuteswest; - t.dstflag = tz.tz_dsttime; - if (copyout((caddr_t)&t, (caddr_t)uap->tp, sizeof(t)) < 0) + tb.timezone = tz.tz_minuteswest; + tb.dstflag = tz.tz_dsttime; + if (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof(t)) < 0) u.u_error = EFAULT; } -#endif + oalarm() { register struct a { @@ -284,7 +358,7 @@ oalarm() struct timeval atv; int s = spl7(); - untimeout(unrto, p); + untimeout(realitexpire, p); timerclear(&p->p_realtimer.it_interval); u.u_r.r_val1 = 0; if (timerisset(&p->p_realtimer.it_value) && @@ -296,7 +370,7 @@ oalarm() } p->p_realtimer.it_value = time; p->p_realtimer.it_value.tv_sec += uap->deltat; - timeout(unrto, p, hzto(&p->p_realtimer.it_value)); + timeout(realitexpire, p, hzto(&p->p_realtimer.it_value)); splx(s); } - +#endif -- 2.20.1