cleanup with comments
[unix-history] / usr / src / sys / kern / kern_time.c
index a8a32cd..8419fe0 100644 (file)
@@ -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 */
 
 #include "../h/param.h"
 #include "../h/dir.h"          /* XXX */
 
 /* 
  * Time of day and interval timer support.
 
 /* 
  * 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()
  */
 
 gettimeofday()
@@ -65,43 +71,33 @@ setthetime(tv)
 
        if (!suser())
                return;
 
        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();
 }
 
        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 {
 getitimer()
 {
        register struct a {
@@ -117,6 +113,12 @@ getitimer()
        }
        s = spl7();
        if (uap->which == ITIMER_REAL) {
        }
        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, <))
                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) {
        }
        s = spl7();
        if (uap->which == ITIMER_REAL) {
-               untimeout(unrto, p);
+               untimeout(realitexpire, p);
                if (timerisset(&aitv.it_value)) {
                        timevaladd(&aitv.it_value, &time);
                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
                }
                p->p_realtimer = aitv;
        } else
@@ -171,7 +173,15 @@ setitimer()
        splx(s);
 }
 
        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;
        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, >)) {
                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;
                }
                        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;
 {
 itimerfix(tv)
        struct timeval *tv;
 {
@@ -206,6 +223,16 @@ itimerfix(tv)
        return (0);
 }
 
        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;
 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) {
 
        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;
                }
                        usec -= itp->it_value.tv_usec;
                        goto expire;
                }
@@ -223,6 +251,7 @@ itimerdecr(itp, usec)
        usec = 0;
        if (timerisset(&itp->it_value))
                return (1);
        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;
 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_sec--;
                }
        } else
-               itp->it_value.tv_usec = 0;
+               itp->it_value.tv_usec = 0;              /* sec is already 0 */
        return (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()
 {
 #ifndef NOCOMPAT
 otime()
 {
@@ -255,26 +323,32 @@ ostime()
        setthetime(&tv);
 }
 
        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;
 
 oftime()
 {
        register struct a {
                struct  timeb   *tp;
        } *uap;
-       struct timeb t;
+       struct timeb tb;
 
        uap = (struct a *)u.u_ap;
        (void) spl7();
 
        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();
        (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;
 }
                u.u_error = EFAULT;
 }
-#endif
+
 oalarm()
 {
        register struct a {
 oalarm()
 {
        register struct a {
@@ -284,7 +358,7 @@ oalarm()
        struct timeval atv;
        int s = spl7();
 
        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) &&
        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;
        }
        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);
 }
        splx(s);
 }
-
+#endif