[BACK]Return to kern_time.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_time.c, Revision 1.101.2.1

1.101.2.1! gdamore     1: /*     $NetBSD: kern_time.c,v 1.102 2006/07/08 12:10:33 kardel Exp $   */
1.42      cgd         2:
                      3: /*-
1.88      mycroft     4:  * Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
1.42      cgd         5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Christopher G. Demetriou.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
1.9       cgd        38:
1.1       cgd        39: /*
1.8       cgd        40:  * Copyright (c) 1982, 1986, 1989, 1993
                     41:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd        42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
1.72      agc        51:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        52:  *    may be used to endorse or promote products derived from this software
                     53:  *    without specific prior written permission.
                     54:  *
                     55:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     56:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     57:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     58:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     59:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     60:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     61:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     63:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     64:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     65:  * SUCH DAMAGE.
                     66:  *
1.33      fvdl       67:  *     @(#)kern_time.c 8.4 (Berkeley) 5/26/95
1.1       cgd        68:  */
1.58      lukem      69:
                     70: #include <sys/cdefs.h>
1.101.2.1! gdamore    71: __KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.102 2006/07/08 12:10:33 kardel Exp $");
1.31      thorpej    72:
                     73: #include "fs_nfs.h"
1.54      bjh21      74: #include "opt_nfs.h"
1.34      thorpej    75: #include "opt_nfsserver.h"
1.1       cgd        76:
1.5       mycroft    77: #include <sys/param.h>
                     78: #include <sys/resourcevar.h>
                     79: #include <sys/kernel.h>
1.8       cgd        80: #include <sys/systm.h>
1.5       mycroft    81: #include <sys/proc.h>
1.63      thorpej    82: #include <sys/sa.h>
                     83: #include <sys/savar.h>
1.8       cgd        84: #include <sys/vnode.h>
1.17      christos   85: #include <sys/signalvar.h>
1.25      perry      86: #include <sys/syslog.h>
1.101     kardel     87: #ifdef __HAVE_TIMECOUNTER
                     88: #include <sys/timetc.h>
                     89: #else /* !__HAVE_TIMECOUNTER */
1.95      cube       90: #include <sys/timevar.h>
1.101     kardel     91: #endif /* !__HAVE_TIMECOUNTER */
1.99      elad       92: #include <sys/kauth.h>
1.1       cgd        93:
1.11      cgd        94: #include <sys/mount.h>
                     95: #include <sys/syscallargs.h>
1.19      christos   96:
1.37      thorpej    97: #include <uvm/uvm_extern.h>
                     98:
1.26      thorpej    99: #if defined(NFS) || defined(NFSSERVER)
1.20      fvdl      100: #include <nfs/rpcv2.h>
                    101: #include <nfs/nfsproto.h>
1.93      jmmv      102: #include <nfs/nfs.h>
1.19      christos  103: #include <nfs/nfs_var.h>
                    104: #endif
1.17      christos  105:
1.5       mycroft   106: #include <machine/cpu.h>
1.23      cgd       107:
1.97      simonb    108: POOL_INIT(ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
                    109:     &pool_allocator_nointr);
                    110: POOL_INIT(ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl",
                    111:     &pool_allocator_nointr);
                    112:
1.63      thorpej   113: static void timerupcall(struct lwp *, void *);
1.101     kardel    114: #ifdef __HAVE_TIMECOUNTER
                    115: static int itimespecfix(struct timespec *);            /* XXX move itimerfix to timespecs */
                    116: #endif /* __HAVE_TIMECOUNTER */
1.63      thorpej   117:
                    118: /* Time of day and interval timer support.
1.1       cgd       119:  *
                    120:  * These routines provide the kernel entry points to get and set
                    121:  * the time-of-day and per-process interval timers.  Subroutines
                    122:  * here provide support for adding and subtracting timeval structures
                    123:  * and decrementing interval timers, optionally reloading the interval
                    124:  * timers when they expire.
                    125:  */
                    126:
1.22      jtc       127: /* This function is used by clock_settime and settimeofday */
1.39      tron      128: int
1.98      christos  129: settime(struct proc *p, struct timespec *ts)
1.22      jtc       130: {
1.98      christos  131:        struct timeval delta, tv;
1.101     kardel    132: #ifdef __HAVE_TIMECOUNTER
                    133:        struct timeval now;
                    134:        struct timespec ts1;
                    135: #endif /* !__HAVE_TIMECOUNTER */
1.47      thorpej   136:        struct cpu_info *ci;
1.22      jtc       137:        int s;
                    138:
1.98      christos  139:        /*
                    140:         * Don't allow the time to be set forward so far it will wrap
                    141:         * and become negative, thus allowing an attacker to bypass
                    142:         * the next check below.  The cutoff is 1 year before rollover
                    143:         * occurs, so even if the attacker uses adjtime(2) to move
                    144:         * the time past the cutoff, it will take a very long time
                    145:         * to get to the wrap point.
                    146:         *
                    147:         * XXX: we check against INT_MAX since on 64-bit
                    148:         *      platforms, sizeof(int) != sizeof(long) and
                    149:         *      time_t is 32 bits even when atv.tv_sec is 64 bits.
                    150:         */
                    151:        if (ts->tv_sec > INT_MAX - 365*24*60*60) {
                    152:                struct proc *pp = p->p_pptr;
                    153:                log(LOG_WARNING, "pid %d (%s) "
                    154:                    "invoked by uid %d ppid %d (%s) "
                    155:                    "tried to set clock forward to %ld\n",
1.99      elad      156:                    p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred),
1.98      christos  157:                    pp->p_pid, pp->p_comm, (long)ts->tv_sec);
                    158:                return (EPERM);
                    159:        }
                    160:        TIMESPEC_TO_TIMEVAL(&tv, ts);
                    161:
1.22      jtc       162:        /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
                    163:        s = splclock();
1.101     kardel    164: #ifdef __HAVE_TIMECOUNTER
                    165:        microtime(&now);
                    166:        timersub(&tv, &now, &delta);
                    167: #else /* !__HAVE_TIMECOUNTER */
1.98      christos  168:        timersub(&tv, &time, &delta);
1.101     kardel    169: #endif /* !__HAVE_TIMECOUNTER */
1.55      tron      170:        if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1) {
                    171:                splx(s);
1.29      tls       172:                return (EPERM);
1.55      tron      173:        }
1.29      tls       174: #ifdef notyet
1.55      tron      175:        if ((delta.tv_sec < 86400) && securelevel > 0) {
                    176:                splx(s);
1.29      tls       177:                return (EPERM);
1.55      tron      178:        }
1.29      tls       179: #endif
1.101     kardel    180: #ifdef __HAVE_TIMECOUNTER
                    181:        ts1.tv_sec = tv.tv_sec;
                    182:        ts1.tv_nsec = tv.tv_usec * 1000;
                    183:        tc_setclock(&ts1);
                    184:        (void) spllowersoftclock();
                    185: #else /* !__HAVE_TIMECOUNTER */
1.98      christos  186:        time = tv;
1.38      thorpej   187:        (void) spllowersoftclock();
1.22      jtc       188:        timeradd(&boottime, &delta, &boottime);
1.101     kardel    189: #endif /* !__HAVE_TIMECOUNTER */
1.47      thorpej   190:        /*
                    191:         * XXXSMP
                    192:         * This is wrong.  We should traverse a list of all
                    193:         * CPUs and add the delta to the runtime of those
                    194:         * CPUs which have a process on them.
                    195:         */
                    196:        ci = curcpu();
                    197:        timeradd(&ci->ci_schedstate.spc_runtime, &delta,
                    198:            &ci->ci_schedstate.spc_runtime);
1.101     kardel    199: #if (defined(NFS) && !defined (NFS_V2_ONLY)) || defined(NFSSERVER)
                    200:        nqnfs_lease_updatetime(delta.tv_sec);
                    201: #endif
1.22      jtc       202:        splx(s);
                    203:        resettodr();
1.29      tls       204:        return (0);
1.22      jtc       205: }
                    206:
                    207: /* ARGSUSED */
                    208: int
1.63      thorpej   209: sys_clock_gettime(struct lwp *l, void *v, register_t *retval)
1.22      jtc       210: {
1.45      augustss  211:        struct sys_clock_gettime_args /* {
1.22      jtc       212:                syscallarg(clockid_t) clock_id;
1.23      cgd       213:                syscallarg(struct timespec *) tp;
                    214:        } */ *uap = v;
1.22      jtc       215:        clockid_t clock_id;
                    216:        struct timespec ats;
                    217:
                    218:        clock_id = SCARG(uap, clock_id);
1.61      simonb    219:        switch (clock_id) {
                    220:        case CLOCK_REALTIME:
1.96      simonb    221:                nanotime(&ats);
1.61      simonb    222:                break;
                    223:        case CLOCK_MONOTONIC:
1.101     kardel    224: #ifdef __HAVE_TIMECOUNTER
                    225:                nanouptime(&ats);
                    226: #else /* !__HAVE_TIMECOUNTER */
                    227:                {
                    228:                int s;
                    229:
1.61      simonb    230:                /* XXX "hz" granularity */
1.63      thorpej   231:                s = splclock();
1.101     kardel    232:                TIMEVAL_TO_TIMESPEC(&mono_time,&ats);
1.61      simonb    233:                splx(s);
1.101     kardel    234:                }
                    235: #endif /* !__HAVE_TIMECOUNTER */
1.61      simonb    236:                break;
                    237:        default:
1.22      jtc       238:                return (EINVAL);
1.61      simonb    239:        }
1.22      jtc       240:
1.24      cgd       241:        return copyout(&ats, SCARG(uap, tp), sizeof(ats));
1.22      jtc       242: }
                    243:
                    244: /* ARGSUSED */
                    245: int
