root/kern/kern_time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. settime
  2. settime
  3. sys_clock_gettime
  4. sys_clock_settime
  5. sys_clock_getres
  6. sys_nanosleep
  7. sys_gettimeofday
  8. sys_settimeofday
  9. sys_adjfreq
  10. sys_adjtime
  11. sys_getitimer
  12. sys_setitimer
  13. realitexpire
  14. itimerfix
  15. itimerround
  16. itimerdecr
  17. ratecheck
  18. ppsratecheck

    1 /*      $OpenBSD: kern_time.c,v 1.62 2007/04/04 17:32:20 art Exp $      */
    2 /*      $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)kern_time.c 8.4 (Berkeley) 5/26/95
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/resourcevar.h>
   37 #include <sys/kernel.h>
   38 #include <sys/systm.h>
   39 #include <sys/proc.h>
   40 #include <sys/vnode.h>
   41 #include <sys/signalvar.h>
   42 #ifdef __HAVE_TIMECOUNTER
   43 #include <sys/timetc.h>
   44 #endif
   45 
   46 #include <sys/mount.h>
   47 #include <sys/syscallargs.h>
   48 
   49 #include <machine/cpu.h>
   50 
   51 void    itimerround(struct timeval *);
   52 
   53 /* 
   54  * Time of day and interval timer support.
   55  *
   56  * These routines provide the kernel entry points to get and set
   57  * the time-of-day and per-process interval timers.  Subroutines
   58  * here provide support for adding and subtracting timeval structures
   59  * and decrementing interval timers, optionally reloading the interval
   60  * timers when they expire.
   61  */
   62 
   63 /* This function is used by clock_settime and settimeofday */
   64 #ifdef __HAVE_TIMECOUNTER
   65 int
   66 settime(struct timespec *ts)
   67 {
   68         struct timespec now;
   69         
   70 
   71         /*
   72          * Don't allow the time to be set forward so far it will wrap
   73          * and become negative, thus allowing an attacker to bypass
   74          * the next check below.  The cutoff is 1 year before rollover
   75          * occurs, so even if the attacker uses adjtime(2) to move
   76          * the time past the cutoff, it will take a very long time
   77          * to get to the wrap point.
   78          *
   79          * XXX: we check against INT_MAX since on 64-bit
   80          *      platforms, sizeof(int) != sizeof(long) and
   81          *      time_t is 32 bits even when atv.tv_sec is 64 bits.
   82          */
   83         if (ts->tv_sec > INT_MAX - 365*24*60*60) {
   84                 printf("denied attempt to set clock forward to %ld\n",
   85                     ts->tv_sec);
   86                 return (EPERM);
   87         }
   88         /*
   89          * If the system is secure, we do not allow the time to be
   90          * set to an earlier value (it may be slowed using adjtime,
   91          * but not set back). This feature prevent interlopers from
   92          * setting arbitrary time stamps on files.
   93          */
   94         nanotime(&now);
   95         if (securelevel > 1 && timespeccmp(ts, &now, <)) {
   96                 printf("denied attempt to set clock back %ld seconds\n",
   97                     now.tv_sec - ts->tv_sec);
   98                 return (EPERM);
   99         }
  100 
  101         tc_setclock(ts);
  102         resettodr();
  103 
  104         return (0);
  105 }
  106 #else
  107 int
  108 settime(struct timespec *ts)
  109 {
  110         struct timeval delta, tvv, *tv;
  111         int s;
  112 
  113         /* XXX - Ugh. */
  114         tv = &tvv;
  115         tvv.tv_sec = ts->tv_sec;
  116         tvv.tv_usec = ts->tv_nsec / 1000;
  117 
  118         /*
  119          * Don't allow the time to be set forward so far it will wrap
  120          * and become negative, thus allowing an attacker to bypass
  121          * the next check below.  The cutoff is 1 year before rollover
  122          * occurs, so even if the attacker uses adjtime(2) to move
  123          * the time past the cutoff, it will take a very long time
  124          * to get to the wrap point.
  125          *
  126          * XXX: we check against INT_MAX since on 64-bit
  127          *      platforms, sizeof(int) != sizeof(long) and
  128          *      time_t is 32 bits even when atv.tv_sec is 64 bits.
  129          */
  130         if (tv->tv_sec > INT_MAX - 365*24*60*60) {
  131                 printf("denied attempt to set clock forward to %ld\n",
  132                     tv->tv_sec);
  133                 return (EPERM);
  134         }
  135         /*
  136          * If the system is secure, we do not allow the time to be
  137          * set to an earlier value (it may be slowed using adjtime,
  138          * but not set back). This feature prevent interlopers from
  139          * setting arbitrary time stamps on files.
  140          */
  141         if (securelevel > 1 && timercmp(tv, &time, <)) {
  142                 printf("denied attempt to set clock back %ld seconds\n",
  143                     time_second - tv->tv_sec);
  144                 return (EPERM);
  145         }
  146 
  147         /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
  148         s = splclock();
  149         timersub(tv, &time, &delta);
  150         time = *tv;
  151         timeradd(&boottime, &delta, &boottime);
  152         splx(s);
  153         resettodr();
  154 
  155         return (0);
  156 }
  157 #endif
  158 
  159 /* ARGSUSED */
  160 int
  161 sys_clock_gettime(struct proc *p, void *v, register_t *retval)
  162 {
  163         struct sys_clock_gettime_args /* {
  164                 syscallarg(clockid_t) clock_id;
  165                 syscallarg(struct timespec *) tp;
  166         } */ *uap = v;
  167         clockid_t clock_id;
  168         struct timespec ats;
  169 
  170         clock_id = SCARG(uap, clock_id);
  171         switch (clock_id) {
  172         case CLOCK_REALTIME:
  173                 nanotime(&ats);
  174                 break;
  175         case CLOCK_MONOTONIC:
  176                 nanouptime(&ats);
  177                 break;
  178         case CLOCK_PROF:
  179                 ats.tv_sec = p->p_rtime.tv_sec;
  180                 ats.tv_nsec = p->p_rtime.tv_usec * 1000;
  181                 break;
  182         default:
  183                 return (EINVAL);
  184         }
  185 
  186         return copyout(&ats, SCARG(uap, tp), sizeof(ats));
  187 }
  188 
  189 /* ARGSUSED */
  190 int
  191 sys_clock_settime(struct proc *p, void *v, register_t *retval)
  192 {
  193         struct sys_clock_settime_args /* {
  194                 syscallarg(clockid_t) clock_id;
  195                 syscallarg(const struct timespec *) tp;
  196         } */ *uap = v;
  197         struct timespec ats;
  198         clockid_t clock_id;
  199         int error;
  200 
  201         if ((error = suser(p, 0)) != 0)
  202                 return (error);
  203 
  204         if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
  205                 return (error);
  206 
  207         clock_id = SCARG(uap, clock_id);
  208         switch (clock_id) {
  209         case CLOCK_REALTIME:
  210                 if ((error = settime(&ats)) != 0)
  211                         return (error);
  212                 break;
  213         default:        /* Other clocks are read-only */
  214                 return (EINVAL);
  215         }
  216 
  217         return (0);
  218 }
  219 
  220 int
  221 sys_clock_getres(struct proc *p, void *v, register_t *retval)
  222 {
  223         struct sys_clock_getres_args /* {
  224                 syscallarg(clockid_t) clock_id;
  225                 syscallarg(struct timespec *) tp;
  226         } */ *uap = v;
  227         clockid_t clock_id;
  228         struct timespec ts;
  229         int error = 0;
  230 
  231         clock_id = SCARG(uap, clock_id);
  232         switch (clock_id) {
  233         case CLOCK_REALTIME:
  234         case CLOCK_MONOTONIC:
  235                 ts.tv_sec = 0;
  236                 ts.tv_nsec = 1000000000 / hz;
  237                 break;
  238         default:
  239                 return (EINVAL);
  240         }
  241 
  242         if (SCARG(uap, tp))
  243                 error = copyout(&ts, SCARG(uap, tp), sizeof (ts));
  244 
  245         return error;
  246 }
  247 
  248 /* ARGSUSED */
  249 int
  250 sys_nanosleep(struct proc *p, void *v, register_t *retval)
  251 {
  252         static int nanowait;
  253         struct sys_nanosleep_args/* {
  254                 syscallarg(const struct timespec *) rqtp;
  255                 syscallarg(struct timespec *) rmtp;
  256         } */ *uap = v;
  257         struct timespec rqt, rmt;
  258         struct timespec sts, ets;
  259         struct timeval tv;
  260         int error;
  261 
  262         error = copyin((const void *)SCARG(uap, rqtp), (void *)&rqt,
  263             sizeof(struct timespec));
  264         if (error)
  265                 return (error);
  266 
  267         TIMESPEC_TO_TIMEVAL(&tv, &rqt);
  268         if (itimerfix(&tv))
  269                 return (EINVAL);
  270 
  271         if (SCARG(uap, rmtp))
  272                 getnanouptime(&sts);
  273 
  274         error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep",
  275             MAX(1, tvtohz(&tv)));
  276         if (error == ERESTART)
  277                 error = EINTR;
  278         if (error == EWOULDBLOCK)
  279                 error = 0;
  280 
  281         if (SCARG(uap, rmtp)) {
  282                 getnanouptime(&ets);
  283 
  284                 timespecsub(&ets, &sts, &sts);
  285                 timespecsub(&rqt, &sts, &rmt);
  286 
  287                 if (rmt.tv_sec < 0)
  288                         timespecclear(&rmt);
  289 
  290                 error = copyout((void *)&rmt, (void *)SCARG(uap,rmtp),
  291                     sizeof(rmt));
  292         }
  293 
  294         return error;
  295 }
  296 
  297 /* ARGSUSED */
  298 int
  299 sys_gettimeofday(struct proc *p, void *v, register_t *retval)
  300 {
  301         struct sys_gettimeofday_args /* {
  302                 syscallarg(struct timeval *) tp;
  303                 syscallarg(struct timezone *) tzp;
  304         } */ *uap = v;
  305         struct timeval atv;
  306         int error = 0;
  307 
  308         if (SCARG(uap, tp)) {
  309                 microtime(&atv);
  310                 if ((error = copyout((void *)&atv, (void *)SCARG(uap, tp),
  311                     sizeof (atv))))
  312                         return (error);
  313         }
  314         if (SCARG(uap, tzp))
  315                 error = copyout((void *)&tz, (void *)SCARG(uap, tzp),
  316                     sizeof (tz));
  317         return (error);
  318 }
  319 
  320 /* ARGSUSED */
  321 int
  322 sys_settimeofday(struct proc *p, void *v, register_t *retval)
  323 {
  324         struct sys_settimeofday_args /* {
  325                 syscallarg(const struct timeval *) tv;
  326                 syscallarg(const struct timezone *) tzp;
  327         } */ *uap = v;
  328         struct timezone atz;
  329         struct timeval atv;
  330         int error;
  331 
  332         if ((error = suser(p, 0)))
  333                 return (error);
  334         /* Verify all parameters before changing time. */
  335         if (SCARG(uap, tv) && (error = copyin((void *)SCARG(uap, tv),
  336             (void *)&atv, sizeof(atv))))
  337                 return (error);
  338         if (SCARG(uap, tzp) && (error = copyin((void *)SCARG(uap, tzp),
  339             (void *)&atz, sizeof(atz))))
  340                 return (error);
  341         if (SCARG(uap, tv)) {
  342                 struct timespec ts;
  343 
  344                 TIMEVAL_TO_TIMESPEC(&atv, &ts);
  345                 if ((error = settime(&ts)) != 0)
  346                         return (error);
  347         }
  348         if (SCARG(uap, tzp))
  349                 tz = atz;
  350         return (0);
  351 }
  352 
  353 #ifdef __HAVE_TIMECOUNTER
  354 struct timeval adjtimedelta;            /* unapplied time correction */
  355 #else
  356 int     tickdelta;                      /* current clock skew, us. per tick */
  357 long    timedelta;                      /* unapplied time correction, us. */
  358 long    bigadj = 1000000;               /* use 10x skew above bigadj us. */
  359 int64_t ntp_tick_permanent;
  360 int64_t ntp_tick_acc;
  361 #endif
  362 
  363 /* ARGSUSED */
  364 int
  365 sys_adjfreq(struct proc *p, void *v, register_t *retval)
  366 {
  367         struct sys_adjfreq_args /* {
  368                 syscallarg(const int64_t *) freq;
  369                 syscallarg(int64_t *) oldfreq;
  370         } */ *uap = v;
  371         int error;
  372         int64_t f;
  373 #ifndef __HAVE_TIMECOUNTER
  374         int s;
  375 
  376         if (SCARG(uap, oldfreq)) {
  377                 f = ntp_tick_permanent * hz;
  378                 if ((error = copyout((void *)&f, (void *)SCARG(uap, oldfreq),
  379                     sizeof(int64_t))))
  380                         return (error);
  381         }
  382         if (SCARG(uap, freq)) {
  383                 if ((error = suser(p, 0)))
  384                         return (error);
  385                 if ((error = copyin((void *)SCARG(uap, freq), (void *)&f,
  386                     sizeof(int64_t))))
  387                         return (error);
  388                 s = splclock();
  389                 ntp_tick_permanent = f / hz;
  390                 splx(s);
  391         }
  392 #else
  393         if (SCARG(uap, oldfreq)) {
  394                 if ((error = tc_adjfreq(&f, NULL)) != 0)
  395                         return (error);
  396                 if ((error = copyout(&f, SCARG(uap, oldfreq), sizeof(f))) != 0)
  397                         return (error);
  398         }
  399         if (SCARG(uap, freq)) {
  400                 if ((error = suser(p, 0)))
  401                         return (error);
  402                 if ((error = copyin(SCARG(uap, freq), &f, sizeof(f))) != 0)
  403                         return (error);
  404                 if ((error = tc_adjfreq(NULL, &f)) != 0)
  405                         return (error);
  406         }
  407 #endif
  408         return (0);
  409 }
  410 
  411 /* ARGSUSED */
  412 int
  413 sys_adjtime(struct proc *p, void *v, register_t *retval)
  414 {
  415         struct sys_adjtime_args /* {
  416                 syscallarg(const struct timeval *) delta;
  417                 syscallarg(struct timeval *) olddelta;
  418         } */ *uap = v;
  419 #ifdef __HAVE_TIMECOUNTER
  420         int error;
  421 
  422         if (SCARG(uap, olddelta))
  423                 if ((error = copyout((void *)&adjtimedelta,
  424                     (void *)SCARG(uap, olddelta), sizeof(struct timeval))))
  425                         return (error);
  426 
  427         if (SCARG(uap, delta)) {
  428                 if ((error = suser(p, 0)))
  429                         return (error);
  430 
  431                 if ((error = copyin((void *)SCARG(uap, delta),
  432                     (void *)&adjtimedelta, sizeof(struct timeval))))
  433                         return (error);
  434         }
  435 
  436         /* Normalize the correction. */
  437         while (adjtimedelta.tv_usec >= 1000000) {
  438                 adjtimedelta.tv_usec -= 1000000;
  439                 adjtimedelta.tv_sec += 1;
  440         }
  441         while (adjtimedelta.tv_usec < 0) {
  442                 adjtimedelta.tv_usec += 1000000;
  443                 adjtimedelta.tv_sec -= 1;
  444         }
  445         return (0);
  446 #else
  447         struct timeval atv;
  448         long ndelta, ntickdelta, odelta;
  449         int s, error;
  450 
  451         if (!SCARG(uap, delta)) {
  452                 s = splclock();
  453                 odelta = timedelta;
  454                 splx(s);
  455                 goto out;
  456         }
  457         if ((error = suser(p, 0)))
  458                 return (error);
  459         if ((error = copyin((void *)SCARG(uap, delta), (void *)&atv,
  460             sizeof(struct timeval))))
  461                 return (error);
  462 
  463         /*
  464          * Compute the total correction and the rate at which to apply it.
  465          * Round the adjustment down to a whole multiple of the per-tick
  466          * delta, so that after some number of incremental changes in
  467          * hardclock(), tickdelta will become zero, lest the correction
  468          * overshoot and start taking us away from the desired final time.
  469          */
  470         if (atv.tv_sec > LONG_MAX / 1000000L)
  471                 ndelta = LONG_MAX;
  472         else if (atv.tv_sec < LONG_MIN / 1000000L)
  473                 ndelta = LONG_MIN;
  474         else {
  475                 ndelta = atv.tv_sec * 1000000L;
  476                 odelta = ndelta;
  477                 ndelta += atv.tv_usec;
  478                 if (atv.tv_usec > 0 && ndelta <= odelta)
  479                         ndelta = LONG_MAX;      
  480                 else if (atv.tv_usec < 0 && ndelta >= odelta)
  481                         ndelta = LONG_MIN;
  482         }
  483 
  484         if (ndelta > bigadj || ndelta < -bigadj)
  485                 ntickdelta = 10 * tickadj;
  486         else
  487                 ntickdelta = tickadj;
  488         if (ndelta % ntickdelta)
  489                 ndelta = ndelta / ntickdelta * ntickdelta;
  490 
  491         /*
  492          * To make hardclock()'s job easier, make the per-tick delta negative
  493          * if we want time to run slower; then hardclock can simply compute
  494          * tick + tickdelta, and subtract tickdelta from timedelta.
  495          */
  496         if (ndelta < 0)
  497                 ntickdelta = -ntickdelta;
  498         s = splclock();
  499         odelta = timedelta;
  500         timedelta = ndelta;
  501         tickdelta = ntickdelta;
  502         splx(s);
  503 
  504 out:
  505         if (SCARG(uap, olddelta)) {
  506                 atv.tv_sec = odelta / 1000000;
  507                 atv.tv_usec = odelta % 1000000;
  508                 if ((error = copyout((void *)&atv, (void *)SCARG(uap, olddelta),
  509                     sizeof(struct timeval))))
  510                         return (error);
  511         }
  512         return (0);
  513 #endif
  514 }
  515 
  516 
  517 /*
  518  * Get value of an interval timer.  The process virtual and
  519  * profiling virtual time timers are kept in the p_stats area, since
  520  * they can be swapped out.  These are kept internally in the
  521  * way they are specified externally: in time until they expire.
  522  *
  523  * The real time interval timer is kept in the process table slot
  524  * for the process, and its value (it_value) is kept as an
  525  * absolute time rather than as a delta, so that it is easy to keep
  526  * periodic real-time signals from drifting.
  527  *
  528  * Virtual time timers are processed in the hardclock() routine of
  529  * kern_clock.c.  The real time timer is processed by a timeout
  530  * routine, called from the softclock() routine.  Since a callout
  531  * may be delayed in real time due to interrupt processing in the system,
  532  * it is possible for the real time timeout routine (realitexpire, given below),
  533  * to be delayed in real time past when it is supposed to occur.  It
  534  * does not suffice, therefore, to reload the real timer .it_value from the
  535  * real time timers .it_interval.  Rather, we compute the next time in
  536  * absolute time the timer should go off.
  537  */
  538 /* ARGSUSED */
  539 int
  540 sys_getitimer(struct proc *p, void *v, register_t *retval)
  541 {
  542         struct sys_getitimer_args /* {
  543                 syscallarg(int) which;
  544                 syscallarg(struct itimerval *) itv;
  545         } */ *uap = v;
  546         struct itimerval aitv;
  547         int s;
  548 
  549         if (SCARG(uap, which) < ITIMER_REAL || SCARG(uap, which) > ITIMER_PROF)
  550                 return (EINVAL);
  551         s = splclock();
  552         if (SCARG(uap, which) == ITIMER_REAL) {
  553                 struct timeval now;
  554 
  555                 getmicrouptime(&now);
  556                 /*
  557                  * Convert from absolute to relative time in .it_value
  558                  * part of real time timer.  If time for real time timer
  559                  * has passed return 0, else return difference between
  560                  * current time and time for the timer to go off.
  561                  */
  562                 aitv = p->p_realtimer;
  563                 if (timerisset(&aitv.it_value)) {
  564                         if (timercmp(&aitv.it_value, &now, <))
  565                                 timerclear(&aitv.it_value);
  566                         else
  567                                 timersub(&aitv.it_value, &now,
  568                                     &aitv.it_value);
  569                 }
  570         } else
  571                 aitv = p->p_stats->p_timer[SCARG(uap, which)];
  572         splx(s);
  573         return (copyout((void *)&aitv, (void *)SCARG(uap, itv),
  574             sizeof (struct itimerval)));
  575 }
  576 
  577 /* ARGSUSED */
  578 int
  579 sys_setitimer(struct proc *p, void *v, register_t *retval)
  580 {
  581         struct sys_setitimer_args /* {
  582                 syscallarg(int) which;
  583                 syscallarg(const struct itimerval *) itv;
  584                 syscallarg(struct itimerval *) oitv;
  585         } */ *uap = v;
  586         struct sys_getitimer_args getargs;
  587         struct itimerval aitv;
  588         const struct itimerval *itvp;
  589         int error;
  590         int timo;
  591 
  592         if (SCARG(uap, which) < ITIMER_REAL || SCARG(uap, which) > ITIMER_PROF)
  593                 return (EINVAL);
  594         itvp = SCARG(uap, itv);
  595         if (itvp && (error = copyin((void *)itvp, (void *)&aitv,
  596             sizeof(struct itimerval))))
  597                 return (error);
  598         if (SCARG(uap, oitv) != NULL) {
  599                 SCARG(&getargs, which) = SCARG(uap, which);
  600                 SCARG(&getargs, itv) = SCARG(uap, oitv);
  601                 if ((error = sys_getitimer(p, &getargs, retval)))
  602                         return (error);
  603         }
  604         if (itvp == 0)
  605                 return (0);
  606         if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
  607                 return (EINVAL);
  608         if (SCARG(uap, which) == ITIMER_REAL) {
  609                 struct timeval ctv;
  610 
  611                 timeout_del(&p->p_realit_to);
  612                 getmicrouptime(&ctv);
  613                 if (timerisset(&aitv.it_value)) {
  614                         timo = tvtohz(&aitv.it_value);
  615                         timeout_add(&p->p_realit_to, timo);
  616                         timeradd(&aitv.it_value, &ctv, &aitv.it_value);
  617                 }
  618                 p->p_realtimer = aitv;
  619         } else {
  620                 int s;
  621 
  622                 itimerround(&aitv.it_interval);
  623                 s = splclock();
  624                 p->p_stats->p_timer[SCARG(uap, which)] = aitv;
  625                 splx(s);
  626         }
  627 
  628         return (0);
  629 }
  630 
  631 /*
  632  * Real interval timer expired:
  633  * send process whose timer expired an alarm signal.
  634  * If time is not set up to reload, then just return.
  635  * Else compute next time timer should go off which is > current time.
  636  * This is where delay in processing this timeout causes multiple
  637  * SIGALRM calls to be compressed into one.
  638  */
  639 void
  640 realitexpire(void *arg)
  641 {
  642         struct proc *p;
  643 
  644         p = (struct proc *)arg;
  645         psignal(p, SIGALRM);
  646         if (!timerisset(&p->p_realtimer.it_interval)) {
  647                 timerclear(&p->p_realtimer.it_value);
  648                 return;
  649         }
  650         for (;;) {
  651                 struct timeval ctv, ntv;
  652                 int timo;
  653 
  654                 timeradd(&p->p_realtimer.it_value,
  655                     &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
  656                 getmicrouptime(&ctv);
  657                 if (timercmp(&p->p_realtimer.it_value, &ctv, >)) {
  658                         ntv = p->p_realtimer.it_value;
  659                         timersub(&ntv, &ctv, &ntv);
  660                         timo = tvtohz(&ntv) - 1;
  661                         if (timo <= 0)
  662                                 timo = 1;
  663                         if ((p->p_flag & P_WEXIT) == 0)
  664                                 timeout_add(&p->p_realit_to, timo);
  665                         return;
  666                 }
  667         }
  668 }
  669 
  670 /*
  671  * Check that a proposed value to load into the .it_value or
  672  * .it_interval part of an interval timer is acceptable.
  673  */
  674 int
  675 itimerfix(struct timeval *tv)
  676 {
  677 
  678         if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
  679             tv->tv_usec < 0 || tv->tv_usec >= 1000000)
  680                 return (EINVAL);
  681 
  682         if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
  683                 tv->tv_usec = tick;
  684 
  685         return (0);
  686 }
  687 
  688 /*
  689  * Timer interval smaller than the resolution of the system clock are
  690  * rounded up.
  691  */
  692 void
  693 itimerround(struct timeval *tv)
  694 {
  695         if (tv->tv_sec == 0 && tv->tv_usec < tick)
  696                 tv->tv_usec = tick;
  697 }
  698 
  699 /*
  700  * Decrement an interval timer by a specified number
  701  * of microseconds, which must be less than a second,
  702  * i.e. < 1000000.  If the timer expires, then reload
  703  * it.  In this case, carry over (usec - old value) to
  704  * reduce the value reloaded into the timer so that
  705  * the timer does not drift.  This routine assumes
  706  * that it is called in a context where the timers
  707  * on which it is operating cannot change in value.
  708  */
  709 int
  710 itimerdecr(struct itimerval *itp, int usec)
  711 {
  712 
  713         if (itp->it_value.tv_usec < usec) {
  714                 if (itp->it_value.tv_sec == 0) {
  715                         /* expired, and already in next interval */
  716                         usec -= itp->it_value.tv_usec;
  717                         goto expire;
  718                 }
  719                 itp->it_value.tv_usec += 1000000;
  720                 itp->it_value.tv_sec--;
  721         }
  722         itp->it_value.tv_usec -= usec;
  723         usec = 0;
  724         if (timerisset(&itp->it_value))
  725                 return (1);
  726         /* expired, exactly at end of interval */
  727 expire:
  728         if (timerisset(&itp->it_interval)) {
  729                 itp->it_value = itp->it_interval;
  730                 itp->it_value.tv_usec -= usec;
  731                 if (itp->it_value.tv_usec < 0) {
  732                         itp->it_value.tv_usec += 1000000;
  733                         itp->it_value.tv_sec--;
  734                 }
  735         } else
  736                 itp->it_value.tv_usec = 0;              /* sec is already 0 */
  737         return (0);
  738 }
  739 
  740 /*
  741  * ratecheck(): simple time-based rate-limit checking.  see ratecheck(9)
  742  * for usage and rationale.
  743  */
  744 int
  745 ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
  746 {
  747         struct timeval tv, delta;
  748         int rv = 0;
  749 
  750         microuptime(&tv);
  751 
  752         timersub(&tv, lasttime, &delta);
  753 
  754         /*
  755          * check for 0,0 is so that the message will be seen at least once,
  756          * even if interval is huge.
  757          */
  758         if (timercmp(&delta, mininterval, >=) ||
  759             (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
  760                 *lasttime = tv;
  761                 rv = 1;
  762         }
  763 
  764         return (rv);
  765 }
  766 
  767 /*
  768  * ppsratecheck(): packets (or events) per second limitation.
  769  */
  770 int
  771 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
  772 {
  773         struct timeval tv, delta;
  774         int rv;
  775 
  776         microuptime(&tv);
  777 
  778         timersub(&tv, lasttime, &delta);
  779 
  780         /*
  781          * check for 0,0 is so that the message will be seen at least once.
  782          * if more than one second have passed since the last update of
  783          * lasttime, reset the counter.
  784          *
  785          * we do increment *curpps even in *curpps < maxpps case, as some may
  786          * try to use *curpps for stat purposes as well.
  787          */
  788         if (maxpps == 0)
  789                 rv = 0;
  790         else if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||
  791             delta.tv_sec >= 1) {
  792                 *lasttime = tv;
  793                 *curpps = 0;
  794                 rv = 1;
  795         } else if (maxpps < 0)
  796                 rv = 1;
  797         else if (*curpps < maxpps)
  798                 rv = 1;
  799         else
  800                 rv = 0;
  801 
  802 #if 1 /*DIAGNOSTIC?*/
  803         /* be careful about wrap-around */
  804         if (*curpps + 1 > *curpps)
  805                 *curpps = *curpps + 1;
  806 #else
  807         /*
  808          * assume that there's not too many calls to this function.
  809          * not sure if the assumption holds, as it depends on *caller's*
  810          * behavior, not the behavior of this function.
  811          * IMHO it is wrong to make assumption on the caller's behavior,
  812          * so the above #if is #if 1, not #ifdef DIAGNOSTIC.
  813          */
  814         *curpps = *curpps + 1;
  815 #endif
  816 
  817         return (rv);
  818 }

/* [<][>][^][v][top][bottom][index][help] */