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  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)kern_time.c 8.1 (Berkeley) 6/10/93
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/6.0/sys/kern/kern_time.c 144445 2005-03-31 22:51:18Z jhb $");
   34 
   35 #include "opt_mac.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/sysproto.h>
   42 #include <sys/resourcevar.h>
   43 #include <sys/signalvar.h>
   44 #include <sys/kernel.h>
   45 #include <sys/mac.h>
   46 #include <sys/syscallsubr.h>
   47 #include <sys/sysent.h>
   48 #include <sys/proc.h>
   49 #include <sys/time.h>
   50 #include <sys/timetc.h>
   51 #include <sys/vnode.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/vm_extern.h>
   55 
   56 int tz_minuteswest;
   57 int tz_dsttime;
   58 
   59 /*
   60  * Time of day and interval timer support.
   61  *
   62  * These routines provide the kernel entry points to get and set
   63  * the time-of-day and per-process interval timers.  Subroutines
   64  * here provide support for adding and subtracting timeval structures
   65  * and decrementing interval timers, optionally reloading the interval
   66  * timers when they expire.
   67  */
   68 
   69 static int      settime(struct thread *, struct timeval *);
   70 static void     timevalfix(struct timeval *);
   71 static void     no_lease_updatetime(int);
   72 
   73 static void 
   74 no_lease_updatetime(deltat)
   75         int deltat;
   76 {
   77 }
   78 
   79 void (*lease_updatetime)(int)  = no_lease_updatetime;
   80 
   81 static int
   82 settime(struct thread *td, struct timeval *tv)
   83 {
   84         struct timeval delta, tv1, tv2;
   85         static struct timeval maxtime, laststep;
   86         struct timespec ts;
   87         int s;
   88 
   89         s = splclock();
   90         microtime(&tv1);
   91         delta = *tv;
   92         timevalsub(&delta, &tv1);
   93 
   94         /*
   95          * If the system is secure, we do not allow the time to be 
   96          * set to a value earlier than 1 second less than the highest
   97          * time we have yet seen. The worst a miscreant can do in
   98          * this circumstance is "freeze" time. He couldn't go
   99          * back to the past.
  100          *
  101          * We similarly do not allow the clock to be stepped more
  102          * than one second, nor more than once per second. This allows
  103          * a miscreant to make the clock march double-time, but no worse.
  104          */
  105         if (securelevel_gt(td->td_ucred, 1) != 0) {
  106                 if (delta.tv_sec < 0 || delta.tv_usec < 0) {
  107                         /*
  108                          * Update maxtime to latest time we've seen.
  109                          */
  110                         if (tv1.tv_sec > maxtime.tv_sec)
  111                                 maxtime = tv1;
  112                         tv2 = *tv;
  113                         timevalsub(&tv2, &maxtime);
  114                         if (tv2.tv_sec < -1) {
  115                                 tv->tv_sec = maxtime.tv_sec - 1;
  116                                 printf("Time adjustment clamped to -1 second\n");
  117                         }
  118                 } else {
  119                         if (tv1.tv_sec == laststep.tv_sec) {
  120                                 splx(s);
  121                                 return (EPERM);
  122                         }
  123                         if (delta.tv_sec > 1) {
  124                                 tv->tv_sec = tv1.tv_sec + 1;
  125                                 printf("Time adjustment clamped to +1 second\n");
  126                         }
  127                         laststep = *tv;
  128                 }
  129         }
  130 
  131         ts.tv_sec = tv->tv_sec;
  132         ts.tv_nsec = tv->tv_usec * 1000;
  133         mtx_lock(&Giant);
  134         tc_setclock(&ts);
  135         (void) splsoftclock();
  136         lease_updatetime(delta.tv_sec);
  137         splx(s);
  138         resettodr();
  139         mtx_unlock(&Giant);
  140         return (0);
  141 }
  142 
  143 #ifndef _SYS_SYSPROTO_H_
  144 struct clock_gettime_args {
  145         clockid_t clock_id;
  146         struct  timespec *tp;
  147 };
  148 #endif
  149 
  150 /*
  151  * MPSAFE
  152  */
  153 /* ARGSUSED */
  154 int
  155 clock_gettime(struct thread *td, struct clock_gettime_args *uap)
  156 {
  157         struct timespec ats;
  158         struct timeval sys, user;
  159         struct proc *p;
  160 
  161         p = td->td_proc;
  162         switch (uap->clock_id) {
  163         case CLOCK_REALTIME:
  164                 nanotime(&ats);
  165                 break;
  166         case CLOCK_VIRTUAL:
  167                 PROC_LOCK(p);
  168                 calcru(p, &user, &sys);
  169                 PROC_UNLOCK(p);
  170                 TIMEVAL_TO_TIMESPEC(&user, &ats);
  171                 break;
  172         case CLOCK_PROF:
  173                 PROC_LOCK(p);
  174                 calcru(p, &user, &sys);
  175                 PROC_UNLOCK(p);
  176                 timevaladd(&user, &sys);
  177                 TIMEVAL_TO_TIMESPEC(&user, &ats);
  178                 break;
  179         case CLOCK_MONOTONIC:
  180                 nanouptime(&ats);
  181                 break;
  182         default:
  183                 return (EINVAL);
  184         }
  185         return (copyout(&ats, uap->tp, sizeof(ats)));
  186 }
  187 
  188 #ifndef _SYS_SYSPROTO_H_
  189 struct clock_settime_args {
  190         clockid_t clock_id;
  191         const struct    timespec *tp;
  192 };
  193 #endif
  194 
  195 /*
  196  * MPSAFE
  197  */
  198 /* ARGSUSED */
  199 int
  200 clock_settime(struct thread *td, struct clock_settime_args *uap)
  201 {
  202         struct timeval atv;
  203         struct timespec ats;
  204         int error;
  205 
  206 #ifdef MAC
  207         error = mac_check_system_settime(td->td_ucred);
  208         if (error)
  209                 return (error);
  210 #endif
  211         if ((error = suser(td)) != 0)
  212                 return (error);
  213         if (uap->clock_id != CLOCK_REALTIME)
  214                 return (EINVAL);
  215         if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
  216                 return (error);
  217         if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
  218                 return (EINVAL);
  219         /* XXX Don't convert nsec->usec and back */
  220         TIMESPEC_TO_TIMEVAL(&atv, &ats);
  221         error = settime(td, &atv);
  222         return (error);
  223 }
  224 
  225 #ifndef _SYS_SYSPROTO_H_
  226 struct clock_getres_args {
  227         clockid_t clock_id;
  228         struct  timespec *tp;
  229 };
  230 #endif
  231 
  232 int
  233 clock_getres(struct thread *td, struct clock_getres_args *uap)
  234 {
  235         struct timespec ts;
  236 
  237         ts.tv_sec = 0;
  238         switch (uap->clock_id) {
  239         case CLOCK_REALTIME:
  240         case CLOCK_MONOTONIC:
  241                 /*
  242                  * Round up the result of the division cheaply by adding 1.
  243                  * Rounding up is especially important if rounding down
  244                  * would give 0.  Perfect rounding is unimportant.
  245                  */
  246                 ts.tv_nsec = 1000000000 / tc_getfrequency() + 1;
  247                 break;
  248         case CLOCK_VIRTUAL:
  249         case CLOCK_PROF:
  250                 /* Accurately round up here because we can do so cheaply. */
  251                 ts.tv_nsec = (1000000000 + hz - 1) / hz;
  252                 break;
  253         default:
  254                 return (EINVAL);
  255         }
  256         if (uap->tp == NULL)
  257                 return (0);
  258         return (copyout(&ts, uap->tp, sizeof(ts)));
  259 }
  260 
  261 static int nanowait;
  262 
  263 int
  264 kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt)
  265 {
  266         struct timespec ts, ts2, ts3;
  267         struct timeval tv;
  268         int error;
  269 
  270         if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
  271                 return (EINVAL);
  272         if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
  273                 return (0);
  274         getnanouptime(&ts);
  275         timespecadd(&ts, rqt);
  276         TIMESPEC_TO_TIMEVAL(&tv, rqt);
  277         for (;;) {
  278                 error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
  279                     tvtohz(&tv));
  280                 getnanouptime(&ts2);
  281                 if (error != EWOULDBLOCK) {
  282                         if (error == ERESTART)
  283                                 error = EINTR;
  284                         if (rmt != NULL) {
  285                                 timespecsub(&ts, &ts2);
  286                                 if (ts.tv_sec < 0)
  287                                         timespecclear(&ts);
  288                                 *rmt = ts;
  289                         }
  290                         return (error);
  291                 }
  292                 if (timespeccmp(&ts2, &ts, >=))
  293                         return (0);
  294                 ts3 = ts;
  295                 timespecsub(&ts3, &ts2);
  296                 TIMESPEC_TO_TIMEVAL(&tv, &ts3);
  297         }
  298 }
  299 
  300 #ifndef _SYS_SYSPROTO_H_
  301 struct nanosleep_args {
  302         struct  timespec *rqtp;
  303         struct  timespec *rmtp;
  304 };
  305 #endif
  306 
  307 /* 
  308  * MPSAFE
  309  */
  310 /* ARGSUSED */
  311 int
  312 nanosleep(struct thread *td, struct nanosleep_args *uap)
  313 {
  314         struct timespec rmt, rqt;
  315         int error;
  316 
  317         error = copyin(uap->rqtp, &rqt, sizeof(rqt));
  318         if (error)
  319                 return (error);
  320 
  321         if (uap->rmtp &&
  322             !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
  323                         return (EFAULT);
  324         error = kern_nanosleep(td, &rqt, &rmt);
  325         if (error && uap->rmtp) {
  326                 int error2;
  327 
  328                 error2 = copyout(&rmt, uap->rmtp, sizeof(rmt));
  329                 if (error2)
  330                         error = error2;
  331         }
  332         return (error);
  333 }
  334 
  335 #ifndef _SYS_SYSPROTO_H_
  336 struct gettimeofday_args {
  337         struct  timeval *tp;
  338         struct  timezone *tzp;
  339 };
  340 #endif
  341 /*
  342  * MPSAFE
  343  */
  344 /* ARGSUSED */
  345 int
  346 gettimeofday(struct thread *td, struct gettimeofday_args *uap)
  347 {
  348         struct timeval atv;
  349         struct timezone rtz;
  350         int error = 0;
  351 
  352         if (uap->tp) {
  353                 microtime(&atv);
  354                 error = copyout(&atv, uap->tp, sizeof (atv));
  355         }
  356         if (error == 0 && uap->tzp != NULL) {
  357                 rtz.tz_minuteswest = tz_minuteswest;
  358                 rtz.tz_dsttime = tz_dsttime;
  359                 error = copyout(&rtz, uap->tzp, sizeof (rtz));
  360         }
  361         return (error);
  362 }
  363 
  364 #ifndef _SYS_SYSPROTO_H_
  365 struct settimeofday_args {
  366         struct  timeval *tv;
  367         struct  timezone *tzp;
  368 };
  369 #endif
  370 /*
  371  * MPSAFE
  372  */
  373 /* ARGSUSED */
  374 int
  375 settimeofday(struct thread *td, struct settimeofday_args *uap)
  376 {
  377         struct timeval atv, *tvp;
  378         struct timezone atz, *tzp;
  379         int error;
  380 
  381         if (uap->tv) {
  382                 error = copyin(uap->tv, &atv, sizeof(atv));
  383                 if (error)
  384                         return (error);
  385                 tvp = &atv;
  386         } else
  387                 tvp = NULL;
  388         if (uap->tzp) {
  389                 error = copyin(uap->tzp, &atz, sizeof(atz));
  390                 if (error)
  391                         return (error);
  392                 tzp = &atz;
  393         } else
  394                 tzp = NULL;
  395         return (kern_settimeofday(td, tvp, tzp));
  396 }
  397 
  398 int
  399 kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp)
  400 {
  401         int error;
  402 
  403 #ifdef MAC
  404         error = mac_check_system_settime(td->td_ucred);
  405         if (error)
  406                 return (error);
  407 #endif
  408         error = suser(td);
  409         if (error)
  410                 return (error);
  411         /* Verify all parameters before changing time. */
  412         if (tv) {
  413                 if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
  414                         return (EINVAL);
  415                 error = settime(td, tv);
  416         }
  417         if (tzp && error == 0) {
  418                 tz_minuteswest = tzp->tz_minuteswest;
  419                 tz_dsttime = tzp->tz_dsttime;
  420         }
  421         return (error);
  422 }
  423 
  424 /*
  425  * Get value of an interval timer.  The process virtual and
  426  * profiling virtual time timers are kept in the p_stats area, since
  427  * they can be swapped out.  These are kept internally in the
  428  * way they are specified externally: in time until they expire.
  429  *
  430  * The real time interval timer is kept in the process table slot
  431  * for the process, and its value (it_value) is kept as an
  432  * absolute time rather than as a delta, so that it is easy to keep
  433  * periodic real-time signals from drifting.
  434  *
  435  * Virtual time timers are processed in the hardclock() routine of
  436  * kern_clock.c.  The real time timer is processed by a timeout
  437  * routine, called from the softclock() routine.  Since a callout
  438  * may be delayed in real time due to interrupt processing in the system,
  439  * it is possible for the real time timeout routine (realitexpire, given below),
  440  * to be delayed in real time past when it is supposed to occur.  It
  441  * does not suffice, therefore, to reload the real timer .it_value from the
  442  * real time timers .it_interval.  Rather, we compute the next time in
  443  * absolute time the timer should go off.
  444  */
  445 #ifndef _SYS_SYSPROTO_H_
  446 struct getitimer_args {
  447         u_int   which;
  448         struct  itimerval *itv;
  449 };
  450 #endif
  451 /*
  452  * MPSAFE
  453  */
  454 int
  455 getitimer(struct thread *td, struct getitimer_args *uap)
  456 {
  457         struct itimerval aitv;
  458         int error;
  459 
  460         error = kern_getitimer(td, uap->which, &aitv);
  461         if (error != 0)
  462                 return (error);
  463         return (copyout(&aitv, uap->itv, sizeof (struct itimerval)));
  464 }
  465 
  466 int
  467 kern_getitimer(struct thread *td, u_int which, struct itimerval *aitv)
  468 {
  469         struct proc *p = td->td_proc;
  470         struct timeval ctv;
  471 
  472         if (which > ITIMER_PROF)
  473                 return (EINVAL);
  474 
  475         if (which == ITIMER_REAL) {
  476                 /*
  477                  * Convert from absolute to relative time in .it_value
  478                  * part of real time timer.  If time for real time timer
  479                  * has passed return 0, else return difference between
  480                  * current time and time for the timer to go off.
  481                  */
  482                 PROC_LOCK(p);
  483                 *aitv = p->p_realtimer;
  484                 PROC_UNLOCK(p);
  485                 if (timevalisset(&aitv->it_value)) {
  486                         getmicrouptime(&ctv);
  487                         if (timevalcmp(&aitv->it_value, &ctv, <))
  488                                 timevalclear(&aitv->it_value);
  489                         else
  490                                 timevalsub(&aitv->it_value, &ctv);
  491                 }
  492         } else {
  493                 mtx_lock_spin(&sched_lock);
  494                 *aitv = p->p_stats->p_timer[which];
  495                 mtx_unlock_spin(&sched_lock);
  496         }
  497         return (0);
  498 }
  499 
  500 #ifndef _SYS_SYSPROTO_H_
  501 struct setitimer_args {
  502         u_int   which;
  503         struct  itimerval *itv, *oitv;
  504 };
  505 #endif
  506 
  507 /*
  508  * MPSAFE
  509  */
  510 int
  511 setitimer(struct thread *td, struct setitimer_args *uap)
  512 {
  513         struct itimerval aitv, oitv;
  514         int error;
  515 
  516         if (uap->itv == NULL) {
  517                 uap->itv = uap->oitv;
  518                 return (getitimer(td, (struct getitimer_args *)uap));
  519         }
  520 
  521         if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval))))
  522                 return (error);
  523         error = kern_setitimer(td, uap->which, &aitv, &oitv);
  524         if (error != 0 || uap->oitv == NULL)
  525                 return (error);
  526         return (copyout(&oitv, uap->oitv, sizeof(struct itimerval)));
  527 }
  528 
  529 int
  530 kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv,
  531     struct itimerval *oitv)
  532 {
  533         struct proc *p = td->td_proc;
  534         struct timeval ctv;
  535 
  536         if (aitv == NULL)
  537                 return (kern_getitimer(td, which, oitv));
  538 
  539         if (which > ITIMER_PROF)
  540                 return (EINVAL);
  541         if (itimerfix(&aitv->it_value))
  542                 return (EINVAL);
  543         if (!timevalisset(&aitv->it_value))
  544                 timevalclear(&aitv->it_interval);
  545         else if (itimerfix(&aitv->it_interval))
  546                 return (EINVAL);
  547 
  548         if (which == ITIMER_REAL) {
  549                 PROC_LOCK(p);
  550                 if (timevalisset(&p->p_realtimer.it_value))
  551                         callout_stop(&p->p_itcallout);
  552                 getmicrouptime(&ctv);
  553                 if (timevalisset(&aitv->it_value)) {
  554                         callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value),
  555                             realitexpire, p);
  556                         timevaladd(&aitv->it_value, &ctv);
  557                 }
  558                 *oitv = p->p_realtimer;
  559                 p->p_realtimer = *aitv;
  560                 PROC_UNLOCK(p);
  561                 if (timevalisset(&oitv->it_value)) {
  562                         if (timevalcmp(&oitv->it_value, &ctv, <))
  563                                 timevalclear(&oitv->it_value);
  564                         else
  565                                 timevalsub(&oitv->it_value, &ctv);
  566                 }
  567         } else {
  568                 mtx_lock_spin(&sched_lock);
  569                 *oitv = p->p_stats->p_timer[which];
  570                 p->p_stats->p_timer[which] = *aitv;
  571                 mtx_unlock_spin(&sched_lock);
  572         }
  573         return (0);
  574 }
  575 
  576 /*
  577  * Real interval timer expired:
  578  * send process whose timer expired an alarm signal.
  579  * If time is not set up to reload, then just return.
  580  * Else compute next time timer should go off which is > current time.
  581  * This is where delay in processing this timeout causes multiple
  582  * SIGALRM calls to be compressed into one.
  583  * tvtohz() always adds 1 to allow for the time until the next clock
  584  * interrupt being strictly less than 1 clock tick, but we don't want
  585  * that here since we want to appear to be in sync with the clock
  586  * interrupt even when we're delayed.
  587  */
  588 void
  589 realitexpire(void *arg)
  590 {
  591         struct proc *p;
  592         struct timeval ctv, ntv;
  593 
  594         p = (struct proc *)arg;
  595         PROC_LOCK(p);
  596         psignal(p, SIGALRM);
  597         if (!timevalisset(&p->p_realtimer.it_interval)) {
  598                 timevalclear(&p->p_realtimer.it_value);
  599                 if (p->p_flag & P_WEXIT)
  600                         wakeup(&p->p_itcallout);
  601                 PROC_UNLOCK(p);
  602                 return;
  603         }
  604         for (;;) {
  605                 timevaladd(&p->p_realtimer.it_value,
  606                     &p->p_realtimer.it_interval);
  607                 getmicrouptime(&ctv);
  608                 if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
  609                         ntv = p->p_realtimer.it_value;
  610                         timevalsub(&ntv, &ctv);
  611                         callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1,
  612                             realitexpire, p);
  613                         PROC_UNLOCK(p);
  614                         return;
  615                 }
  616         }
  617         /*NOTREACHED*/
  618 }
  619 
  620 /*
  621  * Check that a proposed value to load into the .it_value or
  622  * .it_interval part of an interval timer is acceptable, and
  623  * fix it to have at least minimal value (i.e. if it is less
  624  * than the resolution of the clock, round it up.)
  625  */
  626 int
  627 itimerfix(struct timeval *tv)
  628 {
  629 
  630         if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
  631             tv->tv_usec < 0 || tv->tv_usec >= 1000000)
  632                 return (EINVAL);
  633         if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
  634                 tv->tv_usec = tick;
  635         return (0);
  636 }
  637 
  638 /*
  639  * Decrement an interval timer by a specified number
  640  * of microseconds, which must be less than a second,
  641  * i.e. < 1000000.  If the timer expires, then reload
  642  * it.  In this case, carry over (usec - old value) to
  643  * reduce the value reloaded into the timer so that
  644  * the timer does not drift.  This routine assumes
  645  * that it is called in a context where the timers
  646  * on which it is operating cannot change in value.
  647  */
  648 int
  649 itimerdecr(struct itimerval *itp, int usec)
  650 {
  651 
  652         if (itp->it_value.tv_usec < usec) {
  653                 if (itp->it_value.tv_sec == 0) {
  654                         /* expired, and already in next interval */
  655                         usec -= itp->it_value.tv_usec;
  656                         goto expire;
  657                 }
  658                 itp->it_value.tv_usec += 1000000;
  659                 itp->it_value.tv_sec--;
  660         }
  661         itp->it_value.tv_usec -= usec;
  662         usec = 0;
  663         if (timevalisset(&itp->it_value))
  664                 return (1);
  665         /* expired, exactly at end of interval */
  666 expire:
  667         if (timevalisset(&itp->it_interval)) {
  668                 itp->it_value = itp->it_interval;
  669                 itp->it_value.tv_usec -= usec;
  670                 if (itp->it_value.tv_usec < 0) {
  671                         itp->it_value.tv_usec += 1000000;
  672                         itp->it_value.tv_sec--;
  673                 }
  674         } else
  675                 itp->it_value.tv_usec = 0;              /* sec is already 0 */
  676         return (0);
  677 }
  678 
  679 /*
  680  * Add and subtract routines for timevals.
  681  * N.B.: subtract routine doesn't deal with
  682  * results which are before the beginning,
  683  * it just gets very confused in this case.
  684  * Caveat emptor.
  685  */
  686 void
  687 timevaladd(struct timeval *t1, const struct timeval *t2)
  688 {
  689 
  690         t1->tv_sec += t2->tv_sec;
  691         t1->tv_usec += t2->tv_usec;
  692         timevalfix(t1);
  693 }
  694 
  695 void
  696 timevalsub(struct timeval *t1, const struct timeval *t2)
  697 {
  698 
  699         t1->tv_sec -= t2->tv_sec;
  700         t1->tv_usec -= t2->tv_usec;
  701         timevalfix(t1);
  702 }
  703 
  704 static void
  705 timevalfix(struct timeval *t1)
  706 {
  707 
  708         if (t1->tv_usec < 0) {
  709                 t1->tv_sec--;
  710                 t1->tv_usec += 1000000;
  711         }
  712         if (t1->tv_usec >= 1000000) {
  713                 t1->tv_sec++;
  714                 t1->tv_usec -= 1000000;
  715         }
  716 }
  717 
  718 /*
  719  * ratecheck(): simple time-based rate-limit checking.
  720  */
  721 int
  722 ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
  723 {
  724         struct timeval tv, delta;
  725         int rv = 0;
  726 
  727         getmicrouptime(&tv);            /* NB: 10ms precision */
  728         delta = tv;
  729         timevalsub(&delta, lasttime);
  730 
  731         /*
  732          * check for 0,0 is so that the message will be seen at least once,
  733          * even if interval is huge.
  734          */
  735         if (timevalcmp(&delta, mininterval, >=) ||
  736             (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
  737                 *lasttime = tv;
  738                 rv = 1;
  739         }
  740 
  741         return (rv);
  742 }
  743 
  744 /*
  745  * ppsratecheck(): packets (or events) per second limitation.
  746  *
  747  * Return 0 if the limit is to be enforced (e.g. the caller
  748  * should drop a packet because of the rate limitation).
  749  *
  750  * maxpps of 0 always causes zero to be returned.  maxpps of -1
  751  * always causes 1 to be returned; this effectively defeats rate
  752  * limiting.
  753  *
  754  * Note that we maintain the struct timeval for compatibility
  755  * with other bsd systems.  We reuse the storage and just monitor
  756  * clock ticks for minimal overhead.  
  757  */
  758 int
  759 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
  760 {
  761         int now;
  762 
  763         /*
  764          * Reset the last time and counter if this is the first call
  765          * or more than a second has passed since the last update of
  766          * lasttime.
  767          */
  768         now = ticks;
  769         if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) {
  770                 lasttime->tv_sec = now;
  771                 *curpps = 1;
  772                 return (maxpps != 0);
  773         } else {
  774                 (*curpps)++;            /* NB: ignore potential overflow */
  775                 return (maxpps < 0 || *curpps < maxpps);
  776         }
  777 }

Cache object: 3b8253ece6beaaae2713967fc075e0bc


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