[BACK]Return to kern_time.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_time.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb