The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_time.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)kern_time.c 8.1 (Berkeley) 6/10/93
   34  * $FreeBSD$
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/sysproto.h>
   39 #include <sys/resourcevar.h>
   40 #include <sys/signalvar.h>
   41 #include <sys/kernel.h>
   42 #include <sys/systm.h>
   43 #include <sys/sysent.h>
   44 #include <sys/proc.h>
   45 #include <sys/time.h>
   46 #include <sys/vnode.h>
   47 #include <vm/vm.h>
   48 #include <vm/vm_extern.h>
   49 
   50 struct timezone tz;
   51 
   52 /*
   53  * Time of day and interval timer support.
   54  *
   55  * These routines provide the kernel entry points to get and set
   56  * the time-of-day and per-process interval timers.  Subroutines
   57  * here provide support for adding and subtracting timeval structures
   58  * and decrementing interval timers, optionally reloading the interval
   59  * timers when they expire.
   60  */
   61 
   62 static int      nanosleep1 __P((struct proc *p, struct timespec *rqt,
   63                     struct timespec *rmt));
   64 static int      settime __P((struct timeval *));
   65 static void     timevalfix __P((struct timeval *));
   66 static void     no_lease_updatetime __P((int));
   67 
   68 static void 
   69 no_lease_updatetime(deltat)
   70         int deltat;
   71 {
   72 }
   73 
   74 void (*lease_updatetime) __P((int))  = no_lease_updatetime;
   75 
   76 static int
   77 settime(tv)
   78         struct timeval *tv;
   79 {
   80         struct timeval delta, tv1, tv2;
   81         static struct timeval maxtime, laststep;
   82         struct timespec ts;
   83         int s;
   84 
   85         s = splclock();
   86         microtime(&tv1);
   87         delta = *tv;
   88         timevalsub(&delta, &tv1);
   89 
   90         /*
   91          * If the system is secure, we do not allow the time to be 
   92          * set to a value earlier than 1 second less than the highest
   93          * time we have yet seen. The worst a miscreant can do in
   94          * this circumstance is "freeze" time. He couldn't go
   95          * back to the past.
   96          *
   97          * We similarly do not allow the clock to be stepped more
   98          * than one second, nor more than once per second. This allows
   99          * a miscreant to make the clock march double-time, but no worse.
  100          */
  101         if (securelevel > 1) {
  102                 if (delta.tv_sec < 0 || delta.tv_usec < 0) {
  103                         /*
  104                          * Update maxtime to latest time we've seen.
  105                          */
  106                         if (tv1.tv_sec > maxtime.tv_sec)
  107                                 maxtime = tv1;
  108                         tv2 = *tv;
  109                         timevalsub(&tv2, &maxtime);
  110                         if (tv2.tv_sec < -1) {
  111                                 tv->tv_sec = maxtime.tv_sec - 1;
  112                                 printf("Time adjustment clamped to -1 second\n");
  113                         }
  114                 } else {
  115                         if (tv1.tv_sec == laststep.tv_sec) {
  116                                 splx(s);
  117                                 return (EPERM);
  118                         }
  119                         if (delta.tv_sec > 1) {
  120                                 tv->tv_sec = tv1.tv_sec + 1;
  121                                 printf("Time adjustment clamped to +1 second\n");
  122                         }
  123                         laststep = *tv;
  124                 }
  125         }
  126 
  127         ts.tv_sec = tv->tv_sec;
  128         ts.tv_nsec = tv->tv_usec * 1000;
  129         set_timecounter(&ts);
  130         (void) splsoftclock();
  131         lease_updatetime(delta.tv_sec);
  132         splx(s);
  133         resettodr();
  134         return (0);
  135 }
  136 
  137 #ifndef _SYS_SYSPROTO_H_
  138 struct clock_gettime_args {
  139         clockid_t clock_id;
  140         struct  timespec *tp;
  141 };
  142 #endif
  143 
  144 /* ARGSUSED */
  145 int
  146 clock_gettime(p, uap)
  147         struct proc *p;
  148         struct clock_gettime_args *uap;
  149 {
  150         struct timespec ats;
  151 
  152         if (SCARG(uap, clock_id) != CLOCK_REALTIME)
  153                 return (EINVAL);
  154         nanotime(&ats);
  155         return (copyout(&ats, SCARG(uap, tp), sizeof(ats)));
  156 }
  157 
  158 #ifndef _SYS_SYSPROTO_H_
  159 struct clock_settime_args {
  160         clockid_t clock_id;
  161         const struct    timespec *tp;
  162 };
  163 #endif
  164 
  165 /* ARGSUSED */
  166 int
  167 clock_settime(p, uap)
  168         struct proc *p;
  169         struct clock_settime_args *uap;
  170 {
  171         struct timeval atv;
  172         struct timespec ats;
  173         int error;
  174 
  175         if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  176                 return (error);
  177         if (SCARG(uap, clock_id) != CLOCK_REALTIME)
  178                 return (EINVAL);
  179         if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
  180                 return (error);
  181         if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
  182                 return (EINVAL);
  183         /* XXX Don't convert nsec->usec and back */
  184         TIMESPEC_TO_TIMEVAL(&atv, &ats);
  185         if ((error = settime(&atv)))
  186                 return (error);
  187         return (0);
  188 }
  189 
  190 #ifndef _SYS_SYSPROTO_H_
  191 struct clock_getres_args {
  192         clockid_t clock_id;
  193         struct  timespec *tp;
  194 };
  195 #endif
  196 
  197 int
  198 clock_getres(p, uap)
  199         struct proc *p;
  200         struct clock_getres_args *uap;
  201 {
  202         struct timespec ts;
  203         int error;
  204 
  205         if (SCARG(uap, clock_id) != CLOCK_REALTIME)
  206                 return (EINVAL);
  207         error = 0;
  208         if (SCARG(uap, tp)) {
  209                 ts.tv_sec = 0;
  210                 ts.tv_nsec = 1000000000 / timecounter->tc_frequency;
  211                 error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
  212         }
  213         return (error);
  214 }
  215 
  216 static int nanowait;
  217 
  218 static int
  219 nanosleep1(p, rqt, rmt)
  220         struct proc *p;
  221         struct timespec *rqt, *rmt;
  222 {
  223         struct timespec ts, ts2, ts3;
  224         struct timeval tv;
  225         int error;
  226 
  227         if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
  228                 return (EINVAL);
  229         if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
  230                 return (0);
  231         getnanouptime(&ts);
  232         timespecadd(&ts, rqt);
  233         TIMESPEC_TO_TIMEVAL(&tv, rqt);
  234         for (;;) {
  235                 error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
  236                     tvtohz(&tv));
  237                 getnanouptime(&ts2);
  238                 if (error != EWOULDBLOCK) {
  239                         if (error == ERESTART)
  240                                 error = EINTR;
  241                         if (rmt != NULL) {
  242                                 timespecsub(&ts, &ts2);
  243                                 if (ts.tv_sec < 0)
  244                                         timespecclear(&ts);
  245                                 *rmt = ts;
  246                         }
  247                         return (error);
  248                 }
  249                 if (timespeccmp(&ts2, &ts, >=))
  250                         return (0);
  251                 ts3 = ts;
  252                 timespecsub(&ts3, &ts2);
  253                 TIMESPEC_TO_TIMEVAL(&tv, &ts3);
  254         }
  255 }
  256 
  257 #ifndef _SYS_SYSPROTO_H_
  258 struct nanosleep_args {
  259         struct  timespec *rqtp;
  260         struct  timespec *rmtp;
  261 };
  262 #endif
  263 
  264 /* ARGSUSED */
  265 int
  266 nanosleep(p, uap)
  267         struct proc *p;
  268         struct nanosleep_args *uap;
  269 {
  270         struct timespec rmt, rqt;
  271         int error, error2;
  272 
  273         error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
  274         if (error)
  275                 return (error);
  276         if (SCARG(uap, rmtp))
  277                 if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
  278                         return (EFAULT);
  279         error = nanosleep1(p, &rqt, &rmt);
  280         if (error && SCARG(uap, rmtp)) {
  281                 error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
  282                 if (error2)     /* XXX shouldn't happen, did useracc() above */
  283                         return (error2);
  284         }
  285         return (error);
  286 }
  287 
  288 #ifndef _SYS_SYSPROTO_H_
  289 struct gettimeofday_args {
  290         struct  timeval *tp;
  291         struct  timezone *tzp;
  292 };
  293 #endif
  294 /* ARGSUSED */
  295 int
  296 gettimeofday(p, uap)
  297         struct proc *p;
  298         register struct gettimeofday_args *uap;
  299 {
  300         struct timeval atv;
  301         int error = 0;
  302 
  303         if (uap->tp) {
  304                 microtime(&atv);
  305                 if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
  306                     sizeof (atv))))
  307                         return (error);
  308         }
  309         if (uap->tzp)
  310                 error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
  311                     sizeof (tz));
  312         return (error);
  313 }
  314 
  315 #ifndef _SYS_SYSPROTO_H_
  316 struct settimeofday_args {
  317         struct  timeval *tv;
  318         struct  timezone *tzp;
  319 };
  320 #endif
  321 /* ARGSUSED */
  322 int
  323 settimeofday(p, uap)
  324         struct proc *p;
  325         struct settimeofday_args *uap;
  326 {
  327         struct timeval atv;
  328         struct timezone atz;
  329         int error;
  330 
  331         if ((error = suser(p->p_ucred, &p->p_acflag)))
  332                 return (error);
  333         /* Verify all parameters before changing time. */
  334         if (uap->tv) {
  335                 if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
  336                     sizeof(atv))))
  337                         return (error);
  338                 if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
  339                         return (EINVAL);
  340         }
  341         if (uap->tzp &&
  342             (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
  343                 return (error);
  344         if (uap->tv && (error = settime(&atv)))
  345                 return (error);
  346         if (uap->tzp)
  347                 tz = atz;
  348         return (0);
  349 }
  350 
  351 int     tickdelta;                      /* current clock skew, us. per tick */
  352 long    timedelta;                      /* unapplied time correction, us. */
  353 static long     bigadj = 1000000;       /* use 10x skew above bigadj us. */
  354 
  355 #ifndef _SYS_SYSPROTO_H_
  356 struct adjtime_args {
  357         struct timeval *delta;
  358         struct timeval *olddelta;
  359 };
  360 #endif
  361 /* ARGSUSED */
  362 int
  363 adjtime(p, uap)
  364         struct proc *p;
  365         register struct adjtime_args *uap;
  366 {
  367         struct timeval atv;
  368         register long ndelta, ntickdelta, odelta;
  369         int s, error;
  370 
  371         if ((error = suser(p->p_ucred, &p->p_acflag)))
  372                 return (error);
  373         if ((error =
  374             copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
  375                 return (error);
  376 
  377         /*
  378          * Compute the total correction and the rate at which to apply it.
  379          * Round the adjustment down to a whole multiple of the per-tick
  380          * delta, so that after some number of incremental changes in
  381          * hardclock(), tickdelta will become zero, lest the correction
  382          * overshoot and start taking us away from the desired final time.
  383          */
  384         ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
  385         if (ndelta > bigadj || ndelta < -bigadj)
  386                 ntickdelta = 10 * tickadj;
  387         else
  388                 ntickdelta = tickadj;
  389         if (ndelta % ntickdelta)
  390                 ndelta = ndelta / ntickdelta * ntickdelta;
  391 
  392         /*
  393          * To make hardclock()'s job easier, make the per-tick delta negative
  394          * if we want time to run slower; then hardclock can simply compute
  395          * tick + tickdelta, and subtract tickdelta from timedelta.
  396          */
  397         if (ndelta < 0)
  398                 ntickdelta = -ntickdelta;
  399         s = splclock();
  400         odelta = timedelta;
  401         timedelta = ndelta;
  402         tickdelta = ntickdelta;
  403         splx(s);
  404 
  405         if (uap->olddelta) {
  406                 atv.tv_sec = odelta / 1000000;
  407                 atv.tv_usec = odelta % 1000000;
  408                 (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
  409                     sizeof(struct timeval));
  410         }
  411         return (0);
  412 }
  413 
  414 /*
  415  * Get value of an interval timer.  The process virtual and
  416  * profiling virtual time timers are kept in the p_stats area, since
  417  * they can be swapped out.  These are kept internally in the
  418  * way they are specified externally: in time until they expire.
  419  *
  420  * The real time interval timer is kept in the process table slot
  421  * for the process, and its value (it_value) is kept as an
  422  * absolute time rather than as a delta, so that it is easy to keep
  423  * periodic real-time signals from drifting.
  424  *
  425  * Virtual time timers are processed in the hardclock() routine of
  426  * kern_clock.c.  The real time timer is processed by a timeout
  427  * routine, called from the softclock() routine.  Since a callout
  428  * may be delayed in real time due to interrupt processing in the system,
  429  * it is possible for the real time timeout routine (realitexpire, given below),
  430  * to be delayed in real time past when it is supposed to occur.  It
  431  * does not suffice, therefore, to reload the real timer .it_value from the
  432  * real time timers .it_interval.  Rather, we compute the next time in
  433  * absolute time the timer should go off.
  434  */
  435 #ifndef _SYS_SYSPROTO_H_
  436 struct getitimer_args {
  437         u_int   which;
  438         struct  itimerval *itv;
  439 };
  440 #endif
  441 /* ARGSUSED */
  442 int
  443 getitimer(p, uap)
  444         struct proc *p;
  445         register struct getitimer_args *uap;
  446 {
  447         struct timeval ctv;
  448         struct itimerval aitv;
  449         int s;
  450 
  451         if (uap->which > ITIMER_PROF)
  452                 return (EINVAL);
  453         s = splclock(); /* XXX still needed ? */
  454         if (uap->which == ITIMER_REAL) {
  455                 /*
  456                  * Convert from absolute to relative time in .it_value
  457                  * part of real time timer.  If time for real time timer
  458                  * has passed return 0, else return difference between
  459                  * current time and time for the timer to go off.
  460                  */
  461                 aitv = p->p_realtimer;
  462                 if (timevalisset(&aitv.it_value)) {
  463                         getmicrouptime(&ctv);
  464                         if (timevalcmp(&aitv.it_value, &ctv, <))
  465                                 timevalclear(&aitv.it_value);
  466                         else
  467                                 timevalsub(&aitv.it_value, &ctv);
  468                 }
  469         } else
  470                 aitv = p->p_stats->p_timer[uap->which];
  471         splx(s);
  472         return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
  473             sizeof (struct itimerval)));
  474 }
  475 
  476 #ifndef _SYS_SYSPROTO_H_
  477 struct setitimer_args {
  478         u_int   which;
  479         struct  itimerval *itv, *oitv;
  480 };
  481 #endif
  482 /* ARGSUSED */
  483 int
  484 setitimer(p, uap)
  485         struct proc *p;
  486         register struct setitimer_args *uap;
  487 {
  488         struct itimerval aitv;
  489         struct timeval ctv;
  490         register struct itimerval *itvp;
  491         int s, error;
  492 
  493         if (uap->which > ITIMER_PROF)
  494                 return (EINVAL);
  495         itvp = uap->itv;
  496         if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
  497             sizeof(struct itimerval))))
  498                 return (error);
  499         if ((uap->itv = uap->oitv) &&
  500             (error = getitimer(p, (struct getitimer_args *)uap)))
  501                 return (error);
  502         if (itvp == 0)
  503                 return (0);
  504         if (itimerfix(&aitv.it_value))
  505                 return (EINVAL);
  506         if (!timevalisset(&aitv.it_value))
  507                 timevalclear(&aitv.it_interval);
  508         else if (itimerfix(&aitv.it_interval))
  509                 return (EINVAL);
  510         s = splclock(); /* XXX: still needed ? */
  511         if (uap->which == ITIMER_REAL) {
  512                 if (timevalisset(&p->p_realtimer.it_value))
  513                         untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
  514                 if (timevalisset(&aitv.it_value)) 
  515                         p->p_ithandle = timeout(realitexpire, (caddr_t)p,
  516                                                 tvtohz(&aitv.it_value));
  517                 getmicrouptime(&ctv);
  518                 timevaladd(&aitv.it_value, &ctv);
  519                 p->p_realtimer = aitv;
  520         } else
  521                 p->p_stats->p_timer[uap->which] = aitv;
  522         splx(s);
  523         return (0);
  524 }
  525 
  526 /*
  527  * Real interval timer expired:
  528  * send process whose timer expired an alarm signal.
  529  * If time is not set up to reload, then just return.
  530  * Else compute next time timer should go off which is > current time.
  531  * This is where delay in processing this timeout causes multiple
  532  * SIGALRM calls to be compressed into one.
  533  * tvtohz() always adds 1 to allow for the time until the next clock
  534  * interrupt being strictly less than 1 clock tick, but we don't want
  535  * that here since we want to appear to be in sync with the clock
  536  * interrupt even when we're delayed.
  537  */
  538 void
  539 realitexpire(arg)
  540         void *arg;
  541 {
  542         register struct proc *p;
  543         struct timeval ctv, ntv;
  544         int s;
  545 
  546         p = (struct proc *)arg;
  547         psignal(p, SIGALRM);
  548         if (!timevalisset(&p->p_realtimer.it_interval)) {
  549                 timevalclear(&p->p_realtimer.it_value);
  550                 return;
  551         }
  552         for (;;) {
  553                 s = splclock(); /* XXX: still neeeded ? */
  554                 timevaladd(&p->p_realtimer.it_value,
  555                     &p->p_realtimer.it_interval);
  556                 getmicrouptime(&ctv);
  557                 if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
  558                         ntv = p->p_realtimer.it_value;
  559                         timevalsub(&ntv, &ctv);
  560                         p->p_ithandle = timeout(realitexpire, (caddr_t)p,
  561                             tvtohz(&ntv) - 1);
  562                         splx(s);
  563                         return;
  564                 }
  565                 splx(s);
  566         }
  567 }
  568 
  569 /*
  570  * Check that a proposed value to load into the .it_value or
  571  * .it_interval part of an interval timer is acceptable, and
  572  * fix it to have at least minimal value (i.e. if it is less
  573  * than the resolution of the clock, round it up.)
  574  */
  575 int
  576 itimerfix(tv)
  577         struct timeval *tv;
  578 {
  579 
  580         if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
  581             tv->tv_usec < 0 || tv->tv_usec >= 1000000)
  582                 return (EINVAL);
  583         if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
  584                 tv->tv_usec = tick;
  585         return (0);
  586 }
  587 
  588 /*
  589  * Decrement an interval timer by a specified number
  590  * of microseconds, which must be less than a second,
  591  * i.e. < 1000000.  If the timer expires, then reload
  592  * it.  In this case, carry over (usec - old value) to
  593  * reduce the value reloaded into the timer so that
  594  * the timer does not drift.  This routine assumes
  595  * that it is called in a context where the timers
  596  * on which it is operating cannot change in value.
  597  */
  598 int
  599 itimerdecr(itp, usec)
  600         register struct itimerval *itp;
  601         int usec;
  602 {
  603 
  604         if (itp->it_value.tv_usec < usec) {
  605                 if (itp->it_value.tv_sec == 0) {
  606                         /* expired, and already in next interval */
  607                         usec -= itp->it_value.tv_usec;
  608                         goto expire;
  609                 }
  610                 itp->it_value.tv_usec += 1000000;
  611                 itp->it_value.tv_sec--;
  612         }
  613         itp->it_value.tv_usec -= usec;
  614         usec = 0;
  615         if (timevalisset(&itp->it_value))
  616                 return (1);
  617         /* expired, exactly at end of interval */
  618 expire:
  619         if (timevalisset(&itp->it_interval)) {
  620                 itp->it_value = itp->it_interval;
  621                 itp->it_value.tv_usec -= usec;
  622                 if (itp->it_value.tv_usec < 0) {
  623                         itp->it_value.tv_usec += 1000000;
  624                         itp->it_value.tv_sec--;
  625                 }
  626         } else
  627                 itp->it_value.tv_usec = 0;              /* sec is already 0 */
  628         return (0);
  629 }
  630 
  631 /*
  632  * Add and subtract routines for timevals.
  633  * N.B.: subtract routine doesn't deal with
  634  * results which are before the beginning,
  635  * it just gets very confused in this case.
  636  * Caveat emptor.
  637  */
  638 void
  639 timevaladd(t1, t2)
  640         struct timeval *t1, *t2;
  641 {
  642 
  643         t1->tv_sec += t2->tv_sec;
  644         t1->tv_usec += t2->tv_usec;
  645         timevalfix(t1);
  646 }
  647 
  648 void
  649 timevalsub(t1, t2)
  650         struct timeval *t1, *t2;
  651 {
  652 
  653         t1->tv_sec -= t2->tv_sec;
  654         t1->tv_usec -= t2->tv_usec;
  655         timevalfix(t1);
  656 }
  657 
  658 static void
  659 timevalfix(t1)
  660         struct timeval *t1;
  661 {
  662 
  663         if (t1->tv_usec < 0) {
  664                 t1->tv_sec--;
  665                 t1->tv_usec += 1000000;
  666         }
  667         if (t1->tv_usec >= 1000000) {
  668                 t1->tv_sec++;
  669                 t1->tv_usec -= 1000000;
  670         }
  671 }

Cache object: 1645e4bf830ce3aecbe4e578b83cd8d9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.