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: releng/5.0/sys/kern/kern_time.c 108086 2002-12-19 09:40:13Z alfred $
   35  */
   36 
   37 #include "opt_mac.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/sysproto.h>
   44 #include <sys/resourcevar.h>
   45 #include <sys/signalvar.h>
   46 #include <sys/kernel.h>
   47 #include <sys/mac.h>
   48 #include <sys/systm.h>
   49 #include <sys/sysent.h>
   50 #include <sys/proc.h>
   51 #include <sys/time.h>
   52 #include <sys/timetc.h>
   53 #include <sys/vnode.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/vm_extern.h>
   57 
   58 struct timezone tz;
   59 
   60 /*
   61  * Time of day and interval timer support.
   62  *
   63  * These routines provide the kernel entry points to get and set
   64  * the time-of-day and per-process interval timers.  Subroutines
   65  * here provide support for adding and subtracting timeval structures
   66  * and decrementing interval timers, optionally reloading the interval
   67  * timers when they expire.
   68  */
   69 
   70 static int      nanosleep1(struct thread *td, struct timespec *rqt,
   71                     struct timespec *rmt);
   72 static int      settime(struct thread *, struct timeval *);
   73 static void     timevalfix(struct timeval *);
   74 static void     no_lease_updatetime(int);
   75 
   76 static void 
   77 no_lease_updatetime(deltat)
   78         int deltat;
   79 {
   80 }
   81 
   82 void (*lease_updatetime)(int)  = no_lease_updatetime;
   83 
   84 static int
   85 settime(struct thread *td, struct timeval *tv)
   86 {
   87         struct timeval delta, tv1, tv2;
   88         static struct timeval maxtime, laststep;
   89         struct timespec ts;
   90         int s;
   91 
   92         s = splclock();
   93         microtime(&tv1);
   94         delta = *tv;
   95         timevalsub(&delta, &tv1);
   96 
   97         /*
   98          * If the system is secure, we do not allow the time to be 
   99          * set to a value earlier than 1 second less than the highest
  100          * time we have yet seen. The worst a miscreant can do in
  101          * this circumstance is "freeze" time. He couldn't go
  102          * back to the past.
  103          *
  104          * We similarly do not allow the clock to be stepped more
  105          * than one second, nor more than once per second. This allows
  106          * a miscreant to make the clock march double-time, but no worse.
  107          */
  108         if (securelevel_gt(td->td_ucred, 1) != 0) {
  109                 if (delta.tv_sec < 0 || delta.tv_usec < 0) {
  110                         /*
  111                          * Update maxtime to latest time we've seen.
  112                          */
  113                         if (tv1.tv_sec > maxtime.tv_sec)
  114                                 maxtime = tv1;
  115                         tv2 = *tv;
  116                         timevalsub(&tv2, &maxtime);
  117                         if (tv2.tv_sec < -1) {
  118                                 tv->tv_sec = maxtime.tv_sec - 1;
  119                                 printf("Time adjustment clamped to -1 second\n");
  120                         }
  121                 } else {
  122                         if (tv1.tv_sec == laststep.tv_sec) {
  123                                 splx(s);
  124                                 return (EPERM);
  125                         }
  126                         if (delta.tv_sec > 1) {
  127                                 tv->tv_sec = tv1.tv_sec + 1;
  128                                 printf("Time adjustment clamped to +1 second\n");
  129                         }
  130                         laststep = *tv;
  131                 }
  132         }
  133 
  134         ts.tv_sec = tv->tv_sec;
  135         ts.tv_nsec = tv->tv_usec * 1000;
  136         mtx_lock(&Giant);
  137         tc_setclock(&ts);
  138         (void) splsoftclock();
  139         lease_updatetime(delta.tv_sec);
  140         splx(s);
  141         resettodr();
  142         mtx_unlock(&Giant);
  143         return (0);
  144 }
  145 
  146 #ifndef _SYS_SYSPROTO_H_
  147 struct clock_gettime_args {
  148         clockid_t clock_id;
  149         struct  timespec *tp;
  150 };
  151 #endif
  152 
  153 /*
  154  * MPSAFE
  155  */
  156 /* ARGSUSED */
  157 int
  158 clock_gettime(struct thread *td, struct clock_gettime_args *uap)
  159 {
  160         struct timespec ats;
  161 
  162         if (uap->clock_id != CLOCK_REALTIME)
  163                 return (EINVAL);
  164         mtx_lock(&Giant);
  165         nanotime(&ats);
  166         mtx_unlock(&Giant);
  167         return (copyout(&ats, uap->tp, sizeof(ats)));
  168 }
  169 
  170 #ifndef _SYS_SYSPROTO_H_
  171 struct clock_settime_args {
  172         clockid_t clock_id;
  173         const struct    timespec *tp;
  174 };
  175 #endif
  176 
  177 /*
  178  * MPSAFE
  179  */
  180 /* ARGSUSED */
  181 int
  182 clock_settime(struct thread *td, struct clock_settime_args *uap)
  183 {
  184         struct timeval atv;
  185         struct timespec ats;
  186         int error;
  187 
  188 #ifdef MAC
  189         error = mac_check_system_settime(td->td_ucred);
  190         if (error)
  191                 return (error);
  192 #endif
  193         if ((error = suser(td)) != 0)
  194                 return (error);
  195         if (uap->clock_id != CLOCK_REALTIME)
  196                 return (EINVAL);
  197         if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
  198                 return (error);
  199         if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
  200                 return (EINVAL);
  201         /* XXX Don't convert nsec->usec and back */
  202         TIMESPEC_TO_TIMEVAL(&atv, &ats);
  203         error = settime(td, &atv);
  204         return (error);
  205 }
  206 
  207 #ifndef _SYS_SYSPROTO_H_
  208 struct clock_getres_args {
  209         clockid_t clock_id;
  210         struct  timespec *tp;
  211 };
  212 #endif
  213 
  214 int
  215 clock_getres(struct thread *td, struct clock_getres_args *uap)
  216 {
  217         struct timespec ts;
  218         int error;
  219 
  220         if (uap->clock_id != CLOCK_REALTIME)
  221                 return (EINVAL);
  222         error = 0;
  223         if (uap->tp) {
  224                 ts.tv_sec = 0;
  225                 /*
  226                  * Round up the result of the division cheaply by adding 1.
  227                  * Rounding up is especially important if rounding down
  228                  * would give 0.  Perfect rounding is unimportant.
  229                  */
  230                 ts.tv_nsec = 1000000000 / tc_getfrequency() + 1;
  231                 error = copyout(&ts, uap->tp, sizeof(ts));
  232         }
  233         return (error);
  234 }
  235 
  236 static int nanowait;
  237 
  238 static int
  239 nanosleep1(struct thread *td, struct timespec *rqt, struct timespec *rmt)
  240 {
  241         struct timespec ts, ts2, ts3;
  242         struct timeval tv;
  243         int error;
  244 
  245         if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
  246                 return (EINVAL);
  247         if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
  248                 return (0);
  249         getnanouptime(&ts);
  250         timespecadd(&ts, rqt);
  251         TIMESPEC_TO_TIMEVAL(&tv, rqt);
  252         for (;;) {
  253                 error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
  254                     tvtohz(&tv));
  255                 getnanouptime(&ts2);
  256                 if (error != EWOULDBLOCK) {
  257                         if (error == ERESTART)
  258                                 error = EINTR;
  259                         if (rmt != NULL) {
  260                                 timespecsub(&ts, &ts2);
  261                                 if (ts.tv_sec < 0)
  262                                         timespecclear(&ts);
  263                                 *rmt = ts;
  264                         }
  265                         return (error);
  266                 }
  267                 if (timespeccmp(&ts2, &ts, >=))
  268                         return (0);
  269                 ts3 = ts;
  270                 timespecsub(&ts3, &ts2);
  271                 TIMESPEC_TO_TIMEVAL(&tv, &ts3);
  272         }
  273 }
  274 
  275 #ifndef _SYS_SYSPROTO_H_
  276 struct nanosleep_args {
  277         struct  timespec *rqtp;
  278         struct  timespec *rmtp;
  279 };
  280 #endif
  281 
  282 /* 
  283  * MPSAFE
  284  */
  285 /* ARGSUSED */
  286 int
  287 nanosleep(struct thread *td, struct nanosleep_args *uap)
  288 {
  289         struct timespec rmt, rqt;
  290         int error;
  291 
  292         error = copyin(uap->rqtp, &rqt, sizeof(rqt));
  293         if (error)
  294                 return (error);
  295 
  296         mtx_lock(&Giant);
  297         if (uap->rmtp) {
  298                 if (!useracc((caddr_t)uap->rmtp, sizeof(rmt), 
  299                     VM_PROT_WRITE)) {
  300                         error = EFAULT;
  301                         goto done2;
  302                 }
  303         }
  304         error = nanosleep1(td, &rqt, &rmt);
  305         if (error && uap->rmtp) {
  306                 int error2;
  307 
  308                 error2 = copyout(&rmt, uap->rmtp, sizeof(rmt));
  309                 if (error2)     /* XXX shouldn't happen, did useracc() above */
  310                         error = error2;
  311         }
  312 done2:
  313         mtx_unlock(&Giant);
  314         return (error);
  315 }
  316 
  317 #ifndef _SYS_SYSPROTO_H_
  318 struct gettimeofday_args {
  319         struct  timeval *tp;
  320         struct  timezone *tzp;
  321 };
  322 #endif
  323 /*
  324  * MPSAFE
  325  */
  326 /* ARGSUSED */
  327 int
  328 gettimeofday(struct thread *td, struct gettimeofday_args *uap)
  329 {
  330         struct timeval atv;
  331         int error = 0;
  332 
  333         if (uap->tp) {
  334                 microtime(&atv);
  335                 error = copyout(&atv, uap->tp, sizeof (atv));
  336         }
  337         if (error == 0 && uap->tzp != NULL) {
  338                 mtx_lock(&Giant);
  339                 error = copyout(&tz, uap->tzp, sizeof (tz));
  340                 mtx_unlock(&Giant);
  341         }
  342         return (error);
  343 }
  344 
  345 #ifndef _SYS_SYSPROTO_H_
  346 struct settimeofday_args {
  347         struct  timeval *tv;
  348         struct  timezone *tzp;
  349 };
  350 #endif
  351 /*
  352  * MPSAFE
  353  */
  354 /* ARGSUSED */
  355 int
  356 settimeofday(struct thread *td, struct settimeofday_args *uap)
  357 {
  358         struct timeval atv;
  359         struct timezone atz;
  360         int error = 0;
  361 
  362 #ifdef MAC
  363         error = mac_check_system_settime(td->td_ucred);
  364         if (error)
  365                 return (error);
  366 #endif
  367         if ((error = suser(td)))
  368                 return (error);
  369         /* Verify all parameters before changing time. */
  370         if (uap->tv) {
  371                 if ((error = copyin(uap->tv, &atv, sizeof(atv))))
  372                         return (error);
  373                 if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
  374                         return (EINVAL);
  375         }
  376         if (uap->tzp &&
  377             (error = copyin(uap->tzp, &atz, sizeof(atz))))
  378                 return (error);
  379         
  380         if (uap->tv && (error = settime(td, &atv)))
  381                 return (error);
  382         if (uap->tzp) {
  383                 mtx_lock(&Giant);
  384                 tz = atz;
  385                 mtx_unlock(&Giant);
  386         }
  387         return (error);
  388 }
  389 /*
  390  * Get value of an interval timer.  The process virtual and
  391  * profiling virtual time timers are kept in the p_stats area, since
  392  * they can be swapped out.  These are kept internally in the
  393  * way they are specified externally: in time until they expire.
  394  *
  395  * The real time interval timer is kept in the process table slot
  396  * for the process, and its value (it_value) is kept as an
  397  * absolute time rather than as a delta, so that it is easy to keep
  398  * periodic real-time signals from drifting.
  399  *
  400  * Virtual time timers are processed in the hardclock() routine of
  401  * kern_clock.c.  The real time timer is processed by a timeout
  402  * routine, called from the softclock() routine.  Since a callout
  403  * may be delayed in real time due to interrupt processing in the system,
  404  * it is possible for the real time timeout routine (realitexpire, given below),
  405  * to be delayed in real time past when it is supposed to occur.  It
  406  * does not suffice, therefore, to reload the real timer .it_value from the
  407  * real time timers .it_interval.  Rather, we compute the next time in
  408  * absolute time the timer should go off.
  409  */
  410 #ifndef _SYS_SYSPROTO_H_
  411 struct getitimer_args {
  412         u_int   which;
  413         struct  itimerval *itv;
  414 };
  415 #endif
  416 /*
  417  * MPSAFE
  418  */
  419 /* ARGSUSED */
  420 int
  421 getitimer(struct thread *td, struct getitimer_args *uap)
  422 {
  423         struct proc *p = td->td_proc;
  424         struct timeval ctv;
  425         struct itimerval aitv;
  426         int s;
  427         int error;
  428 
  429         if (uap->which > ITIMER_PROF)
  430                 return (EINVAL);
  431 
  432         mtx_lock(&Giant);
  433 
  434         s = splclock(); /* XXX still needed ? */
  435         if (uap->which == ITIMER_REAL) {
  436                 /*
  437                  * Convert from absolute to relative time in .it_value
  438                  * part of real time timer.  If time for real time timer
  439                  * has passed return 0, else return difference between
  440                  * current time and time for the timer to go off.
  441                  */
  442                 aitv = p->p_realtimer;
  443                 if (timevalisset(&aitv.it_value)) {
  444                         getmicrouptime(&ctv);
  445                         if (timevalcmp(&aitv.it_value, &ctv, <))
  446                                 timevalclear(&aitv.it_value);
  447                         else
  448                                 timevalsub(&aitv.it_value, &ctv);
  449                 }
  450         } else {
  451                 aitv = p->p_stats->p_timer[uap->which];
  452         }
  453         splx(s);
  454         error = copyout(&aitv, uap->itv, sizeof (struct itimerval));
  455         mtx_unlock(&Giant);
  456         return(error);
  457 }
  458 
  459 #ifndef _SYS_SYSPROTO_H_
  460 struct setitimer_args {
  461         u_int   which;
  462         struct  itimerval *itv, *oitv;
  463 };
  464 #endif
  465 /*
  466  * MPSAFE
  467  */
  468 /* ARGSUSED */
  469 int
  470 setitimer(struct thread *td, struct setitimer_args *uap)
  471 {
  472         struct proc *p = td->td_proc;
  473         struct itimerval aitv;
  474         struct timeval ctv;
  475         struct itimerval *itvp;
  476         int s, error = 0;
  477 
  478         if (uap->which > ITIMER_PROF)
  479                 return (EINVAL);
  480         itvp = uap->itv;
  481         if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
  482                 return (error);
  483 
  484         mtx_lock(&Giant);
  485 
  486         if ((uap->itv = uap->oitv) &&
  487             (error = getitimer(td, (struct getitimer_args *)uap))) {
  488                 goto done2;
  489         }
  490         if (itvp == 0) {
  491                 error = 0;
  492                 goto done2;
  493         }
  494         if (itimerfix(&aitv.it_value)) {
  495                 error = EINVAL;
  496                 goto done2;
  497         }
  498         if (!timevalisset(&aitv.it_value)) {
  499                 timevalclear(&aitv.it_interval);
  500         } else if (itimerfix(&aitv.it_interval)) {
  501                 error = EINVAL;
  502                 goto done2;
  503         }
  504         s = splclock(); /* XXX: still needed ? */
  505         if (uap->which == ITIMER_REAL) {
  506                 if (timevalisset(&p->p_realtimer.it_value))
  507                         callout_stop(&p->p_itcallout);
  508                 if (timevalisset(&aitv.it_value)) 
  509                         callout_reset(&p->p_itcallout, tvtohz(&aitv.it_value),
  510                             realitexpire, p);
  511                 getmicrouptime(&ctv);
  512                 timevaladd(&aitv.it_value, &ctv);
  513                 p->p_realtimer = aitv;
  514         } else {
  515                 p->p_stats->p_timer[uap->which] = aitv;
  516         }
  517         splx(s);
  518 done2:
  519         mtx_unlock(&Giant);
  520         return (error);
  521 }
  522 
  523 /*
  524  * Real interval timer expired:
  525  * send process whose timer expired an alarm signal.
  526  * If time is not set up to reload, then just return.
  527  * Else compute next time timer should go off which is > current time.
  528  * This is where delay in processing this timeout causes multiple
  529  * SIGALRM calls to be compressed into one.
  530  * tvtohz() always adds 1 to allow for the time until the next clock
  531  * interrupt being strictly less than 1 clock tick, but we don't want
  532  * that here since we want to appear to be in sync with the clock
  533  * interrupt even when we're delayed.
  534  */
  535 void
  536 realitexpire(void *arg)
  537 {
  538         struct proc *p;
  539         struct timeval ctv, ntv;
  540         int s;
  541 
  542         p = (struct proc *)arg;
  543         PROC_LOCK(p);
  544         psignal(p, SIGALRM);
  545         if (!timevalisset(&p->p_realtimer.it_interval)) {
  546                 timevalclear(&p->p_realtimer.it_value);
  547                 PROC_UNLOCK(p);
  548                 return;
  549         }
  550         for (;;) {
  551                 s = splclock(); /* XXX: still neeeded ? */
  552                 timevaladd(&p->p_realtimer.it_value,
  553                     &p->p_realtimer.it_interval);
  554                 getmicrouptime(&ctv);
  555                 if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
  556                         ntv = p->p_realtimer.it_value;
  557                         timevalsub(&ntv, &ctv);
  558                         callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1,
  559                             realitexpire, p);
  560                         splx(s);
  561                         PROC_UNLOCK(p);
  562                         return;
  563                 }
  564                 splx(s);
  565         }
  566         /*NOTREACHED*/
  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(struct timeval *tv)
  577 {
  578 
  579         if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
  580             tv->tv_usec < 0 || tv->tv_usec >= 1000000)
  581                 return (EINVAL);
  582         if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
  583                 tv->tv_usec = tick;
  584         return (0);
  585 }
  586 
  587 /*
  588  * Decrement an interval timer by a specified number
  589  * of microseconds, which must be less than a second,
  590  * i.e. < 1000000.  If the timer expires, then reload
  591  * it.  In this case, carry over (usec - old value) to
  592  * reduce the value reloaded into the timer so that
  593  * the timer does not drift.  This routine assumes
  594  * that it is called in a context where the timers
  595  * on which it is operating cannot change in value.
  596  */
  597 int
  598 itimerdecr(struct itimerval *itp, int usec)
  599 {
  600 
  601         if (itp->it_value.tv_usec < usec) {
  602                 if (itp->it_value.tv_sec == 0) {
  603                         /* expired, and already in next interval */
  604                         usec -= itp->it_value.tv_usec;
  605                         goto expire;
  606                 }
  607                 itp->it_value.tv_usec += 1000000;
  608                 itp->it_value.tv_sec--;
  609         }
  610         itp->it_value.tv_usec -= usec;
  611         usec = 0;
  612         if (timevalisset(&itp->it_value))
  613                 return (1);
  614         /* expired, exactly at end of interval */
  615 expire:
  616         if (timevalisset(&itp->it_interval)) {
  617                 itp->it_value = itp->it_interval;
  618                 itp->it_value.tv_usec -= usec;
  619                 if (itp->it_value.tv_usec < 0) {
  620                         itp->it_value.tv_usec += 1000000;
  621                         itp->it_value.tv_sec--;
  622                 }
  623         } else
  624                 itp->it_value.tv_usec = 0;              /* sec is already 0 */
  625         return (0);
  626 }
  627 
  628 /*
  629  * Add and subtract routines for timevals.
  630  * N.B.: subtract routine doesn't deal with
  631  * results which are before the beginning,
  632  * it just gets very confused in this case.
  633  * Caveat emptor.
  634  */
  635 void
  636 timevaladd(struct timeval *t1, struct timeval *t2)
  637 {
  638 
  639         t1->tv_sec += t2->tv_sec;
  640         t1->tv_usec += t2->tv_usec;
  641         timevalfix(t1);
  642 }
  643 
  644 void
  645 timevalsub(struct timeval *t1, struct timeval *t2)
  646 {
  647 
  648         t1->tv_sec -= t2->tv_sec;
  649         t1->tv_usec -= t2->tv_usec;
  650         timevalfix(t1);
  651 }
  652 
  653 static void
  654 timevalfix(struct timeval *t1)
  655 {
  656 
  657         if (t1->tv_usec < 0) {
  658                 t1->tv_sec--;
  659                 t1->tv_usec += 1000000;
  660         }
  661         if (t1->tv_usec >= 1000000) {
  662                 t1->tv_sec++;
  663                 t1->tv_usec -= 1000000;
  664         }
  665 }

Cache object: e6ade0c87821cf1d0e096d0a878ae3a2


[ 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.