1.90      thorpej   246: sys_clock_settime(struct lwp *l, void *v, register_t *retval)
1.22      jtc       247: {
1.45      augustss  248:        struct sys_clock_settime_args /* {
1.22      jtc       249:                syscallarg(clockid_t) clock_id;
1.23      cgd       250:                syscallarg(const struct timespec *) tp;
                    251:        } */ *uap = v;
1.63      thorpej   252:        struct proc *p = l->l_proc;
1.22      jtc       253:        int error;
                    254:
1.99      elad      255:        if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER,
                    256:                                       &p->p_acflag)) != 0)
1.22      jtc       257:                return (error);
                    258:
1.98      christos  259:        return (clock_settime1(p, SCARG(uap, clock_id), SCARG(uap, tp)));
1.56      manu      260: }
                    261:
                    262:
                    263: int
1.98      christos  264: clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp)
1.56      manu      265: {
1.60      manu      266:        struct timespec ats;
1.56      manu      267:        int error;
                    268:
1.60      manu      269:        if ((error = copyin(tp, &ats, sizeof(ats))) != 0)
                    270:                return (error);
                    271:
1.61      simonb    272:        switch (clock_id) {
                    273:        case CLOCK_REALTIME:
1.98      christos  274:                if ((error = settime(p, &ats)) != 0)
1.61      simonb    275:                        return (error);
                    276:                break;
                    277:        case CLOCK_MONOTONIC:
                    278:                return (EINVAL);        /* read-only clock */
                    279:        default:
1.56      manu      280:                return (EINVAL);
1.61      simonb    281:        }
1.22      jtc       282:
                    283:        return 0;
                    284: }
                    285:
                    286: int
1.63      thorpej   287: sys_clock_getres(struct lwp *l, void *v, register_t *retval)
1.22      jtc       288: {
1.45      augustss  289:        struct sys_clock_getres_args /* {
1.22      jtc       290:                syscallarg(clockid_t) clock_id;
1.23      cgd       291:                syscallarg(struct timespec *) tp;
                    292:        } */ *uap = v;
1.22      jtc       293:        clockid_t clock_id;
                    294:        struct timespec ts;
                    295:        int error = 0;
                    296:
                    297:        clock_id = SCARG(uap, clock_id);
1.61      simonb    298:        switch (clock_id) {
                    299:        case CLOCK_REALTIME:
                    300:        case CLOCK_MONOTONIC:
1.22      jtc       301:                ts.tv_sec = 0;
1.101.2.1! gdamore   302: #ifdef __HAVE_TIMECOUNTER
        !           303:                if (tc_getfrequency() > 1000000000)
        !           304:                        ts.tv_nsec = 1;
        !           305:                else
        !           306:                        ts.tv_nsec = 1000000000 / tc_getfrequency();
        !           307: #else /* !__HAVE_TIMECOUNTER */
1.22      jtc       308:                ts.tv_nsec = 1000000000 / hz;
1.101.2.1! gdamore   309: #endif /* !__HAVE_TIMECOUNTER */
1.61      simonb    310:                break;
                    311:        default:
                    312:                return (EINVAL);
                    313:        }
1.22      jtc       314:
1.61      simonb    315:        if (SCARG(uap, tp))
1.35      perry     316:                error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
1.22      jtc       317:
                    318:        return error;
                    319: }
                    320:
1.27      jtc       321: /* ARGSUSED */
                    322: int
1.63      thorpej   323: sys_nanosleep(struct lwp *l, void *v, register_t *retval)
1.27      jtc       324: {
1.101     kardel    325: #ifdef __HAVE_TIMECOUNTER
                    326:        static int nanowait;
                    327:        struct sys_nanosleep_args/* {
                    328:                syscallarg(struct timespec *) rqtp;
                    329:                syscallarg(struct timespec *) rmtp;
                    330:        } */ *uap = v;
                    331:        struct timespec rmt, rqt;
                    332:        int error, timo;
                    333:
                    334:        error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
                    335:        if (error)
                    336:                return (error);
                    337:
                    338:        if (itimespecfix(&rqt))
                    339:                return (EINVAL);
                    340:
                    341:        timo = tstohz(&rqt);
                    342:        /*
                    343:         * Avoid inadvertantly sleeping forever
                    344:         */
                    345:        if (timo == 0)
                    346:                timo = 1;
                    347:
                    348:        error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
                    349:        if (error == ERESTART)
                    350:                error = EINTR;
                    351:        if (error == EWOULDBLOCK)
                    352:                error = 0;
                    353:
                    354:        if (SCARG(uap, rmtp)) {
                    355:                int error1;
                    356:
                    357:                getnanotime(&rmt);
                    358:
                    359:                timespecsub(&rqt, &rmt, &rmt);
                    360:                if (rmt.tv_sec < 0)
                    361:                        timespecclear(&rmt);
                    362:
                    363:                error1 = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
                    364:                        sizeof(rmt));
                    365:                if (error1)
                    366:                        return (error1);
                    367:        }
                    368:
                    369:        return error;
                    370: #else /* !__HAVE_TIMECOUNTER */
1.27      jtc       371:        static int nanowait;
1.45      augustss  372:        struct sys_nanosleep_args/* {
1.27      jtc       373:                syscallarg(struct timespec *) rqtp;
                    374:                syscallarg(struct timespec *) rmtp;
                    375:        } */ *uap = v;
                    376:        struct timespec rqt;
                    377:        struct timespec rmt;
                    378:        struct timeval atv, utv;
                    379:        int error, s, timo;
                    380:
1.89      christos  381:        error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
1.27      jtc       382:        if (error)
                    383:                return (error);
                    384:
1.85      atatat    385:        TIMESPEC_TO_TIMEVAL(&atv,&rqt);
1.80      christos  386:        if (itimerfix(&atv))
1.27      jtc       387:                return (EINVAL);
                    388:
                    389:        s = splclock();
                    390:        timeradd(&atv,&time,&atv);
                    391:        timo = hzto(&atv);
1.63      thorpej   392:        /*
1.27      jtc       393:         * Avoid inadvertantly sleeping forever
                    394:         */
                    395:        if (timo == 0)
                    396:                timo = 1;
                    397:        splx(s);
                    398:
                    399:        error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
                    400:        if (error == ERESTART)
                    401:                error = EINTR;
                    402:        if (error == EWOULDBLOCK)
                    403:                error = 0;
                    404:
                    405:        if (SCARG(uap, rmtp)) {
1.89      christos  406:                int error1;
1.28      jtc       407:
1.27      jtc       408:                s = splclock();
                    409:                utv = time;
                    410:                splx(s);
                    411:
                    412:                timersub(&atv, &utv, &utv);
                    413:                if (utv.tv_sec < 0)
                    414:                        timerclear(&utv);
                    415:
                    416:                TIMEVAL_TO_TIMESPEC(&utv,&rmt);
1.89      christos  417:                error1 = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
1.28      jtc       418:                        sizeof(rmt));
1.89      christos  419:                if (error1)
                    420:                        return (error1);
1.27      jtc       421:        }
                    422:
                    423:        return error;
1.101     kardel    424: #endif /* !__HAVE_TIMECOUNTER */
1.27      jtc       425: }
1.22      jtc       426:
1.1       cgd       427: /* ARGSUSED */
1.3       andrew    428: int
1.63      thorpej   429: sys_gettimeofday(struct lwp *l, void *v, register_t *retval)
1.15      thorpej   430: {
1.45      augustss  431:        struct sys_gettimeofday_args /* {
1.11      cgd       432:                syscallarg(struct timeval *) tp;
1.84      simonb    433:                syscallarg(void *) tzp;         really "struct timezone *"
1.15      thorpej   434:        } */ *uap = v;
1.1       cgd       435:        struct timeval atv;
                    436:        int error = 0;
1.25      perry     437:        struct timezone tzfake;
1.1       cgd       438:
1.11      cgd       439:        if (SCARG(uap, tp)) {
1.1       cgd       440:                microtime(&atv);
1.35      perry     441:                error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
1.17      christos  442:                if (error)
1.1       cgd       443:                        return (error);
                    444:        }
1.25      perry     445:        if (SCARG(uap, tzp)) {
                    446:                /*
1.32      mycroft   447:                 * NetBSD has no kernel notion of time zone, so we just
1.25      perry     448:                 * fake up a timezone struct and return it if demanded.
                    449:                 */
                    450:                tzfake.tz_minuteswest = 0;
                    451:                tzfake.tz_dsttime = 0;
1.35      perry     452:                error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
1.25      perry     453:        }
1.1       cgd       454:        return (error);
                    455: }
                    456:
                    457: /* ARGSUSED */
1.3       andrew    458: int
1.63      thorpej   459: sys_settimeofday(struct lwp *l, void *v, register_t *retval)
1.15      thorpej   460: {
1.16      mycroft   461:        struct sys_settimeofday_args /* {
1.24      cgd       462:                syscallarg(const struct timeval *) tv;
1.84      simonb    463:                syscallarg(const void *) tzp;   really "const struct timezone *"
1.15      thorpej   464:        } */ *uap = v;
1.63      thorpej   465:        struct proc *p = l->l_proc;
1.60      manu      466:        int error;
                    467:
1.99      elad      468:        if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER,
                    469:                                       &p->p_acflag)) != 0)
1.60      manu      470:                return (error);
                    471:
                    472:        return settimeofday1(SCARG(uap, tv), SCARG(uap, tzp), p);
                    473: }
                    474:
                    475: int
1.90      thorpej   476: settimeofday1(const struct timeval *utv, const struct timezone *utzp,
                    477:     struct proc *p)
1.60      manu      478: {
1.22      jtc       479:        struct timeval atv;
1.98      christos  480:        struct timespec ts;
1.22      jtc       481:        int error;
1.1       cgd       482:
1.8       cgd       483:        /* Verify all parameters before changing time. */
1.25      perry     484:        /*
1.32      mycroft   485:         * NetBSD has no kernel notion of time zone, and only an
1.25      perry     486:         * obsolete program would try to set it, so we log a warning.
                    487:         */
1.98      christos  488:        if (utzp)
1.25      perry     489:                log(LOG_WARNING, "pid %d attempted to set the "
1.63      thorpej   490:                    "(obsolete) kernel time zone\n", p->p_pid);
1.98      christos  491:
                    492:        if (utv == NULL)
                    493:                return 0;
                    494:
                    495:        if ((error = copyin(utv, &atv, sizeof(atv))) != 0)
                    496:                return error;
                    497:        TIMEVAL_TO_TIMESPEC(&atv, &ts);
                    498:        return settime(p, &ts);
1.1       cgd       499: }
                    500:
1.101     kardel    501: #ifndef __HAVE_TIMECOUNTER
1.1       cgd       502: int    tickdelta;                      /* current clock skew, us. per tick */
                    503: long   timedelta;                      /* unapplied time correction, us. */
                    504: long   bigadj = 1000000;               /* use 10x skew above bigadj us. */
1.101     kardel    505: #endif
                    506:
1.68      dsl       507: int    time_adjusted;                  /* set if an adjustment is made */
1.1       cgd       508:
                    509: /* ARGSUSED */
1.3       andrew    510: int
1.63      thorpej   511: sys_adjtime(struct lwp *l, void *v, register_t *retval)
1.15      thorpej   512: {
1.45      augustss  513:        struct sys_adjtime_args /* {
1.24      cgd       514:                syscallarg(const struct timeval *) delta;
1.11      cgd       515:                syscallarg(struct timeval *) olddelta;
1.15      thorpej   516:        } */ *uap = v;
1.63      thorpej   517:        struct proc *p = l->l_proc;
1.56      manu      518:        int error;
1.1       cgd       519:
1.99      elad      520:        if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER,
                    521:                                       &p->p_acflag)) != 0)
1.1       cgd       522:                return (error);
1.17      christos  523:
1.60      manu      524:        return adjtime1(SCARG(uap, delta), SCARG(uap, olddelta), p);
1.56      manu      525: }
                    526:
                    527: int
1.90      thorpej   528: adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p)
1.56      manu      529: {
1.60      manu      530:        struct timeval atv;
1.101     kardel    531:        int error = 0;
                    532:
                    533: #ifdef __HAVE_TIMECOUNTER
                    534:        extern int64_t time_adjtime;  /* in kern_ntptime.c */
                    535: #else /* !__HAVE_TIMECOUNTER */
1.56      manu      536:        long ndelta, ntickdelta, odelta;
                    537:        int s;
1.101     kardel    538: #endif /* !__HAVE_TIMECOUNTER */
                    539:
                    540: #ifdef __HAVE_TIMECOUNTER
                    541:        if (olddelta) {
                    542:                atv.tv_sec = time_adjtime / 1000000;
                    543:                atv.tv_usec = time_adjtime % 1000000;
                    544:                if (atv.tv_usec < 0) {
                    545:                        atv.tv_usec += 1000000;
                    546:                        atv.tv_sec--;
                    547:                }
                    548:                error = copyout(&atv, olddelta, sizeof(struct timeval));
                    549:                if (error)
                    550:                        return (error);
                    551:        }
                    552:
                    553:        if (delta) {
                    554:                error = copyin(delta, &atv, sizeof(struct timeval));
                    555:                if (error)
                    556:                        return (error);
                    557:
                    558:                time_adjtime = (int64_t)atv.tv_sec * 1000000 +
                    559:                        atv.tv_usec;
1.8       cgd       560:
1.101     kardel    561:                if (time_adjtime)
                    562:                        /* We need to save the system time during shutdown */
                    563:                        time_adjusted |= 1;
                    564:        }
                    565: #else /* !__HAVE_TIMECOUNTER */
1.60      manu      566:        error = copyin(delta, &atv, sizeof(struct timeval));
                    567:        if (error)
                    568:                return (error);
                    569:
1.8       cgd       570:        /*
                    571:         * Compute the total correction and the rate at which to apply it.
                    572:         * Round the adjustment down to a whole multiple of the per-tick
                    573:         * delta, so that after some number of incremental changes in
                    574:         * hardclock(), tickdelta will become zero, lest the correction
                    575:         * overshoot and start taking us away from the desired final time.
                    576:         */
1.60      manu      577:        ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
1.41      hwr       578:        if (ndelta > bigadj || ndelta < -bigadj)
1.8       cgd       579:                ntickdelta = 10 * tickadj;
                    580:        else
                    581:                ntickdelta = tickadj;
                    582:        if (ndelta % ntickdelta)
                    583:                ndelta = ndelta / ntickdelta * ntickdelta;
                    584:
                    585:        /*
                    586:         * To make hardclock()'s job easier, make the per-tick delta negative
                    587:         * if we want time to run slower; then hardclock can simply compute
                    588:         * tick + tickdelta, and subtract tickdelta from timedelta.
                    589:         */
                    590:        if (ndelta < 0)
                    591:                ntickdelta = -ntickdelta;
1.68      dsl       592:        if (ndelta != 0)
                    593:                /* We need to save the system clock time during shutdown */
                    594:                time_adjusted |= 1;
1.1       cgd       595:        s = splclock();
1.8       cgd       596:        odelta = timedelta;
1.1       cgd       597:        timedelta = ndelta;
1.8       cgd       598:        tickdelta = ntickdelta;
1.1       cgd       599:        splx(s);
                    600:
1.56      manu      601:        if (olddelta) {
1.60      manu      602:                atv.tv_sec = odelta / 1000000;
                    603:                atv.tv_usec = odelta % 1000000;
1.79      chs       604:                error = copyout(&atv, olddelta, sizeof(struct timeval));
1.8       cgd       605:        }
1.101     kardel    606: #endif /* __HAVE_TIMECOUNTER */
                    607:
1.79      chs       608:        return error;
1.1       cgd       609: }
                    610:
                    611: /*
1.63      thorpej   612:  * Interval timer support. Both the BSD getitimer() family and the POSIX
                    613:  * timer_*() family of routines are supported.
1.1       cgd       614:  *
1.63      thorpej   615:  * All timers are kept in an array pointed to by p_timers, which is
                    616:  * allocated on demand - many processes don't use timers at all. The
                    617:  * first three elements in this array are reserved for the BSD timers:
                    618:  * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, and element
                    619:  * 2 is ITIMER_PROF. The rest may be allocated by the timer_create()
                    620:  * syscall.
1.1       cgd       621:  *
1.63      thorpej   622:  * Realtime timers are kept in the ptimer structure as an absolute
                    623:  * time; virtual time timers are kept as a linked list of deltas.
1.1       cgd       624:  * Virtual time timers are processed in the hardclock() routine of
1.63      thorpej   625:  * kern_clock.c.  The real time timer is processed by a callout
                    626:  * routine, called from the softclock() routine.  Since a callout may
                    627:  * be delayed in real time due to interrupt processing in the system,
                    628:  * it is possible for the real time timeout routine (realtimeexpire,
                    629:  * given below), to be delayed in real time past when it is supposed
                    630:  * to occur.  It does not suffice, therefore, to reload the real timer
                    631:  * .it_value from the real time timers .it_interval.  Rather, we
                    632:  * compute the next time in absolute time the timer should go off.  */
                    633:
                    634: /* Allocate a POSIX realtime timer. */
                    635: int
                    636: sys_timer_create(struct lwp *l, void *v, register_t *retval)
                    637: {
                    638:        struct sys_timer_create_args /* {
                    639:                syscallarg(clockid_t) clock_id;
                    640:                syscallarg(struct sigevent *) evp;
                    641:                syscallarg(timer_t *) timerid;
                    642:        } */ *uap = v;
1.92      cube      643:
                    644:        return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id),
                    645:            SCARG(uap, evp), copyin, l->l_proc);
                    646: }
                    647:
                    648: int
                    649: timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp,
1.95      cube      650:     copyin_t fetch_event, struct proc *p)
1.92      cube      651: {
                    652:        int error;
                    653:        timer_t timerid;
1.63      thorpej   654:        struct ptimer *pt;
                    655:
                    656:        if (id < CLOCK_REALTIME ||
                    657:            id > CLOCK_PROF)
                    658:                return (EINVAL);
                    659:
                    660:        if (p->p_timers == NULL)
                    661:                timers_alloc(p);
                    662:
                    663:        /* Find a free timer slot, skipping those reserved for setitimer(). */
                    664:        for (timerid = 3; timerid < TIMER_MAX; timerid++)
                    665:                if (p->p_timers->pts_timers[timerid] == NULL)
                    666:                        break;
                    667:
                    668:        if (timerid == TIMER_MAX)
                    669:                return EAGAIN;
                    670:
                    671:        pt = pool_get(&ptimer_pool, PR_WAITOK);
                    672:        if (evp) {
                    673:                if (((error =
1.92      cube      674:                    (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) ||
1.63      thorpej   675:                    ((pt->pt_ev.sigev_notify < SIGEV_NONE) ||
                    676:                        (pt->pt_ev.sigev_notify > SIGEV_SA))) {
                    677:                        pool_put(&ptimer_pool, pt);
                    678:                        return (error ? error : EINVAL);
                    679:                }
                    680:        } else {
                    681:                pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
                    682:                switch (id) {
                    683:                case CLOCK_REALTIME:
                    684:                        pt->pt_ev.sigev_signo = SIGALRM;
                    685:                        break;
                    686:                case CLOCK_VIRTUAL:
                    687:                        pt->pt_ev.sigev_signo = SIGVTALRM;
                    688:                        break;
                    689:                case CLOCK_PROF:
                    690:                        pt->pt_ev.sigev_signo = SIGPROF;
                    691:                        break;
                    692:                }
                    693:                pt->pt_ev.sigev_value.sival_int = timerid;
                    694:        }
1.73      christos  695:        pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo;
                    696:        pt->pt_info.ksi_errno = 0;
                    697:        pt->pt_info.ksi_code = 0;
                    698:        pt->pt_info.ksi_pid = p->p_pid;
1.99      elad      699:        pt->pt_info.ksi_uid = kauth_cred_getuid(p->p_cred);
1.73      christos  700:        pt->pt_info.ksi_sigval = pt->pt_ev.sigev_value;
1.63      thorpej   701:
                    702:        pt->pt_type = id;
                    703:        pt->pt_proc = p;
                    704:        pt->pt_overruns = 0;
                    705:        pt->pt_poverruns = 0;
1.64      nathanw   706:        pt->pt_entry = timerid;
1.63      thorpej   707:        timerclear(&pt->pt_time.it_value);
                    708:        if (id == CLOCK_REALTIME)
                    709:                callout_init(&pt->pt_ch);
                    710:        else
                    711:                pt->pt_active = 0;
                    712:
                    713:        p->p_timers->pts_timers[timerid] = pt;
                    714:
1.92      cube      715:        return copyout(&timerid, tid, sizeof(timerid));
1.63      thorpej   716: }
                    717:
                    718: /* Delete a POSIX realtime timer */
1.3       andrew    719: int
1.63      thorpej   720: sys_timer_delete(struct lwp *l, void *v, register_t *retval)
1.15      thorpej   721: {
1.63      thorpej   722:        struct sys_timer_delete_args /*  {
                    723:                syscallarg(timer_t) timerid;
1.15      thorpej   724:        } */ *uap = v;
1.63      thorpej   725:        struct proc *p = l->l_proc;
1.65      jdolecek  726:        timer_t timerid;
1.63      thorpej   727:        struct ptimer *pt, *ptn;
1.1       cgd       728:        int s;
                    729:
1.63      thorpej   730:        timerid = SCARG(uap, timerid);
                    731:
                    732:        if ((p->p_timers == NULL) ||
                    733:            (timerid < 2) || (timerid >= TIMER_MAX) ||
                    734:            ((pt = p->p_timers->pts_timers[timerid]) == NULL))
1.1       cgd       735:                return (EINVAL);
1.63      thorpej   736:
                    737:        if (pt->pt_type == CLOCK_REALTIME)
                    738:                callout_stop(&pt->pt_ch);
                    739:        else if (pt->pt_active) {
                    740:                s = splclock();
                    741:                ptn = LIST_NEXT(pt, pt_list);
                    742:                LIST_REMOVE(pt, pt_list);
                    743:                for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
                    744:                        timeradd(&pt->pt_time.it_value, &ptn->pt_time.it_value,
                    745:                            &ptn->pt_time.it_value);
                    746:                splx(s);
                    747:        }
                    748:
                    749:        p->p_timers->pts_timers[timerid] = NULL;
                    750:        pool_put(&ptimer_pool, pt);
                    751:
                    752:        return (0);
                    753: }
                    754:
                    755: /*
1.67      nathanw   756:  * Set up the given timer. The value in pt->pt_time.it_value is taken
                    757:  * to be an absolute time for CLOCK_REALTIME timers and a relative
                    758:  * time for virtual timers.
1.63      thorpej   759:  * Must be called at splclock().
                    760:  */
                    761: void
                    762: timer_settime(struct ptimer *pt)
                    763: {
                    764:        struct ptimer *ptn, *pptn;
                    765:        struct ptlist *ptl;
                    766:
                    767:        if (pt->pt_type == CLOCK_REALTIME) {
                    768:                callout_stop(&pt->pt_ch);
                    769:                if (timerisset(&pt->pt_time.it_value)) {
                    770:                        /*
                    771:                         * Don't need to check hzto() return value, here.
                    772:                         * callout_reset() does it for us.
                    773:                         */
                    774:                        callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
                    775:                            realtimerexpire, pt);
                    776:                }
                    777:        } else {
                    778:                if (pt->pt_active) {
                    779:                        ptn = LIST_NEXT(pt, pt_list);
                    780:                        LIST_REMOVE(pt, pt_list);
                    781:                        for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
                    782:                                timeradd(&pt->pt_time.it_value,
                    783:                                    &ptn->pt_time.it_value,
                    784:                                    &ptn->pt_time.it_value);
                    785:                }
                    786:                if (timerisset(&pt->pt_time.it_value)) {
                    787:                        if (pt->pt_type == CLOCK_VIRTUAL)
                    788:                                ptl = &pt->pt_proc->p_timers->pts_virtual;
                    789:                        else
                    790:                                ptl = &pt->pt_proc->p_timers->pts_prof;
                    791:
                    792:                        for (ptn = LIST_FIRST(ptl), pptn = NULL;
                    793:                             ptn && timercmp(&pt->pt_time.it_value,
                    794:                                 &ptn->pt_time.it_value, >);
                    795:                             pptn = ptn, ptn = LIST_NEXT(ptn, pt_list))
                    796:                                timersub(&pt->pt_time.it_value,
                    797:                                    &ptn->pt_time.it_value,
                    798:                                    &pt->pt_time.it_value);
                    799:
                    800:                        if (pptn)
                    801:                                LIST_INSERT_AFTER(pptn, pt, pt_list);
                    802:                        else
                    803:                                LIST_INSERT_HEAD(ptl, pt, pt_list);
                    804:
                    805:                        for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list))
                    806:                                timersub(&ptn->pt_time.it_value,
                    807:                                    &pt->pt_time.it_value,
                    808:                                    &ptn->pt_time.it_value);
                    809:
                    810:                        pt->pt_active = 1;
                    811:                } else
                    812:                        pt->pt_active = 0;
                    813:        }
                    814: }
                    815:
                    816: void
                    817: timer_gettime(struct ptimer *pt, struct itimerval *aitv)
                    818: {
1.101     kardel    819: #ifdef __HAVE_TIMECOUNTER
                    820:        struct timeval now;
                    821: #endif
1.63      thorpej   822:        struct ptimer *ptn;
                    823:
                    824:        *aitv = pt->pt_time;
                    825:        if (pt->pt_type == CLOCK_REALTIME) {
1.1       cgd       826:                /*
1.12      mycroft   827:                 * Convert from absolute to relative time in .it_value
1.63      thorpej   828:                 * part of real time timer.  If time for real time
                    829:                 * timer has passed return 0, else return difference
                    830:                 * between current time and time for the timer to go
                    831:                 * off.
1.1       cgd       832:                 */
1.63      thorpej   833:                if (timerisset(&aitv->it_value)) {
1.101     kardel    834: #ifdef __HAVE_TIMECOUNTER
                    835:                        getmicrotime(&now);
                    836:                        if (timercmp(&aitv->it_value, &now, <))
                    837:                                timerclear(&aitv->it_value);
                    838:                        else
                    839:                                timersub(&aitv->it_value, &now,
                    840:                                    &aitv->it_value);
                    841: #else /* !__HAVE_TIMECOUNTER */
1.63      thorpej   842:                        if (timercmp(&aitv->it_value, &time, <))
                    843:                                timerclear(&aitv->it_value);
1.1       cgd       844:                        else
1.63      thorpej   845:                                timersub(&aitv->it_value, &time,
                    846:                                    &aitv->it_value);
1.101     kardel    847: #endif /* !__HAVE_TIMECOUNTER */
1.36      thorpej   848:                }
1.63      thorpej   849:        } else if (pt->pt_active) {
                    850:                if (pt->pt_type == CLOCK_VIRTUAL)
                    851:                        ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual);
                    852:                else
                    853:                        ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof);
                    854:                for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list))
                    855:                        timeradd(&aitv->it_value,
                    856:                            &ptn->pt_time.it_value, &aitv->it_value);
                    857:                KASSERT(ptn != NULL); /* pt should be findable on the list */
1.1       cgd       858:        } else
1.63      thorpej   859:                timerclear(&aitv->it_value);
                    860: }
                    861:
                    862:
                    863:
                    864: /* Set and arm a POSIX realtime timer */
                    865: int
                    866: sys_timer_settime(struct lwp *l, void *v, register_t *retval)
                    867: {
                    868:        struct sys_timer_settime_args /* {
                    869:                syscallarg(timer_t) timerid;
                    870:                syscallarg(int) flags;
                    871:                syscallarg(const struct itimerspec *) value;
                    872:                syscallarg(struct itimerspec *) ovalue;
                    873:        } */ *uap = v;
1.92      cube      874:        int error;
                    875:        struct itimerspec value, ovalue, *ovp = NULL;
                    876:
                    877:        if ((error = copyin(SCARG(uap, value), &value,
                    878:            sizeof(struct itimerspec))) != 0)
                    879:                return (error);
                    880:
                    881:        if (SCARG(uap, ovalue))
                    882:                ovp = &ovalue;
                    883:
                    884:        if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
                    885:            SCARG(uap, flags), l->l_proc)) != 0)
                    886:                return error;
                    887:
                    888:        if (ovp)
                    889:                return copyout(&ovalue, SCARG(uap, ovalue),
                    890:                    sizeof(struct itimerspec));
                    891:        return 0;
                    892: }
                    893:
                    894: int
                    895: dotimer_settime(int timerid, struct itimerspec *value,
                    896:     struct itimerspec *ovalue, int flags, struct proc *p)
                    897: {
1.101     kardel    898: #ifdef __HAVE_TIMECOUNTER
                    899:        struct timeval now;
                    900: #endif
1.63      thorpej   901:        struct itimerval val, oval;
                    902:        struct ptimer *pt;
1.101     kardel    903:        int s;
1.63      thorpej   904:
                    905:        if ((p->p_timers == NULL) ||
                    906:            (timerid < 2) || (timerid >= TIMER_MAX) ||
                    907:            ((pt = p->p_timers->pts_timers[timerid]) == NULL))
                    908:                return (EINVAL);
                    909:
1.92      cube      910:        TIMESPEC_TO_TIMEVAL(&val.it_value, &value->it_value);
                    911:        TIMESPEC_TO_TIMEVAL(&val.it_interval, &value->it_interval);
1.63      thorpej   912:        if (itimerfix(&val.it_value) || itimerfix(&val.it_interval))
                    913:                return (EINVAL);
                    914:
                    915:        oval = pt->pt_time;
                    916:        pt->pt_time = val;
                    917:
                    918:        s = splclock();
1.67      nathanw   919:        /*
                    920:         * If we've been passed a relative time for a realtime timer,
                    921:         * convert it to absolute; if an absolute time for a virtual
                    922:         * timer, convert it to relative and make sure we don't set it
                    923:         * to zero, which would cancel the timer, or let it go
                    924:         * negative, which would confuse the comparison tests.
                    925:         */
                    926:        if (timerisset(&pt->pt_time.it_value)) {
                    927:                if (pt->pt_type == CLOCK_REALTIME) {
1.101     kardel    928: #ifdef __HAVE_TIMECOUNTER
                    929:                        if ((flags & TIMER_ABSTIME) == 0) {
                    930:                                getmicrotime(&now);
                    931:                                timeradd(&pt->pt_time.it_value, &now,
                    932:                                    &pt->pt_time.it_value);
                    933:                        }
                    934: #else /* !__HAVE_TIMECOUNTER */
1.92      cube      935:                        if ((flags & TIMER_ABSTIME) == 0)
1.67      nathanw   936:                                timeradd(&pt->pt_time.it_value, &time,
                    937:                                    &pt->pt_time.it_value);
1.101     kardel    938: #endif /* !__HAVE_TIMECOUNTER */
1.67      nathanw   939:                } else {
1.92      cube      940:                        if ((flags & TIMER_ABSTIME) != 0) {
1.101     kardel    941: #ifdef __HAVE_TIMECOUNTER
                    942:                                getmicrotime(&now);
                    943:                                timersub(&pt->pt_time.it_value, &now,
                    944:                                    &pt->pt_time.it_value);
                    945: #else /* !__HAVE_TIMECOUNTER */
1.67      nathanw   946:                                timersub(&pt->pt_time.it_value, &time,
                    947:                                    &pt->pt_time.it_value);
1.101     kardel    948: #endif /* !__HAVE_TIMECOUNTER */
1.67      nathanw   949:                                if (!timerisset(&pt->pt_time.it_value) ||
                    950:                                    pt->pt_time.it_value.tv_sec < 0) {
                    951:                                        pt->pt_time.it_value.tv_sec = 0;
                    952:                                        pt->pt_time.it_value.tv_usec = 1;
                    953:                                }
                    954:                        }
                    955:                }
                    956:        }
                    957:
1.63      thorpej   958:        timer_settime(pt);
                    959:        splx(s);
                    960:
1.92      cube      961:        if (ovalue) {
                    962:                TIMEVAL_TO_TIMESPEC(&oval.it_value, &ovalue->it_value);
                    963:                TIMEVAL_TO_TIMESPEC(&oval.it_interval, &ovalue->it_interval);
1.63      thorpej   964:        }
                    965:
                    966:        return (0);
                    967: }
                    968:
                    969: /* Return the time remaining until a POSIX timer fires. */
                    970: int
                    971: sys_timer_gettime(struct lwp *l, void *v, register_t *retval)
                    972: {
                    973:        struct sys_timer_gettime_args /* {
                    974:                syscallarg(timer_t) timerid;
                    975:                syscallarg(struct itimerspec *) value;
                    976:        } */ *uap = v;
                    977:        struct itimerspec its;
1.92      cube      978:        int error;
                    979:
                    980:        if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
                    981:            &its)) != 0)
                    982:                return error;
                    983:
                    984:        return copyout(&its, SCARG(uap, value), sizeof(its));
                    985: }
                    986:
                    987: int
                    988: dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its)
                    989: {
                    990:        int s;
1.63      thorpej   991:        struct ptimer *pt;
1.92      cube      992:        struct itimerval aitv;
1.63      thorpej   993:
                    994:        if ((p->p_timers == NULL) ||
                    995:            (timerid < 2) || (timerid >= TIMER_MAX) ||
                    996:            ((pt = p->p_timers->pts_timers[timerid]) == NULL))
                    997:                return (EINVAL);
                    998:
                    999:        s = splclock();
                   1000:        timer_gettime(pt, &aitv);
1.1       cgd      1001:        splx(s);
1.63      thorpej  1002:
1.92      cube     1003:        TIMEVAL_TO_TIMESPEC(&aitv.it_interval, &its->it_interval);
                   1004:        TIMEVAL_TO_TIMESPEC(&aitv.it_value, &its->it_value);
1.63      thorpej  1005:
1.92      cube     1006:        return 0;
1.63      thorpej  1007: }
                   1008:
                   1009: /*
                   1010:  * Return the count of the number of times a periodic timer expired
                   1011:  * while a notification was already pending. The counter is reset when
                   1012:  * a timer expires and a notification can be posted.
                   1013:  */
                   1014: int
                   1015: sys_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
                   1016: {
                   1017:        struct sys_timer_getoverrun_args /* {
                   1018:                syscallarg(timer_t) timerid;
                   1019:        } */ *uap = v;
                   1020:        struct proc *p = l->l_proc;
                   1021:        int timerid;
                   1022:        struct ptimer *pt;
                   1023:
                   1024:        timerid = SCARG(uap, timerid);
                   1025:
                   1026:        if ((p->p_timers == NULL) ||
                   1027:            (timerid < 2) || (timerid >= TIMER_MAX) ||
                   1028:            ((pt = p->p_timers->pts_timers[timerid]) == NULL))
                   1029:                return (EINVAL);
                   1030:
                   1031:        *retval = pt->pt_poverruns;
                   1032:
                   1033:        return (0);
                   1034: }
                   1035:
                   1036: /* Glue function that triggers an upcall; called from userret(). */
                   1037: static void
                   1038: timerupcall(struct lwp *l, void *arg)
                   1039: {
1.64      nathanw  1040:        struct ptimers *pt = (struct ptimers *)arg;
                   1041:        unsigned int i, fired, done;
1.74      cl       1042:
1.81      cl       1043:        KDASSERT(l->l_proc->p_sa);
                   1044:        /* Bail out if we do not own the virtual processor */
1.82      cl       1045:        if (l->l_savp->savp_lwp != l)
1.81      cl       1046:                return ;
1.87      perry    1047:
1.63      thorpej  1048:        KERNEL_PROC_LOCK(l);
1.71      fvdl     1049:
1.64      nathanw  1050:        fired = pt->pts_fired;
                   1051:        done = 0;
                   1052:        while ((i = ffs(fired)) != 0) {
1.74      cl       1053:                siginfo_t *si;
1.73      christos 1054:                int mask = 1 << --i;
1.74      cl       1055:                int f;
1.73      christos 1056:
1.74      cl       1057:                f = l->l_flag & L_SA;
                   1058:                l->l_flag &= ~L_SA;
1.94      chs      1059:                si = siginfo_alloc(PR_WAITOK);
1.77      thorpej  1060:                si->_info = pt->pts_timers[i]->pt_info.ksi_info;
1.64      nathanw  1061:                if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l,
1.94      chs      1062:                    sizeof(*si), si, siginfo_free) != 0) {
                   1063:                        siginfo_free(si);
1.86      mycroft  1064:                        /* XXX What do we do here?? */
                   1065:                } else
1.73      christos 1066:                        done |= mask;
                   1067:                fired &= ~mask;
1.74      cl       1068:                l->l_flag |= f;
1.64      nathanw  1069:        }
                   1070:        pt->pts_fired &= ~done;
                   1071:        if (pt->pts_fired == 0)
1.63      thorpej  1072:                l->l_proc->p_userret = NULL;
                   1073:
                   1074:        KERNEL_PROC_UNLOCK(l);
                   1075: }
                   1076:
                   1077: /*
                   1078:  * Real interval timer expired:
                   1079:  * send process whose timer expired an alarm signal.
                   1080:  * If time is not set up to reload, then just return.
                   1081:  * Else compute next time timer should go off which is > current time.
                   1082:  * This is where delay in processing this timeout causes multiple
                   1083:  * SIGALRM calls to be compressed into one.
                   1084:  */
                   1085: void
                   1086: realtimerexpire(void *arg)
                   1087: {
1.101     kardel   1088: #ifdef __HAVE_TIMECOUNTER
                   1089:        struct timeval now;
                   1090: #endif
1.63      thorpej  1091:        struct ptimer *pt;
                   1092:        int s;
                   1093:
                   1094:        pt = (struct ptimer *)arg;
                   1095:
                   1096:        itimerfire(pt);
                   1097:
                   1098:        if (!timerisset(&pt->pt_time.it_interval)) {
                   1099:                timerclear(&pt->pt_time.it_value);
                   1100:                return;
                   1101:        }
1.101     kardel   1102: #ifdef __HAVE_TIMECOUNTER
                   1103:        for (;;) {
                   1104:                s = splclock(); /* XXX need spl now? */
                   1105:                timeradd(&pt->pt_time.it_value,
                   1106:                    &pt->pt_time.it_interval, &pt->pt_time.it_value);
                   1107:                getmicrotime(&now);
                   1108:                if (timercmp(&pt->pt_time.it_value, &now, >)) {
                   1109:                        /*
                   1110:                         * Don't need to check hzto() return value, here.
                   1111:                         * callout_reset() does it for us.
                   1112:                         */
                   1113:                        callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
                   1114:                            realtimerexpire, pt);
                   1115:                        splx(s);
                   1116:                        return;
                   1117:                }
                   1118:                splx(s);
                   1119:                pt->pt_overruns++;
                   1120:        }
                   1121: #else /* !__HAVE_TIMECOUNTER */
1.63      thorpej  1122:        for (;;) {
                   1123:                s = splclock();
                   1124:                timeradd(&pt->pt_time.it_value,
                   1125:                    &pt->pt_time.it_interval, &pt->pt_time.it_value);
                   1126:                if (timercmp(&pt->pt_time.it_value, &time, >)) {
                   1127:                        /*
                   1128:                         * Don't need to check hzto() return value, here.
                   1129:                         * callout_reset() does it for us.
                   1130:                         */
                   1131:                        callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
                   1132:                            realtimerexpire, pt);
                   1133:                        splx(s);
                   1134:                        return;
                   1135:                }
                   1136:                splx(s);
                   1137:                pt->pt_overruns++;
                   1138:        }
1.101     kardel   1139: #endif /* !__HAVE_TIMECOUNTER */
1.63      thorpej  1140: }
                   1141:
                   1142: /* BSD routine to get the value of an interval timer. */
                   1143: /* ARGSUSED */
                   1144: int
                   1145: sys_getitimer(struct lwp *l, void *v, register_t *retval)
                   1146: {
                   1147:        struct sys_getitimer_args /* {
                   1148:                syscallarg(int) which;
                   1149:                syscallarg(struct itimerval *) itv;
                   1150:        } */ *uap = v;
                   1151:        struct proc *p = l->l_proc;
                   1152:        struct itimerval aitv;
1.91      cube     1153:        int error;
                   1154:
                   1155:        error = dogetitimer(p, SCARG(uap, which), &aitv);
                   1156:        if (error)
                   1157:                return error;
                   1158:        return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
                   1159: }
1.63      thorpej  1160:
1.91      cube     1161: int
                   1162: dogetitimer(struct proc *p, int which, struct itimerval *itvp)
                   1163: {
                   1164:        int s;
1.63      thorpej  1165:
                   1166:        if ((u_int)which > ITIMER_PROF)
                   1167:                return (EINVAL);
                   1168:
                   1169:        if ((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)){
1.91      cube     1170:                timerclear(&itvp->it_value);
                   1171:                timerclear(&itvp->it_interval);
1.63      thorpej  1172:        } else {
                   1173:                s = splclock();
1.91      cube     1174:                timer_gettime(p->p_timers->pts_timers[which], itvp);
1.63      thorpej  1175:                splx(s);
                   1176:        }
                   1177:
1.91      cube     1178:        return 0;
1.1       cgd      1179: }
                   1180:
1.63      thorpej  1181: /* BSD routine to set/arm an interval timer. */
1.1       cgd      1182: /* ARGSUSED */
1.3       andrew   1183: int
1.63      thorpej  1184: sys_setitimer(struct lwp *l, void *v, register_t *retval)
1.15      thorpej  1185: {
1.45      augustss 1186:        struct sys_setitimer_args /* {
1.30      mycroft  1187:                syscallarg(int) which;
1.24      cgd      1188:                syscallarg(const struct itimerval *) itv;
1.11      cgd      1189:                syscallarg(struct itimerval *) oitv;
1.15      thorpej  1190:        } */ *uap = v;
1.63      thorpej  1191:        struct proc *p = l->l_proc;
1.30      mycroft  1192:        int which = SCARG(uap, which);
1.21      cgd      1193:        struct sys_getitimer_args getargs;
1.91      cube     1194:        const struct itimerval *itvp;
1.1       cgd      1195:        struct itimerval aitv;
1.91      cube     1196:        int error;
1.1       cgd      1197:
1.30      mycroft  1198:        if ((u_int)which > ITIMER_PROF)
1.1       cgd      1199:                return (EINVAL);
1.11      cgd      1200:        itvp = SCARG(uap, itv);
1.63      thorpej  1201:        if (itvp &&
1.56      manu     1202:            (error = copyin(itvp, &aitv, sizeof(struct itimerval)) != 0))
1.1       cgd      1203:                return (error);
1.21      cgd      1204:        if (SCARG(uap, oitv) != NULL) {
1.30      mycroft  1205:                SCARG(&getargs, which) = which;
1.21      cgd      1206:                SCARG(&getargs, itv) = SCARG(uap, oitv);
1.63      thorpej  1207:                if ((error = sys_getitimer(l, &getargs, retval)) != 0)
1.21      cgd      1208:                        return (error);
                   1209:        }
1.1       cgd      1210:        if (itvp == 0)
                   1211:                return (0);
1.91      cube     1212:
                   1213:        return dosetitimer(p, which, &aitv);
                   1214: }
                   1215:
                   1216: int
                   1217: dosetitimer(struct proc *p, int which, struct itimerval *itvp)
                   1218: {
1.101     kardel   1219: #ifdef __HAVE_TIMECOUNTER
                   1220:        struct timeval now;
                   1221: #endif
1.91      cube     1222:        struct ptimer *pt;
                   1223:        int s;
                   1224:
                   1225:        if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
1.1       cgd      1226:                return (EINVAL);
1.63      thorpej  1227:
                   1228:        /*
                   1229:         * Don't bother allocating data structures if the process just
                   1230:         * wants to clear the timer.
                   1231:         */
1.91      cube     1232:        if (!timerisset(&itvp->it_value) &&
1.63      thorpej  1233:            ((p->p_timers == NULL) ||(p->p_timers->pts_timers[which] == NULL)))
                   1234:                return (0);
                   1235:
                   1236:        if (p->p_timers == NULL)
                   1237:                timers_alloc(p);
                   1238:        if (p->p_timers->pts_timers[which] == NULL) {
                   1239:                pt = pool_get(&ptimer_pool, PR_WAITOK);
                   1240:                pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
1.76      christos 1241:                pt->pt_ev.sigev_value.sival_int = which;
1.63      thorpej  1242:                pt->pt_overruns = 0;
                   1243:                pt->pt_proc = p;
                   1244:                pt->pt_type = which;
1.64      nathanw  1245:                pt->pt_entry = which;
1.63      thorpej  1246:                switch (which) {
                   1247:                case ITIMER_REAL:
                   1248:                        callout_init(&pt->pt_ch);
                   1249:                        pt->pt_ev.sigev_signo = SIGALRM;
                   1250:                        break;
                   1251:                case ITIMER_VIRTUAL:
                   1252:                        pt->pt_active = 0;
                   1253:                        pt->pt_ev.sigev_signo = SIGVTALRM;
                   1254:                        break;
                   1255:                case ITIMER_PROF:
                   1256:                        pt->pt_active = 0;
                   1257:                        pt->pt_ev.sigev_signo = SIGPROF;
                   1258:                        break;
1.1       cgd      1259:                }
                   1260:        } else
1.63      thorpej  1261:                pt = p->p_timers->pts_timers[which];
                   1262:
1.91      cube     1263:        pt->pt_time = *itvp;
1.63      thorpej  1264:        p->p_timers->pts_timers[which] = pt;
                   1265:
                   1266:        s = splclock();
1.67      nathanw  1267:        if ((which == ITIMER_REAL) && timerisset(&pt->pt_time.it_value)) {
                   1268:                /* Convert to absolute time */
1.101     kardel   1269: #ifdef __HAVE_TIMECOUNTER
                   1270:                /* XXX need to wrap in splclock for timecounters case? */
                   1271:                getmicrotime(&now);
                   1272:                timeradd(&pt->pt_time.it_value, &now, &pt->pt_time.it_value);
                   1273: #else /* !__HAVE_TIMECOUNTER */
1.67      nathanw  1274:                timeradd(&pt->pt_time.it_value, &time, &pt->pt_time.it_value);
1.101     kardel   1275: #endif /* !__HAVE_TIMECOUNTER */
1.67      nathanw  1276:        }
1.63      thorpej  1277:        timer_settime(pt);
1.1       cgd      1278:        splx(s);
1.63      thorpej  1279:
1.1       cgd      1280:        return (0);
                   1281: }
                   1282:
1.63      thorpej  1283: /* Utility routines to manage the array of pointers to timers. */
                   1284: void
                   1285: timers_alloc(struct proc *p)
                   1286: {
                   1287:        int i;
                   1288:        struct ptimers *pts;
                   1289:
1.100     yamt     1290:        pts = pool_get(&ptimers_pool, PR_WAITOK);
1.63      thorpej  1291:        LIST_INIT(&pts->pts_virtual);
                   1292:        LIST_INIT(&pts->pts_prof);
                   1293:        for (i = 0; i < TIMER_MAX; i++)
                   1294:                pts->pts_timers[i] = NULL;
1.64      nathanw  1295:        pts->pts_fired = 0;
1.63      thorpej  1296:        p->p_timers = pts;
                   1297: }
                   1298:
1.1       cgd      1299: /*
1.63      thorpej  1300:  * Clean up the per-process timers. If "which" is set to TIMERS_ALL,
                   1301:  * then clean up all timers and free all the data structures. If
                   1302:  * "which" is set to TIMERS_POSIX, only clean up the timers allocated
                   1303:  * by timer_create(), not the BSD setitimer() timers, and only free the
                   1304:  * structure if none of those remain.
1.1       cgd      1305:  */
1.3       andrew   1306: void
1.63      thorpej  1307: timers_free(struct proc *p, int which)
1.6       cgd      1308: {
1.63      thorpej  1309:        int i, s;
                   1310:        struct ptimers *pts;
                   1311:        struct ptimer *pt, *ptn;
                   1312:        struct timeval tv;
                   1313:
                   1314:        if (p->p_timers) {
                   1315:                pts = p->p_timers;
                   1316:                if (which == TIMERS_ALL)
                   1317:                        i = 0;
                   1318:                else {
                   1319:                        s = splclock();
                   1320:                        timerclear(&tv);
                   1321:                        for (ptn = LIST_FIRST(&p->p_timers->pts_virtual);
                   1322:                             ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL];
                   1323:                             ptn = LIST_NEXT(ptn, pt_list))
                   1324:                                timeradd(&tv, &ptn->pt_time.it_value, &tv);
                   1325:                        LIST_FIRST(&p->p_timers->pts_virtual) = NULL;
                   1326:                        if (ptn) {
                   1327:                                timeradd(&tv, &ptn->pt_time.it_value,
                   1328:                                    &ptn->pt_time.it_value);
                   1329:                                LIST_INSERT_HEAD(&p->p_timers->pts_virtual,
                   1330:                                    ptn, pt_list);
                   1331:                        }
                   1332:
                   1333:                        timerclear(&tv);
                   1334:                        for (ptn = LIST_FIRST(&p->p_timers->pts_prof);
                   1335:                             ptn && ptn != pts->pts_timers[ITIMER_PROF];
                   1336:                             ptn = LIST_NEXT(ptn, pt_list))
                   1337:                                timeradd(&tv, &ptn->pt_time.it_value, &tv);
                   1338:                        LIST_FIRST(&p->p_timers->pts_prof) = NULL;
                   1339:                        if (ptn) {
                   1340:                                timeradd(&tv, &ptn->pt_time.it_value,
                   1341:                                    &ptn->pt_time.it_value);
                   1342:                                LIST_INSERT_HEAD(&p->p_timers->pts_prof, ptn,
                   1343:                                    pt_list);
                   1344:                        }
1.1       cgd      1345:                        splx(s);
1.63      thorpej  1346:                        i = 3;
                   1347:                }
                   1348:                for ( ; i < TIMER_MAX; i++)
                   1349:                        if ((pt = pts->pts_timers[i]) != NULL) {
                   1350:                                if (pt->pt_type == CLOCK_REALTIME)
                   1351:                                        callout_stop(&pt->pt_ch);
                   1352:                                pts->pts_timers[i] = NULL;
                   1353:                                pool_put(&ptimer_pool, pt);
                   1354:                        }
                   1355:                if ((pts->pts_timers[0] == NULL) &&
                   1356:                    (pts->pts_timers[1] == NULL) &&
                   1357:                    (pts->pts_timers[2] == NULL)) {
                   1358:                        p->p_timers = NULL;
1.97      simonb   1359:                        pool_put(&ptimers_pool, pts);
1.1       cgd      1360:                }
                   1361:        }
                   1362: }
                   1363:
                   1364: /*
                   1365:  * Check that a proposed value to load into the .it_value or
                   1366:  * .it_interval part of an interval timer is acceptable, and
                   1367:  * fix it to have at least minimal value (i.e. if it is less
                   1368:  * than the resolution of the clock, round it up.)
                   1369:  */
1.3       andrew   1370: int
1.63      thorpej  1371: itimerfix(struct timeval *tv)
1.1       cgd      1372: {
                   1373:
1.59      christos 1374:        if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
1.1       cgd      1375:                return (EINVAL);
                   1376:        if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
                   1377:                tv->tv_usec = tick;
                   1378:        return (0);
                   1379: }
                   1380:
1.101     kardel   1381: #ifdef __HAVE_TIMECOUNTER
                   1382: int
                   1383: itimespecfix(struct timespec *ts)
                   1384: {
                   1385:
                   1386:        if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000)
                   1387:                return (EINVAL);
                   1388:        if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000)
                   1389:                ts->tv_nsec = tick * 1000;
                   1390:        return (0);
                   1391: }
                   1392: #endif /* __HAVE_TIMECOUNTER */
                   1393:
1.1       cgd      1394: /*
                   1395:  * Decrement an interval timer by a specified number
                   1396:  * of microseconds, which must be less than a second,
                   1397:  * i.e. < 1000000.  If the timer expires, then reload
                   1398:  * it.  In this case, carry over (usec - old value) to
1.8       cgd      1399:  * reduce the value reloaded into the timer so that
1.1       cgd      1400:  * the timer does not drift.  This routine assumes
                   1401:  * that it is called in a context where the timers
                   1402:  * on which it is operating cannot change in value.
                   1403:  */
1.3       andrew   1404: int
1.63      thorpej  1405: itimerdecr(struct ptimer *pt, int usec)
                   1406: {
1.45      augustss 1407:        struct itimerval *itp;
1.1       cgd      1408:
1.63      thorpej  1409:        itp = &pt->pt_time;
1.1       cgd      1410:        if (itp->it_value.tv_usec < usec) {
                   1411:                if (itp->it_value.tv_sec == 0) {
                   1412:                        /* expired, and already in next interval */
                   1413:                        usec -= itp->it_value.tv_usec;
                   1414:                        goto expire;
                   1415:                }
                   1416:                itp->it_value.tv_usec += 1000000;
                   1417:                itp->it_value.tv_sec--;
                   1418:        }
                   1419:        itp->it_value.tv_usec -= usec;
                   1420:        usec = 0;
                   1421:        if (timerisset(&itp->it_value))
                   1422:                return (1);
                   1423:        /* expired, exactly at end of interval */
                   1424: expire:
                   1425:        if (timerisset(&itp->it_interval)) {
                   1426:                itp->it_value = itp->it_interval;
                   1427:                itp->it_value.tv_usec -= usec;
                   1428:                if (itp->it_value.tv_usec < 0) {
                   1429:                        itp->it_value.tv_usec += 1000000;
                   1430:                        itp->it_value.tv_sec--;
                   1431:                }
1.63      thorpej  1432:                timer_settime(pt);
1.1       cgd      1433:        } else
                   1434:                itp->it_value.tv_usec = 0;              /* sec is already 0 */
                   1435:        return (0);
1.42      cgd      1436: }
                   1437:
1.63      thorpej  1438: void
                   1439: itimerfire(struct ptimer *pt)
                   1440: {
                   1441:        struct proc *p = pt->pt_proc;
1.82      cl       1442:        struct sadata_vp *vp;
1.64      nathanw  1443:        int s;
1.82      cl       1444:        unsigned int i;
1.78      cl       1445:
1.63      thorpej  1446:        if (pt->pt_ev.sigev_notify == SIGEV_SIGNAL) {
                   1447:                /*
                   1448:                 * No RT signal infrastructure exists at this time;
                   1449:                 * just post the signal number and throw away the
                   1450:                 * value.
                   1451:                 */
                   1452:                if (sigismember(&p->p_sigctx.ps_siglist, pt->pt_ev.sigev_signo))
                   1453:                        pt->pt_overruns++;
                   1454:                else {
1.75      christos 1455:                        ksiginfo_t ksi;
                   1456:                        (void)memset(&ksi, 0, sizeof(ksi));
                   1457:                        ksi.ksi_signo = pt->pt_ev.sigev_signo;
                   1458:                        ksi.ksi_code = SI_TIMER;
                   1459:                        ksi.ksi_sigval = pt->pt_ev.sigev_value;
1.63      thorpej  1460:                        pt->pt_poverruns = pt->pt_overruns;
                   1461:                        pt->pt_overruns = 0;
1.75      christos 1462:                        kpsignal(p, &ksi, NULL);
1.63      thorpej  1463:                }
                   1464:        } else if (pt->pt_ev.sigev_notify == SIGEV_SA && (p->p_flag & P_SA)) {
                   1465:                /* Cause the process to generate an upcall when it returns. */
                   1466:
                   1467:                if (p->p_userret == NULL) {
1.70      nathanw  1468:                        /*
                   1469:                         * XXX stop signals can be processed inside tsleep,
                   1470:                         * which can be inside sa_yield's inner loop, which
                   1471:                         * makes testing for sa_idle alone insuffucent to
                   1472:                         * determine if we really should call setrunnable.
                   1473:                         */
1.63      thorpej  1474:                        pt->pt_poverruns = pt->pt_overruns;
                   1475:                        pt->pt_overruns = 0;
1.64      nathanw  1476:                        i = 1 << pt->pt_entry;
                   1477:                        p->p_timers->pts_fired = i;
1.63      thorpej  1478:                        p->p_userret = timerupcall;
1.64      nathanw  1479:                        p->p_userret_arg = p->p_timers;
1.87      perry    1480:
1.78      cl       1481:                        SCHED_LOCK(s);
1.82      cl       1482:                        SLIST_FOREACH(vp, &p->p_sa->sa_vps, savp_next) {
                   1483:                                if (vp->savp_lwp->l_flag & L_SA_IDLE) {
                   1484:                                        vp->savp_lwp->l_flag &= ~L_SA_IDLE;
                   1485:                                        sched_wakeup(vp->savp_lwp);
                   1486:                                        break;
                   1487:                                }
1.78      cl       1488:                        }
                   1489:                        SCHED_UNLOCK(s);
1.64      nathanw  1490:                } else if (p->p_userret == timerupcall) {
                   1491:                        i = 1 << pt->pt_entry;
                   1492:                        if ((p->p_timers->pts_fired & i) == 0) {
                   1493:                                pt->pt_poverruns = pt->pt_overruns;
                   1494:                                pt->pt_overruns = 0;
1.66      jdolecek 1495:                                p->p_timers->pts_fired |= i;
1.64      nathanw  1496:                        } else
                   1497:                                pt->pt_overruns++;
                   1498:                } else {
1.63      thorpej  1499:                        pt->pt_overruns++;
1.78      cl       1500:                        if ((p->p_flag & P_WEXIT) == 0)
                   1501:                                printf("itimerfire(%d): overrun %d on timer %x (userret is %p)\n",
                   1502:                                    p->p_pid, pt->pt_overruns,
                   1503:                                    pt->pt_ev.sigev_value.sival_int,
                   1504:                                    p->p_userret);
1.64      nathanw  1505:                }
1.63      thorpej  1506:        }
                   1507:
                   1508: }
                   1509:
1.42      cgd      1510: /*
                   1511:  * ratecheck(): simple time-based rate-limit checking.  see ratecheck(9)
                   1512:  * for usage and rationale.
                   1513:  */
                   1514: int
1.63      thorpej  1515: ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
1.42      cgd      1516: {
1.49      itojun   1517:        struct timeval tv, delta;
1.101     kardel   1518:        int rv = 0;
                   1519: #ifndef __HAVE_TIMECOUNTER
                   1520:        int s;
                   1521: #endif
1.42      cgd      1522:
1.101     kardel   1523: #ifdef __HAVE_TIMECOUNTER
                   1524:        getmicrouptime(&tv);
                   1525: #else /* !__HAVE_TIMECOUNTER */
1.63      thorpej  1526:        s = splclock();
1.49      itojun   1527:        tv = mono_time;
                   1528:        splx(s);
1.101     kardel   1529: #endif /* !__HAVE_TIMECOUNTER */
1.49      itojun   1530:        timersub(&tv, lasttime, &delta);
1.42      cgd      1531:
                   1532:        /*
                   1533:         * check for 0,0 is so that the message will be seen at least once,
                   1534:         * even if interval is huge.
                   1535:         */
                   1536:        if (timercmp(&delta, mininterval, >=) ||
                   1537:            (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
1.49      itojun   1538:                *lasttime = tv;
1.42      cgd      1539:                rv = 1;
                   1540:        }
1.50      itojun   1541:
                   1542:        return (rv);
                   1543: }
                   1544:
                   1545: /*
                   1546:  * ppsratecheck(): packets (or events) per second limitation.
                   1547:  */
                   1548: int
1.63      thorpej  1549: ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
1.50      itojun   1550: {
                   1551:        struct timeval tv, delta;
1.101     kardel   1552:        int rv;
                   1553: #ifndef __HAVE_TIMECOUNTER
                   1554:        int s;
                   1555: #endif
1.50      itojun   1556:
1.101     kardel   1557: #ifdef __HAVE_TIMECOUNTER
                   1558:        getmicrouptime(&tv);
                   1559: #else /* !__HAVE_TIMECOUNTER */
1.63      thorpej  1560:        s = splclock();
1.50      itojun   1561:        tv = mono_time;
                   1562:        splx(s);
1.101     kardel   1563: #endif /* !__HAVE_TIMECOUNTER */
1.50      itojun   1564:        timersub(&tv, lasttime, &delta);
                   1565:
                   1566:        /*
                   1567:         * check for 0,0 is so that the message will be seen at least once.
                   1568:         * if more than one second have passed since the last update of
                   1569:         * lasttime, reset the counter.
                   1570:         *
                   1571:         * we do increment *curpps even in *curpps < maxpps case, as some may
                   1572:         * try to use *curpps for stat purposes as well.
                   1573:         */
                   1574:        if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||
                   1575:            delta.tv_sec >= 1) {
                   1576:                *lasttime = tv;
                   1577:                *curpps = 0;
1.69      dyoung   1578:        }
                   1579:        if (maxpps < 0)
1.53      itojun   1580:                rv = 1;
                   1581:        else if (*curpps < maxpps)
1.50      itojun   1582:                rv = 1;
                   1583:        else
                   1584:                rv = 0;
                   1585:
1.51      jhawk    1586: #if 1 /*DIAGNOSTIC?*/
1.50      itojun   1587:        /* be careful about wrap-around */
                   1588:        if (*curpps + 1 > *curpps)
                   1589:                *curpps = *curpps + 1;
                   1590: #else
                   1591:        /*
                   1592:         * assume that there's not too many calls to this function.
                   1593:         * not sure if the assumption holds, as it depends on *caller's*
                   1594:         * behavior, not the behavior of this function.
                   1595:         * IMHO it is wrong to make assumption on the caller's behavior,
1.51      jhawk    1596:         * so the above #if is #if 1, not #ifdef DIAGNOSTIC.
1.50      itojun   1597:         */
                   1598:        *curpps = *curpps + 1;
                   1599: #endif
1.42      cgd      1600:
                   1601:        return (rv);
1.1       cgd      1602: }

CVSweb <webmaster@jp.NetBSD.org>