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

1.201   ! kamil       1: /*     $NetBSD: kern_time.c,v 1.200 2019/09/20 14:12:57 kamil Exp $    */
1.42      cgd         2:
                      3: /*-
1.158     ad          4:  * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009 The NetBSD Foundation, Inc.
1.42      cgd         5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.158     ad          8:  * by Christopher G. Demetriou, and by Andrew Doran.
1.42      cgd         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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.9       cgd        31:
1.1       cgd        32: /*
1.8       cgd        33:  * Copyright (c) 1982, 1986, 1989, 1993
                     34:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd        35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
1.72      agc        44:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        45:  *    may be used to endorse or promote products derived from this software
                     46:  *    without specific prior written permission.
                     47:  *
                     48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     58:  * SUCH DAMAGE.
                     59:  *
1.33      fvdl       60:  *     @(#)kern_time.c 8.4 (Berkeley) 5/26/95
1.1       cgd        61:  */
1.58      lukem      62:
                     63: #include <sys/cdefs.h>
1.201   ! kamil      64: __KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.200 2019/09/20 14:12:57 kamil Exp $");
1.1       cgd        65:
1.5       mycroft    66: #include <sys/param.h>
                     67: #include <sys/resourcevar.h>
                     68: #include <sys/kernel.h>
1.8       cgd        69: #include <sys/systm.h>
1.5       mycroft    70: #include <sys/proc.h>
1.8       cgd        71: #include <sys/vnode.h>
1.17      christos   72: #include <sys/signalvar.h>
1.25      perry      73: #include <sys/syslog.h>
1.101     kardel     74: #include <sys/timetc.h>
1.143     ad         75: #include <sys/timex.h>
1.99      elad       76: #include <sys/kauth.h>
1.11      cgd        77: #include <sys/mount.h>
                     78: #include <sys/syscallargs.h>
1.143     ad         79: #include <sys/cpu.h>
1.19      christos   80:
1.142     ad         81: static void    timer_intr(void *);
                     82: static void    itimerfire(struct ptimer *);
                     83: static void    itimerfree(struct ptimers *, int);
                     84:
                     85: kmutex_t       timer_lock;
                     86:
                     87: static void    *timer_sih;
                     88: static TAILQ_HEAD(, ptimer) timer_queue;
1.131     ad         89:
1.161     pooka      90: struct pool ptimer_pool, ptimers_pool;
1.97      simonb     91:
1.168     yamt       92: #define        CLOCK_VIRTUAL_P(clockid)        \
                     93:        ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF)
                     94:
                     95: CTASSERT(ITIMER_REAL == CLOCK_REALTIME);
                     96: CTASSERT(ITIMER_VIRTUAL == CLOCK_VIRTUAL);
                     97: CTASSERT(ITIMER_PROF == CLOCK_PROF);
1.170     christos   98: CTASSERT(ITIMER_MONOTONIC == CLOCK_MONOTONIC);
1.168     yamt       99:
1.187     christos  100: #define        DELAYTIMER_MAX  32
1.186     christos  101:
1.131     ad        102: /*
                    103:  * Initialize timekeeping.
                    104:  */
                    105: void
                    106: time_init(void)
                    107: {
                    108:
1.161     pooka     109:        pool_init(&ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
                    110:            &pool_allocator_nointr, IPL_NONE);
                    111:        pool_init(&ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl",
                    112:            &pool_allocator_nointr, IPL_NONE);
1.131     ad        113: }
                    114:
1.142     ad        115: void
                    116: time_init2(void)
                    117: {
                    118:
                    119:        TAILQ_INIT(&timer_queue);
                    120:        mutex_init(&timer_lock, MUTEX_DEFAULT, IPL_SCHED);
                    121:        timer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
                    122:            timer_intr, NULL);
                    123: }
                    124:
1.63      thorpej   125: /* Time of day and interval timer support.
1.1       cgd       126:  *
                    127:  * These routines provide the kernel entry points to get and set
                    128:  * the time-of-day and per-process interval timers.  Subroutines
                    129:  * here provide support for adding and subtracting timeval structures
                    130:  * and decrementing interval timers, optionally reloading the interval
                    131:  * timers when they expire.
                    132:  */
                    133:
1.22      jtc       134: /* This function is used by clock_settime and settimeofday */
1.132     elad      135: static int
1.156     christos  136: settime1(struct proc *p, const struct timespec *ts, bool check_kauth)
1.22      jtc       137: {
1.156     christos  138:        struct timespec delta, now;
1.129     ad        139:        int s;
1.22      jtc       140:
                    141:        /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
1.129     ad        142:        s = splclock();
1.156     christos  143:        nanotime(&now);
                    144:        timespecsub(ts, &now, &delta);
1.132     elad      145:
1.134     elad      146:        if (check_kauth && kauth_authorize_system(kauth_cred_get(),
1.156     christos  147:            KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts),
                    148:            &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) {
1.129     ad        149:                splx(s);
1.29      tls       150:                return (EPERM);
1.55      tron      151:        }
1.132     elad      152:
1.29      tls       153: #ifdef notyet
1.109     elad      154:        if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */
1.129     ad        155:                splx(s);
1.29      tls       156:                return (EPERM);
1.55      tron      157:        }
1.29      tls       158: #endif
1.103     kardel    159:
1.156     christos  160:        tc_setclock(ts);
1.103     kardel    161:
1.156     christos  162:        timespecadd(&boottime, &delta, &boottime);
1.103     kardel    163:
1.22      jtc       164:        resettodr();
1.129     ad        165:        splx(s);
                    166:
1.29      tls       167:        return (0);
1.22      jtc       168: }
                    169:
1.132     elad      170: int
                    171: settime(struct proc *p, struct timespec *ts)
                    172: {
                    173:        return (settime1(p, ts, true));
                    174: }
                    175:
1.22      jtc       176: /* ARGSUSED */
                    177: int
1.156     christos  178: sys___clock_gettime50(struct lwp *l,
                    179:     const struct sys___clock_gettime50_args *uap, register_t *retval)
1.22      jtc       180: {
1.135     dsl       181:        /* {
1.22      jtc       182:                syscallarg(clockid_t) clock_id;
1.23      cgd       183:                syscallarg(struct timespec *) tp;
1.135     dsl       184:        } */
1.165     njoly     185:        int error;
1.22      jtc       186:        struct timespec ats;
                    187:
1.165     njoly     188:        error = clock_gettime1(SCARG(uap, clock_id), &ats);
                    189:        if (error != 0)
                    190:                return error;
                    191:
                    192:        return copyout(&ats, SCARG(uap, tp), sizeof(ats));
                    193: }
                    194:
1.22      jtc       195: /* ARGSUSED */
                    196: int
1.156     christos  197: sys___clock_settime50(struct lwp *l,
                    198:     const struct sys___clock_settime50_args *uap, register_t *retval)
1.22      jtc       199: {
1.135     dsl       200:        /* {
1.22      jtc       201:                syscallarg(clockid_t) clock_id;
1.23      cgd       202:                syscallarg(const struct timespec *) tp;
1.135     dsl       203:        } */
1.156     christos  204:        int error;
                    205:        struct timespec ats;
1.22      jtc       206:
1.156     christos  207:        if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
                    208:                return error;
                    209:
                    210:        return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, true);
1.56      manu      211: }
                    212:
                    213:
                    214: int
1.132     elad      215: clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp,
                    216:     bool check_kauth)
1.56      manu      217: {
                    218:        int error;
                    219:
1.201   ! kamil     220:        if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000L)
        !           221:                return EINVAL;
        !           222:
1.61      simonb    223:        switch (clock_id) {
                    224:        case CLOCK_REALTIME:
1.156     christos  225:                if ((error = settime1(p, tp, check_kauth)) != 0)
1.61      simonb    226:                        return (error);
                    227:                break;
                    228:        case CLOCK_MONOTONIC:
                    229:                return (EINVAL);        /* read-only clock */
                    230:        default:
1.56      manu      231:                return (EINVAL);
1.61      simonb    232:        }
1.22      jtc       233:
                    234:        return 0;
                    235: }
                    236:
                    237: int
1.156     christos  238: sys___clock_getres50(struct lwp *l, const struct sys___clock_getres50_args *uap,
1.140     yamt      239:     register_t *retval)
1.22      jtc       240: {
1.135     dsl       241:        /* {
1.22      jtc       242:                syscallarg(clockid_t) clock_id;
1.23      cgd       243:                syscallarg(struct timespec *) tp;
1.135     dsl       244:        } */
1.22      jtc       245:        struct timespec ts;
1.180     maxv      246:        int error;
1.22      jtc       247:
1.164     njoly     248:        if ((error = clock_getres1(SCARG(uap, clock_id), &ts)) != 0)
                    249:                return error;
                    250:
                    251:        if (SCARG(uap, tp))
                    252:                error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
                    253:
                    254:        return error;
                    255: }
                    256:
                    257: int
                    258: clock_getres1(clockid_t clock_id, struct timespec *ts)
                    259: {
                    260:
1.61      simonb    261:        switch (clock_id) {
                    262:        case CLOCK_REALTIME:
                    263:        case CLOCK_MONOTONIC:
1.164     njoly     264:                ts->tv_sec = 0;
1.102     kardel    265:                if (tc_getfrequency() > 1000000000)
1.164     njoly     266:                        ts->tv_nsec = 1;
1.102     kardel    267:                else
1.164     njoly     268:                        ts->tv_nsec = 1000000000 / tc_getfrequency();
1.61      simonb    269:                break;
                    270:        default:
1.164     njoly     271:                return EINVAL;
1.61      simonb    272:        }
1.22      jtc       273:
1.164     njoly     274:        return 0;
1.22      jtc       275: }
                    276:
1.27      jtc       277: /* ARGSUSED */
                    278: int
1.156     christos  279: sys___nanosleep50(struct lwp *l, const struct sys___nanosleep50_args *uap,
1.140     yamt      280:     register_t *retval)
1.27      jtc       281: {
1.135     dsl       282:        /* {
1.101     kardel    283:                syscallarg(struct timespec *) rqtp;
                    284:                syscallarg(struct timespec *) rmtp;
1.135     dsl       285:        } */
1.101     kardel    286:        struct timespec rmt, rqt;
1.120     dsl       287:        int error, error1;
1.101     kardel    288:
                    289:        error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
                    290:        if (error)
                    291:                return (error);
                    292:
1.175     christos  293:        error = nanosleep1(l, CLOCK_MONOTONIC, 0, &rqt,
                    294:            SCARG(uap, rmtp) ? &rmt : NULL);
                    295:        if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR))
                    296:                return error;
                    297:
                    298:        error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
                    299:        return error1 ? error1 : error;
                    300: }
                    301:
                    302: /* ARGSUSED */
                    303: int
                    304: sys_clock_nanosleep(struct lwp *l, const struct sys_clock_nanosleep_args *uap,
                    305:     register_t *retval)
                    306: {
                    307:        /* {
                    308:                syscallarg(clockid_t) clock_id;
                    309:                syscallarg(int) flags;
                    310:                syscallarg(struct timespec *) rqtp;
                    311:                syscallarg(struct timespec *) rmtp;
                    312:        } */
                    313:        struct timespec rmt, rqt;
                    314:        int error, error1;
                    315:
                    316:        error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
                    317:        if (error)
1.181     christos  318:                goto out;
1.175     christos  319:
                    320:        error = nanosleep1(l, SCARG(uap, clock_id), SCARG(uap, flags), &rqt,
                    321:            SCARG(uap, rmtp) ? &rmt : NULL);
1.120     dsl       322:        if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR))
1.181     christos  323:                goto out;
1.120     dsl       324:
1.189     njoly     325:        if ((SCARG(uap, flags) & TIMER_ABSTIME) == 0 &&
                    326:            (error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt))) != 0)
1.181     christos  327:                error = error1;
                    328: out:
                    329:        *retval = error;
                    330:        return 0;
1.120     dsl       331: }
                    332:
                    333: int
1.175     christos  334: nanosleep1(struct lwp *l, clockid_t clock_id, int flags, struct timespec *rqt,
                    335:     struct timespec *rmt)
1.120     dsl       336: {
1.141     yamt      337:        struct timespec rmtstart;
1.120     dsl       338:        int error, timo;
                    339:
1.184     uwe       340:        if ((error = ts2timo(clock_id, flags, rqt, &timo, &rmtstart)) != 0) {
                    341:                if (error == ETIMEDOUT) {
                    342:                        error = 0;
                    343:                        if (rmt != NULL)
                    344:                                rmt->tv_sec = rmt->tv_nsec = 0;
                    345:                }
                    346:                return error;
                    347:        }
1.101     kardel    348:
                    349:        /*
1.175     christos  350:         * Avoid inadvertently sleeping forever
1.101     kardel    351:         */
                    352:        if (timo == 0)
                    353:                timo = 1;
1.141     yamt      354: again:
                    355:        error = kpause("nanoslp", true, timo, NULL);
1.197     kre       356:        if (error == EWOULDBLOCK)
                    357:                error = 0;
1.141     yamt      358:        if (rmt != NULL || error == 0) {
                    359:                struct timespec rmtend;
                    360:                struct timespec t0;
                    361:                struct timespec *t;
1.101     kardel    362:
1.175     christos  363:                (void)clock_gettime1(clock_id, &rmtend);
1.141     yamt      364:                t = (rmt != NULL) ? rmt : &t0;
1.179     christos  365:                if (flags & TIMER_ABSTIME) {
                    366:                        timespecsub(rqt, &rmtend, t);
                    367:                } else {
                    368:                        timespecsub(&rmtend, &rmtstart, t);
                    369:                        timespecsub(rqt, t, t);
                    370:                }
1.141     yamt      371:                if (t->tv_sec < 0)
                    372:                        timespecclear(t);
                    373:                if (error == 0) {
                    374:                        timo = tstohz(t);
                    375:                        if (timo > 0)
                    376:                                goto again;
                    377:                }
                    378:        }
1.104     kardel    379:
1.101     kardel    380:        if (error == ERESTART)
                    381:                error = EINTR;
                    382:
                    383:        return error;
1.27      jtc       384: }
1.22      jtc       385:
1.186     christos  386: int
                    387: sys_clock_getcpuclockid2(struct lwp *l,
                    388:     const struct sys_clock_getcpuclockid2_args *uap,
                    389:     register_t *retval)
                    390: {
                    391:        /* {
                    392:                syscallarg(idtype_t idtype;
                    393:                syscallarg(id_t id);
                    394:                syscallarg(clockid_t *)clock_id;
                    395:        } */
                    396:        pid_t pid;
                    397:        lwpid_t lid;
                    398:        clockid_t clock_id;
                    399:        id_t id = SCARG(uap, id);
                    400:
                    401:        switch (SCARG(uap, idtype)) {
                    402:        case P_PID:
1.188     msaitoh   403:                pid = id == 0 ? l->l_proc->p_pid : id;
1.186     christos  404:                clock_id = CLOCK_PROCESS_CPUTIME_ID | pid;
                    405:                break;
                    406:        case P_LWPID:
                    407:                lid = id == 0 ? l->l_lid : id;
                    408:                clock_id = CLOCK_THREAD_CPUTIME_ID | lid;
                    409:                break;
                    410:        default:
                    411:                return EINVAL;
                    412:        }
                    413:        return copyout(&clock_id, SCARG(uap, clock_id), sizeof(clock_id));
                    414: }
                    415:
1.1       cgd       416: /* ARGSUSED */
1.3       andrew    417: int
1.156     christos  418: sys___gettimeofday50(struct lwp *l, const struct sys___gettimeofday50_args *uap,
1.140     yamt      419:     register_t *retval)
1.15      thorpej   420: {
1.135     dsl       421:        /* {
1.11      cgd       422:                syscallarg(struct timeval *) tp;
1.135     dsl       423:                syscallarg(void *) tzp;         really "struct timezone *";
                    424:        } */
1.1       cgd       425:        struct timeval atv;
                    426:        int error = 0;
1.25      perry     427:        struct timezone tzfake;
1.1       cgd       428:
1.11      cgd       429:        if (SCARG(uap, tp)) {
1.190     maxv      430:                memset(&atv, 0, sizeof(atv));
1.1       cgd       431:                microtime(&atv);
1.35      perry     432:                error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
1.17      christos  433:                if (error)
1.1       cgd       434:                        return (error);
                    435:        }
1.25      perry     436:        if (SCARG(uap, tzp)) {
                    437:                /*
1.32      mycroft   438:                 * NetBSD has no kernel notion of time zone, so we just
1.25      perry     439:                 * fake up a timezone struct and return it if demanded.
                    440:                 */
                    441:                tzfake.tz_minuteswest = 0;
                    442:                tzfake.tz_dsttime = 0;
1.35      perry     443:                error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
1.25      perry     444:        }
1.1       cgd       445:        return (error);
                    446: }
                    447:
                    448: /* ARGSUSED */
1.3       andrew    449: int
1.156     christos  450: sys___settimeofday50(struct lwp *l, const struct sys___settimeofday50_args *uap,
1.140     yamt      451:     register_t *retval)
1.15      thorpej   452: {
1.135     dsl       453:        /* {
1.24      cgd       454:                syscallarg(const struct timeval *) tv;
1.140     yamt      455:                syscallarg(const void *) tzp; really "const struct timezone *";
1.135     dsl       456:        } */
1.60      manu      457:
1.119     dsl       458:        return settimeofday1(SCARG(uap, tv), true, SCARG(uap, tzp), l, true);
1.60      manu      459: }
                    460:
                    461: int
1.119     dsl       462: settimeofday1(const struct timeval *utv, bool userspace,
                    463:     const void *utzp, struct lwp *l, bool check_kauth)
1.60      manu      464: {
1.22      jtc       465:        struct timeval atv;
1.98      christos  466:        struct timespec ts;
1.22      jtc       467:        int error;
1.1       cgd       468:
1.8       cgd       469:        /* Verify all parameters before changing time. */
1.119     dsl       470:
1.25      perry     471:        /*
1.32      mycroft   472:         * NetBSD has no kernel notion of time zone, and only an
1.25      perry     473:         * obsolete program would try to set it, so we log a warning.
                    474:         */
1.98      christos  475:        if (utzp)
1.25      perry     476:                log(LOG_WARNING, "pid %d attempted to set the "
1.119     dsl       477:                    "(obsolete) kernel time zone\n", l->l_proc->p_pid);
1.98      christos  478:
                    479:        if (utv == NULL)
                    480:                return 0;
                    481:
1.119     dsl       482:        if (userspace) {
                    483:                if ((error = copyin(utv, &atv, sizeof(atv))) != 0)
                    484:                        return error;
                    485:                utv = &atv;
                    486:        }
                    487:
1.200     kamil     488:        if (utv->tv_usec < 0 || utv->tv_usec >= 1000000)
                    489:                return EINVAL;
                    490:
1.119     dsl       491:        TIMEVAL_TO_TIMESPEC(utv, &ts);
1.133     elad      492:        return settime1(l->l_proc, &ts, check_kauth);
1.1       cgd       493: }
                    494:
1.68      dsl       495: int    time_adjusted;                  /* set if an adjustment is made */
1.1       cgd       496:
                    497: /* ARGSUSED */
1.3       andrew    498: int
1.156     christos  499: sys___adjtime50(struct lwp *l, const struct sys___adjtime50_args *uap,
1.140     yamt      500:     register_t *retval)
1.15      thorpej   501: {
1.135     dsl       502:        /* {
1.24      cgd       503:                syscallarg(const struct timeval *) delta;
1.11      cgd       504:                syscallarg(struct timeval *) olddelta;
1.135     dsl       505:        } */
1.180     maxv      506:        int error;
1.156     christos  507:        struct timeval atv, oldatv;
1.1       cgd       508:
1.106     elad      509:        if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME,
                    510:            KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0)
1.156     christos  511:                return error;
1.17      christos  512:
1.156     christos  513:        if (SCARG(uap, delta)) {
                    514:                error = copyin(SCARG(uap, delta), &atv,
                    515:                    sizeof(*SCARG(uap, delta)));
                    516:                if (error)
                    517:                        return (error);
                    518:        }
                    519:        adjtime1(SCARG(uap, delta) ? &atv : NULL,
                    520:            SCARG(uap, olddelta) ? &oldatv : NULL, l->l_proc);
                    521:        if (SCARG(uap, olddelta))
                    522:                error = copyout(&oldatv, SCARG(uap, olddelta),
                    523:                    sizeof(*SCARG(uap, olddelta)));
                    524:        return error;
1.56      manu      525: }
                    526:
1.156     christos  527: void
1.110     yamt      528: adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p)
1.56      manu      529: {
1.101     kardel    530:        extern int64_t time_adjtime;  /* in kern_ntptime.c */
                    531:
                    532:        if (olddelta) {
1.194     maxv      533:                memset(olddelta, 0, sizeof(*olddelta));
1.143     ad        534:                mutex_spin_enter(&timecounter_lock);
1.156     christos  535:                olddelta->tv_sec = time_adjtime / 1000000;
                    536:                olddelta->tv_usec = time_adjtime % 1000000;
                    537:                if (olddelta->tv_usec < 0) {
                    538:                        olddelta->tv_usec += 1000000;
                    539:                        olddelta->tv_sec--;
1.101     kardel    540:                }
1.157     christos  541:                mutex_spin_exit(&timecounter_lock);
1.101     kardel    542:        }
                    543:
                    544:        if (delta) {
1.156     christos  545:                mutex_spin_enter(&timecounter_lock);
1.157     christos  546:                time_adjtime = delta->tv_sec * 1000000 + delta->tv_usec;
1.101     kardel    547:
1.143     ad        548:                if (time_adjtime) {
1.101     kardel    549:                        /* We need to save the system time during shutdown */
                    550:                        time_adjusted |= 1;
1.143     ad        551:                }
                    552:                mutex_spin_exit(&timecounter_lock);
1.101     kardel    553:        }
1.1       cgd       554: }
                    555:
                    556: /*
1.63      thorpej   557:  * Interval timer support. Both the BSD getitimer() family and the POSIX
                    558:  * timer_*() family of routines are supported.
1.1       cgd       559:  *
1.63      thorpej   560:  * All timers are kept in an array pointed to by p_timers, which is
                    561:  * allocated on demand - many processes don't use timers at all. The
1.183     christos  562:  * first four elements in this array are reserved for the BSD timers:
1.170     christos  563:  * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, element
                    564:  * 2 is ITIMER_PROF, and element 3 is ITIMER_MONOTONIC. The rest may be
                    565:  * allocated by the timer_create() syscall.
1.1       cgd       566:  *
1.63      thorpej   567:  * Realtime timers are kept in the ptimer structure as an absolute
                    568:  * time; virtual time timers are kept as a linked list of deltas.
1.1       cgd       569:  * Virtual time timers are processed in the hardclock() routine of
1.63      thorpej   570:  * kern_clock.c.  The real time timer is processed by a callout
                    571:  * routine, called from the softclock() routine.  Since a callout may
                    572:  * be delayed in real time due to interrupt processing in the system,
                    573:  * it is possible for the real time timeout routine (realtimeexpire,
                    574:  * given below), to be delayed in real time past when it is supposed
                    575:  * to occur.  It does not suffice, therefore, to reload the real timer
                    576:  * .it_value from the real time timers .it_interval.  Rather, we
                    577:  * compute the next time in absolute time the timer should go off.  */
                    578:
                    579: /* Allocate a POSIX realtime timer. */
                    580: int
1.140     yamt      581: sys_timer_create(struct lwp *l, const struct sys_timer_create_args *uap,
                    582:     register_t *retval)
1.63      thorpej   583: {
1.135     dsl       584:        /* {
1.63      thorpej   585:                syscallarg(clockid_t) clock_id;
                    586:                syscallarg(struct sigevent *) evp;
                    587:                syscallarg(timer_t *) timerid;
1.135     dsl       588:        } */
1.92      cube      589:
                    590:        return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id),
1.105     ad        591:            SCARG(uap, evp), copyin, l);
1.92      cube      592: }
                    593:
                    594: int
                    595: timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp,
1.105     ad        596:     copyin_t fetch_event, struct lwp *l)
1.92      cube      597: {
                    598:        int error;
                    599:        timer_t timerid;
1.142     ad        600:        struct ptimers *pts;
1.63      thorpej   601:        struct ptimer *pt;
1.105     ad        602:        struct proc *p;
                    603:
                    604:        p = l->l_proc;
1.63      thorpej   605:
1.170     christos  606:        if ((u_int)id > CLOCK_MONOTONIC)
1.63      thorpej   607:                return (EINVAL);
                    608:
1.142     ad        609:        if ((pts = p->p_timers) == NULL)
                    610:                pts = timers_alloc(p);
1.63      thorpej   611:
1.195     christos  612:        pt = pool_get(&ptimer_pool, PR_WAITOK | PR_ZERO);
1.142     ad        613:        if (evp != NULL) {
1.63      thorpej   614:                if (((error =
1.92      cube      615:                    (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) ||
1.63      thorpej   616:                    ((pt->pt_ev.sigev_notify < SIGEV_NONE) ||
1.163     drochner  617:                        (pt->pt_ev.sigev_notify > SIGEV_SA)) ||
                    618:                        (pt->pt_ev.sigev_notify == SIGEV_SIGNAL &&
                    619:                         (pt->pt_ev.sigev_signo <= 0 ||
                    620:                          pt->pt_ev.sigev_signo >= NSIG))) {
1.63      thorpej   621:                        pool_put(&ptimer_pool, pt);
                    622:                        return (error ? error : EINVAL);
                    623:                }
1.142     ad        624:        }
                    625:
                    626:        /* Find a free timer slot, skipping those reserved for setitimer(). */
                    627:        mutex_spin_enter(&timer_lock);
1.183     christos  628:        for (timerid = TIMER_MIN; timerid < TIMER_MAX; timerid++)
1.142     ad        629:                if (pts->pts_timers[timerid] == NULL)
                    630:                        break;
                    631:        if (timerid == TIMER_MAX) {
                    632:                mutex_spin_exit(&timer_lock);
                    633:                pool_put(&ptimer_pool, pt);
                    634:                return EAGAIN;
                    635:        }
                    636:        if (evp == NULL) {
1.63      thorpej   637:                pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
                    638:                switch (id) {
                    639:                case CLOCK_REALTIME:
1.168     yamt      640:                case CLOCK_MONOTONIC:
1.63      thorpej   641:                        pt->pt_ev.sigev_signo = SIGALRM;
                    642:                        break;
                    643:                case CLOCK_VIRTUAL:
                    644:                        pt->pt_ev.sigev_signo = SIGVTALRM;
                    645:                        break;
                    646:                case CLOCK_PROF:
                    647:                        pt->pt_ev.sigev_signo = SIGPROF;
                    648:                        break;
                    649:                }
                    650:                pt->pt_ev.sigev_value.sival_int = timerid;
                    651:        }
1.73      christos  652:        pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo;
                    653:        pt->pt_info.ksi_errno = 0;
                    654:        pt->pt_info.ksi_code = 0;
                    655:        pt->pt_info.ksi_pid = p->p_pid;
1.105     ad        656:        pt->pt_info.ksi_uid = kauth_cred_getuid(l->l_cred);
1.124     christos  657:        pt->pt_info.ksi_value = pt->pt_ev.sigev_value;
1.63      thorpej   658:        pt->pt_type = id;
                    659:        pt->pt_proc = p;
                    660:        pt->pt_overruns = 0;
                    661:        pt->pt_poverruns = 0;
1.64      nathanw   662:        pt->pt_entry = timerid;
1.142     ad        663:        pt->pt_queued = false;
1.150     christos  664:        timespecclear(&pt->pt_time.it_value);
1.168     yamt      665:        if (!CLOCK_VIRTUAL_P(id))
                    666:                callout_init(&pt->pt_ch, CALLOUT_MPSAFE);
1.149     christos  667:        else
                    668:                pt->pt_active = 0;
                    669:
1.142     ad        670:        pts->pts_timers[timerid] = pt;
                    671:        mutex_spin_exit(&timer_lock);
1.63      thorpej   672:
1.92      cube      673:        return copyout(&timerid, tid, sizeof(timerid));
1.63      thorpej   674: }
                    675:
                    676: /* Delete a POSIX realtime timer */
1.3       andrew    677: int
1.140     yamt      678: sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap,
                    679:     register_t *retval)
1.15      thorpej   680: {
1.135     dsl       681:        /* {
1.63      thorpej   682:                syscallarg(timer_t) timerid;
1.135     dsl       683:        } */
1.63      thorpej   684:        struct proc *p = l->l_proc;
1.65      jdolecek  685:        timer_t timerid;
1.142     ad        686:        struct ptimers *pts;
1.63      thorpej   687:        struct ptimer *pt, *ptn;
1.1       cgd       688:
1.63      thorpej   689:        timerid = SCARG(uap, timerid);
1.142     ad        690:        pts = p->p_timers;
                    691:
                    692:        if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
                    693:                return (EINVAL);
1.63      thorpej   694:
1.142     ad        695:        mutex_spin_enter(&timer_lock);
                    696:        if ((pt = pts->pts_timers[timerid]) == NULL) {
                    697:                mutex_spin_exit(&timer_lock);
1.1       cgd       698:                return (EINVAL);
1.142     ad        699:        }
1.168     yamt      700:        if (CLOCK_VIRTUAL_P(pt->pt_type)) {
1.149     christos  701:                if (pt->pt_active) {
                    702:                        ptn = LIST_NEXT(pt, pt_list);
                    703:                        LIST_REMOVE(pt, pt_list);
                    704:                        for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
1.150     christos  705:                                timespecadd(&pt->pt_time.it_value,
1.149     christos  706:                                    &ptn->pt_time.it_value,
                    707:                                    &ptn->pt_time.it_value);
                    708:                        pt->pt_active = 0;
                    709:                }
1.63      thorpej   710:        }
1.198     riastrad  711:
                    712:        /* Free the timer and release the lock.  */
1.142     ad        713:        itimerfree(pts, timerid);
1.63      thorpej   714:
                    715:        return (0);
                    716: }
                    717:
                    718: /*
1.67      nathanw   719:  * Set up the given timer. The value in pt->pt_time.it_value is taken
1.168     yamt      720:  * to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC timers and
                    721:  * a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers.
1.198     riastrad  722:  *
                    723:  * If the callout had already fired but not yet run, fails with
                    724:  * ERESTART -- caller must restart from the top to look up a timer.
1.63      thorpej   725:  */
1.198     riastrad  726: int
1.63      thorpej   727: timer_settime(struct ptimer *pt)
                    728: {
                    729:        struct ptimer *ptn, *pptn;
                    730:        struct ptlist *ptl;
                    731:
1.142     ad        732:        KASSERT(mutex_owned(&timer_lock));
                    733:
1.168     yamt      734:        if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
1.198     riastrad  735:                /*
                    736:                 * Try to stop the callout.  However, if it had already
                    737:                 * fired, we have to drop the lock to wait for it, so
                    738:                 * the world may have changed and pt may not be there
                    739:                 * any more.  In that case, tell the caller to start
                    740:                 * over from the top.
                    741:                 */
                    742:                if (callout_halt(&pt->pt_ch, &timer_lock))
                    743:                        return ERESTART;
                    744:
                    745:                /* Now we can touch pt and start it up again.  */
1.150     christos  746:                if (timespecisset(&pt->pt_time.it_value)) {
1.63      thorpej   747:                        /*
1.150     christos  748:                         * Don't need to check tshzto() return value, here.
1.63      thorpej   749:                         * callout_reset() does it for us.
                    750:                         */
1.171     christos  751:                        callout_reset(&pt->pt_ch,
                    752:                            pt->pt_type == CLOCK_MONOTONIC ?
                    753:                            tshztoup(&pt->pt_time.it_value) :
                    754:                            tshzto(&pt->pt_time.it_value),
1.63      thorpej   755:                            realtimerexpire, pt);
                    756:                }
                    757:        } else {
                    758:                if (pt->pt_active) {
                    759:                        ptn = LIST_NEXT(pt, pt_list);
                    760:                        LIST_REMOVE(pt, pt_list);
                    761:                        for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
1.150     christos  762:                                timespecadd(&pt->pt_time.it_value,
1.63      thorpej   763:                                    &ptn->pt_time.it_value,
                    764:                                    &ptn->pt_time.it_value);
                    765:                }
1.150     christos  766:                if (timespecisset(&pt->pt_time.it_value)) {
1.63      thorpej   767:                        if (pt->pt_type == CLOCK_VIRTUAL)
                    768:                                ptl = &pt->pt_proc->p_timers->pts_virtual;
                    769:                        else
                    770:                                ptl = &pt->pt_proc->p_timers->pts_prof;
                    771:
                    772:                        for (ptn = LIST_FIRST(ptl), pptn = NULL;
1.150     christos  773:                             ptn && timespeccmp(&pt->pt_time.it_value,
1.63      thorpej   774:                                 &ptn->pt_time.it_value, >);
                    775:                             pptn = ptn, ptn = LIST_NEXT(ptn, pt_list))
1.150     christos  776:                                timespecsub(&pt->pt_time.it_value,
1.63      thorpej   777:                                    &ptn->pt_time.it_value,
                    778:                                    &pt->pt_time.it_value);
                    779:
                    780:                        if (pptn)
                    781:                                LIST_INSERT_AFTER(pptn, pt, pt_list);
                    782:                        else
                    783:                                LIST_INSERT_HEAD(ptl, pt, pt_list);
                    784:
                    785:                        for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list))
1.150     christos  786:                                timespecsub(&ptn->pt_time.it_value,
1.63      thorpej   787:                                    &pt->pt_time.it_value,
                    788:                                    &ptn->pt_time.it_value);
                    789:
                    790:                        pt->pt_active = 1;
                    791:                } else
                    792:                        pt->pt_active = 0;
                    793:        }
1.198     riastrad  794:
                    795:        /* Success!  */
                    796:        return 0;
1.63      thorpej   797: }
                    798:
                    799: void
1.150     christos  800: timer_gettime(struct ptimer *pt, struct itimerspec *aits)
1.63      thorpej   801: {
1.150     christos  802:        struct timespec now;
1.63      thorpej   803:        struct ptimer *ptn;
                    804:
1.142     ad        805:        KASSERT(mutex_owned(&timer_lock));
                    806:
1.150     christos  807:        *aits = pt->pt_time;
1.168     yamt      808:        if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
1.1       cgd       809:                /*
1.12      mycroft   810:                 * Convert from absolute to relative time in .it_value
1.63      thorpej   811:                 * part of real time timer.  If time for real time
                    812:                 * timer has passed return 0, else return difference
                    813:                 * between current time and time for the timer to go
                    814:                 * off.
1.1       cgd       815:                 */
1.150     christos  816:                if (timespecisset(&aits->it_value)) {
1.168     yamt      817:                        if (pt->pt_type == CLOCK_REALTIME) {
                    818:                                getnanotime(&now);
                    819:                        } else { /* CLOCK_MONOTONIC */
                    820:                                getnanouptime(&now);
                    821:                        }
1.150     christos  822:                        if (timespeccmp(&aits->it_value, &now, <))
                    823:                                timespecclear(&aits->it_value);
1.101     kardel    824:                        else
1.150     christos  825:                                timespecsub(&aits->it_value, &now,
                    826:                                    &aits->it_value);
1.36      thorpej   827:                }
1.63      thorpej   828:        } else if (pt->pt_active) {
                    829:                if (pt->pt_type == CLOCK_VIRTUAL)
                    830:                        ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual);
                    831:                else
                    832:                        ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof);
                    833:                for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list))
1.150     christos  834:                        timespecadd(&aits->it_value,
                    835:                            &ptn->pt_time.it_value, &aits->it_value);
1.63      thorpej   836:                KASSERT(ptn != NULL); /* pt should be findable on the list */
1.1       cgd       837:        } else
1.150     christos  838:                timespecclear(&aits->it_value);
1.63      thorpej   839: }
                    840:
                    841:
                    842:
                    843: /* Set and arm a POSIX realtime timer */
                    844: int
1.156     christos  845: sys___timer_settime50(struct lwp *l,
                    846:     const struct sys___timer_settime50_args *uap,
1.140     yamt      847:     register_t *retval)
1.63      thorpej   848: {
1.135     dsl       849:        /* {
1.63      thorpej   850:                syscallarg(timer_t) timerid;
                    851:                syscallarg(int) flags;
                    852:                syscallarg(const struct itimerspec *) value;
                    853:                syscallarg(struct itimerspec *) ovalue;
1.135     dsl       854:        } */
1.92      cube      855:        int error;
                    856:        struct itimerspec value, ovalue, *ovp = NULL;
                    857:
                    858:        if ((error = copyin(SCARG(uap, value), &value,
                    859:            sizeof(struct itimerspec))) != 0)
                    860:                return (error);
                    861:
                    862:        if (SCARG(uap, ovalue))
                    863:                ovp = &ovalue;
                    864:
                    865:        if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
                    866:            SCARG(uap, flags), l->l_proc)) != 0)
                    867:                return error;
                    868:
                    869:        if (ovp)
                    870:                return copyout(&ovalue, SCARG(uap, ovalue),
                    871:                    sizeof(struct itimerspec));
                    872:        return 0;
                    873: }
                    874:
                    875: int
                    876: dotimer_settime(int timerid, struct itimerspec *value,
                    877:     struct itimerspec *ovalue, int flags, struct proc *p)
                    878: {
1.150     christos  879:        struct timespec now;
                    880:        struct itimerspec val, oval;
1.142     ad        881:        struct ptimers *pts;
1.63      thorpej   882:        struct ptimer *pt;
1.160     christos  883:        int error;
1.63      thorpej   884:
1.142     ad        885:        pts = p->p_timers;
1.63      thorpej   886:
1.142     ad        887:        if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
                    888:                return EINVAL;
1.150     christos  889:        val = *value;
1.160     christos  890:        if ((error = itimespecfix(&val.it_value)) != 0 ||
                    891:            (error = itimespecfix(&val.it_interval)) != 0)
                    892:                return error;
1.63      thorpej   893:
1.142     ad        894:        mutex_spin_enter(&timer_lock);
1.198     riastrad  895: restart:
1.142     ad        896:        if ((pt = pts->pts_timers[timerid]) == NULL) {
                    897:                mutex_spin_exit(&timer_lock);
1.150     christos  898:                return EINVAL;
1.142     ad        899:        }
                    900:
1.63      thorpej   901:        oval = pt->pt_time;
                    902:        pt->pt_time = val;
                    903:
1.67      nathanw   904:        /*
                    905:         * If we've been passed a relative time for a realtime timer,
                    906:         * convert it to absolute; if an absolute time for a virtual
                    907:         * timer, convert it to relative and make sure we don't set it
                    908:         * to zero, which would cancel the timer, or let it go
                    909:         * negative, which would confuse the comparison tests.
                    910:         */
1.150     christos  911:        if (timespecisset(&pt->pt_time.it_value)) {
1.168     yamt      912:                if (!CLOCK_VIRTUAL_P(pt->pt_type)) {
1.101     kardel    913:                        if ((flags & TIMER_ABSTIME) == 0) {
1.168     yamt      914:                                if (pt->pt_type == CLOCK_REALTIME) {
                    915:                                        getnanotime(&now);
                    916:                                } else { /* CLOCK_MONOTONIC */
                    917:                                        getnanouptime(&now);
                    918:                                }
1.150     christos  919:                                timespecadd(&pt->pt_time.it_value, &now,
1.101     kardel    920:                                    &pt->pt_time.it_value);
                    921:                        }
1.67      nathanw   922:                } else {
1.92      cube      923:                        if ((flags & TIMER_ABSTIME) != 0) {
1.150     christos  924:                                getnanotime(&now);
                    925:                                timespecsub(&pt->pt_time.it_value, &now,
1.101     kardel    926:                                    &pt->pt_time.it_value);
1.150     christos  927:                                if (!timespecisset(&pt->pt_time.it_value) ||
1.67      nathanw   928:                                    pt->pt_time.it_value.tv_sec < 0) {
                    929:                                        pt->pt_time.it_value.tv_sec = 0;
1.150     christos  930:                                        pt->pt_time.it_value.tv_nsec = 1;
1.67      nathanw   931:                                }
                    932:                        }
                    933:                }
                    934:        }
                    935:
1.198     riastrad  936:        error = timer_settime(pt);
                    937:        if (error == ERESTART) {
                    938:                KASSERT(!CLOCK_VIRTUAL_P(pt->pt_type));
                    939:                goto restart;
                    940:        }
                    941:        KASSERT(error == 0);
1.142     ad        942:        mutex_spin_exit(&timer_lock);
1.63      thorpej   943:
1.150     christos  944:        if (ovalue)
                    945:                *ovalue = oval;
1.63      thorpej   946:
                    947:        return (0);
                    948: }
                    949:
                    950: /* Return the time remaining until a POSIX timer fires. */
                    951: int
1.156     christos  952: sys___timer_gettime50(struct lwp *l,
                    953:     const struct sys___timer_gettime50_args *uap, register_t *retval)
1.63      thorpej   954: {
1.135     dsl       955:        /* {
1.63      thorpej   956:                syscallarg(timer_t) timerid;
                    957:                syscallarg(struct itimerspec *) value;
1.135     dsl       958:        } */
1.63      thorpej   959:        struct itimerspec its;
1.92      cube      960:        int error;
                    961:
                    962:        if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
                    963:            &its)) != 0)
                    964:                return error;
                    965:
                    966:        return copyout(&its, SCARG(uap, value), sizeof(its));
                    967: }
                    968:
                    969: int
                    970: dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its)
                    971: {
1.63      thorpej   972:        struct ptimer *pt;
1.142     ad        973:        struct ptimers *pts;
1.63      thorpej   974:
1.142     ad        975:        pts = p->p_timers;
                    976:        if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
1.63      thorpej   977:                return (EINVAL);
1.142     ad        978:        mutex_spin_enter(&timer_lock);
                    979:        if ((pt = pts->pts_timers[timerid]) == NULL) {
                    980:                mutex_spin_exit(&timer_lock);
                    981:                return (EINVAL);
                    982:        }
1.150     christos  983:        timer_gettime(pt, its);
1.142     ad        984:        mutex_spin_exit(&timer_lock);
1.63      thorpej   985:
1.92      cube      986:        return 0;
1.63      thorpej   987: }
                    988:
                    989: /*
                    990:  * Return the count of the number of times a periodic timer expired
                    991:  * while a notification was already pending. The counter is reset when
                    992:  * a timer expires and a notification can be posted.
                    993:  */
                    994: int
1.140     yamt      995: sys_timer_getoverrun(struct lwp *l, const struct sys_timer_getoverrun_args *uap,
                    996:     register_t *retval)
1.63      thorpej   997: {
1.135     dsl       998:        /* {
1.63      thorpej   999:                syscallarg(timer_t) timerid;
1.135     dsl      1000:        } */
1.63      thorpej  1001:        struct proc *p = l->l_proc;
1.142     ad       1002:        struct ptimers *pts;
1.63      thorpej  1003:        int timerid;
                   1004:        struct ptimer *pt;
                   1005:
                   1006:        timerid = SCARG(uap, timerid);
                   1007:
1.142     ad       1008:        pts = p->p_timers;
                   1009:        if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
                   1010:                return (EINVAL);
                   1011:        mutex_spin_enter(&timer_lock);
                   1012:        if ((pt = pts->pts_timers[timerid]) == NULL) {
                   1013:                mutex_spin_exit(&timer_lock);
1.63      thorpej  1014:                return (EINVAL);
1.142     ad       1015:        }
1.63      thorpej  1016:        *retval = pt->pt_poverruns;
1.187     christos 1017:        if (*retval >= DELAYTIMER_MAX)
                   1018:                *retval = DELAYTIMER_MAX;
1.142     ad       1019:        mutex_spin_exit(&timer_lock);
1.63      thorpej  1020:
                   1021:        return (0);
                   1022: }
                   1023:
                   1024: /*
                   1025:  * Real interval timer expired:
                   1026:  * send process whose timer expired an alarm signal.
                   1027:  * If time is not set up to reload, then just return.
                   1028:  * Else compute next time timer should go off which is > current time.
                   1029:  * This is where delay in processing this timeout causes multiple
                   1030:  * SIGALRM calls to be compressed into one.
                   1031:  */
                   1032: void
                   1033: realtimerexpire(void *arg)
                   1034: {
1.166     yamt     1035:        uint64_t last_val, next_val, interval, now_ns;
1.150     christos 1036:        struct timespec now, next;
1.63      thorpej  1037:        struct ptimer *pt;
1.148     joerg    1038:        int backwards;
1.63      thorpej  1039:
1.142     ad       1040:        pt = arg;
1.63      thorpej  1041:
1.142     ad       1042:        mutex_spin_enter(&timer_lock);
1.63      thorpej  1043:        itimerfire(pt);
                   1044:
1.150     christos 1045:        if (!timespecisset(&pt->pt_time.it_interval)) {
                   1046:                timespecclear(&pt->pt_time.it_value);
1.142     ad       1047:                mutex_spin_exit(&timer_lock);
1.63      thorpej  1048:                return;
                   1049:        }
1.148     joerg    1050:
1.171     christos 1051:        if (pt->pt_type == CLOCK_MONOTONIC) {
                   1052:                getnanouptime(&now);
                   1053:        } else {
                   1054:                getnanotime(&now);
                   1055:        }
1.150     christos 1056:        backwards = (timespeccmp(&pt->pt_time.it_value, &now, >));
                   1057:        timespecadd(&pt->pt_time.it_value, &pt->pt_time.it_interval, &next);
1.148     joerg    1058:        /* Handle the easy case of non-overflown timers first. */
1.150     christos 1059:        if (!backwards && timespeccmp(&next, &now, >)) {
1.148     joerg    1060:                pt->pt_time.it_value = next;
                   1061:        } else {
1.166     yamt     1062:                now_ns = timespec2ns(&now);
1.150     christos 1063:                last_val = timespec2ns(&pt->pt_time.it_value);
                   1064:                interval = timespec2ns(&pt->pt_time.it_interval);
1.148     joerg    1065:
1.166     yamt     1066:                next_val = now_ns +
                   1067:                    (now_ns - last_val + interval - 1) % interval;
1.148     joerg    1068:
                   1069:                if (backwards)
                   1070:                        next_val += interval;
                   1071:                else
1.166     yamt     1072:                        pt->pt_overruns += (now_ns - last_val) / interval;
1.148     joerg    1073:
1.150     christos 1074:                pt->pt_time.it_value.tv_sec = next_val / 1000000000;
                   1075:                pt->pt_time.it_value.tv_nsec = next_val % 1000000000;
1.101     kardel   1076:        }
1.148     joerg    1077:
                   1078:        /*
1.198     riastrad 1079:         * Reset the callout, if it's not going away.
                   1080:         *
1.150     christos 1081:         * Don't need to check tshzto() return value, here.
1.148     joerg    1082:         * callout_reset() does it for us.
                   1083:         */
1.198     riastrad 1084:        if (!pt->pt_dying)
                   1085:                callout_reset(&pt->pt_ch,
                   1086:                    (pt->pt_type == CLOCK_MONOTONIC
                   1087:                        ? tshztoup(&pt->pt_time.it_value)
                   1088:                        : tshzto(&pt->pt_time.it_value)),
                   1089:                    realtimerexpire, pt);
1.148     joerg    1090:        mutex_spin_exit(&timer_lock);
1.63      thorpej  1091: }
                   1092:
                   1093: /* BSD routine to get the value of an interval timer. */
                   1094: /* ARGSUSED */
                   1095: int
1.156     christos 1096: sys___getitimer50(struct lwp *l, const struct sys___getitimer50_args *uap,
1.140     yamt     1097:     register_t *retval)
1.63      thorpej  1098: {
1.135     dsl      1099:        /* {
1.63      thorpej  1100:                syscallarg(int) which;
                   1101:                syscallarg(struct itimerval *) itv;
1.135     dsl      1102:        } */
1.63      thorpej  1103:        struct proc *p = l->l_proc;
                   1104:        struct itimerval aitv;
1.91      cube     1105:        int error;
                   1106:
1.191     maxv     1107:        memset(&aitv, 0, sizeof(aitv));
1.91      cube     1108:        error = dogetitimer(p, SCARG(uap, which), &aitv);
                   1109:        if (error)
                   1110:                return error;
                   1111:        return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
                   1112: }
1.63      thorpej  1113:
1.91      cube     1114: int
                   1115: dogetitimer(struct proc *p, int which, struct itimerval *itvp)
                   1116: {
1.142     ad       1117:        struct ptimers *pts;
                   1118:        struct ptimer *pt;
1.150     christos 1119:        struct itimerspec its;
1.63      thorpej  1120:
1.170     christos 1121:        if ((u_int)which > ITIMER_MONOTONIC)
1.63      thorpej  1122:                return (EINVAL);
                   1123:
1.142     ad       1124:        mutex_spin_enter(&timer_lock);
                   1125:        pts = p->p_timers;
                   1126:        if (pts == NULL || (pt = pts->pts_timers[which]) == NULL) {
1.91      cube     1127:                timerclear(&itvp->it_value);
                   1128:                timerclear(&itvp->it_interval);
1.150     christos 1129:        } else {
                   1130:                timer_gettime(pt, &its);
1.151     christos 1131:                TIMESPEC_TO_TIMEVAL(&itvp->it_value, &its.it_value);
                   1132:                TIMESPEC_TO_TIMEVAL(&itvp->it_interval, &its.it_interval);
1.150     christos 1133:        }
1.188     msaitoh  1134:        mutex_spin_exit(&timer_lock);
1.63      thorpej  1135:
1.91      cube     1136:        return 0;
1.1       cgd      1137: }
                   1138:
1.63      thorpej  1139: /* BSD routine to set/arm an interval timer. */
1.1       cgd      1140: /* ARGSUSED */
1.3       andrew   1141: int
1.156     christos 1142: sys___setitimer50(struct lwp *l, const struct sys___setitimer50_args *uap,
1.140     yamt     1143:     register_t *retval)
1.15      thorpej  1144: {
1.135     dsl      1145:        /* {
1.30      mycroft  1146:                syscallarg(int) which;
1.24      cgd      1147:                syscallarg(const struct itimerval *) itv;
1.11      cgd      1148:                syscallarg(struct itimerval *) oitv;
1.135     dsl      1149:        } */
1.63      thorpej  1150:        struct proc *p = l->l_proc;
1.30      mycroft  1151:        int which = SCARG(uap, which);
1.156     christos 1152:        struct sys___getitimer50_args getargs;
1.91      cube     1153:        const struct itimerval *itvp;
1.1       cgd      1154:        struct itimerval aitv;
1.91      cube     1155:        int error;
1.1       cgd      1156:
1.170     christos 1157:        if ((u_int)which > ITIMER_MONOTONIC)
1.1       cgd      1158:                return (EINVAL);
1.11      cgd      1159:        itvp = SCARG(uap, itv);
1.63      thorpej  1160:        if (itvp &&
1.174     dholland 1161:            (error = copyin(itvp, &aitv, sizeof(struct itimerval))) != 0)
1.1       cgd      1162:                return (error);
1.21      cgd      1163:        if (SCARG(uap, oitv) != NULL) {
1.30      mycroft  1164:                SCARG(&getargs, which) = which;
1.21      cgd      1165:                SCARG(&getargs, itv) = SCARG(uap, oitv);
1.156     christos 1166:                if ((error = sys___getitimer50(l, &getargs, retval)) != 0)
1.21      cgd      1167:                        return (error);
                   1168:        }
1.1       cgd      1169:        if (itvp == 0)
                   1170:                return (0);
1.91      cube     1171:
                   1172:        return dosetitimer(p, which, &aitv);
                   1173: }
                   1174:
                   1175: int
                   1176: dosetitimer(struct proc *p, int which, struct itimerval *itvp)
                   1177: {
1.150     christos 1178:        struct timespec now;
1.142     ad       1179:        struct ptimers *pts;
                   1180:        struct ptimer *pt, *spare;
1.198     riastrad 1181:        int error;
1.91      cube     1182:
1.170     christos 1183:        KASSERT((u_int)which <= CLOCK_MONOTONIC);
1.91      cube     1184:        if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
1.1       cgd      1185:                return (EINVAL);
1.63      thorpej  1186:
                   1187:        /*
                   1188:         * Don't bother allocating data structures if the process just
                   1189:         * wants to clear the timer.
                   1190:         */
1.142     ad       1191:        spare = NULL;
                   1192:        pts = p->p_timers;
                   1193:  retry:
                   1194:        if (!timerisset(&itvp->it_value) && (pts == NULL ||
                   1195:            pts->pts_timers[which] == NULL))
1.63      thorpej  1196:                return (0);
1.142     ad       1197:        if (pts == NULL)
                   1198:                pts = timers_alloc(p);
                   1199:        mutex_spin_enter(&timer_lock);
1.198     riastrad 1200: restart:
1.142     ad       1201:        pt = pts->pts_timers[which];
                   1202:        if (pt == NULL) {
                   1203:                if (spare == NULL) {
                   1204:                        mutex_spin_exit(&timer_lock);
1.195     christos 1205:                        spare = pool_get(&ptimer_pool, PR_WAITOK | PR_ZERO);
1.142     ad       1206:                        goto retry;
                   1207:                }
                   1208:                pt = spare;
                   1209:                spare = NULL;
1.63      thorpej  1210:                pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
1.76      christos 1211:                pt->pt_ev.sigev_value.sival_int = which;
1.63      thorpej  1212:                pt->pt_overruns = 0;
                   1213:                pt->pt_proc = p;
                   1214:                pt->pt_type = which;
1.64      nathanw  1215:                pt->pt_entry = which;
1.142     ad       1216:                pt->pt_queued = false;
1.196     mlelstv  1217:                if (!CLOCK_VIRTUAL_P(which))
1.149     christos 1218:                        callout_init(&pt->pt_ch, CALLOUT_MPSAFE);
                   1219:                else
                   1220:                        pt->pt_active = 0;
                   1221:
1.63      thorpej  1222:                switch (which) {
                   1223:                case ITIMER_REAL:
1.170     christos 1224:                case ITIMER_MONOTONIC:
1.63      thorpej  1225:                        pt->pt_ev.sigev_signo = SIGALRM;
                   1226:                        break;
                   1227:                case ITIMER_VIRTUAL:
                   1228:                        pt->pt_ev.sigev_signo = SIGVTALRM;
                   1229:                        break;
                   1230:                case ITIMER_PROF:
                   1231:                        pt->pt_ev.sigev_signo = SIGPROF;
                   1232:                        break;
1.1       cgd      1233:                }
1.142     ad       1234:                pts->pts_timers[which] = pt;
                   1235:        }
1.63      thorpej  1236:
1.150     christos 1237:        TIMEVAL_TO_TIMESPEC(&itvp->it_value, &pt->pt_time.it_value);
                   1238:        TIMEVAL_TO_TIMESPEC(&itvp->it_interval, &pt->pt_time.it_interval);
                   1239:
1.170     christos 1240:        if (timespecisset(&pt->pt_time.it_value)) {
1.67      nathanw  1241:                /* Convert to absolute time */
1.101     kardel   1242:                /* XXX need to wrap in splclock for timecounters case? */
1.170     christos 1243:                switch (which) {
                   1244:                case ITIMER_REAL:
                   1245:                        getnanotime(&now);
                   1246:                        timespecadd(&pt->pt_time.it_value, &now,
                   1247:                            &pt->pt_time.it_value);
                   1248:                        break;
                   1249:                case ITIMER_MONOTONIC:
                   1250:                        getnanouptime(&now);
                   1251:                        timespecadd(&pt->pt_time.it_value, &now,
                   1252:                            &pt->pt_time.it_value);
                   1253:                        break;
                   1254:                default:
                   1255:                        break;
                   1256:                }
1.67      nathanw  1257:        }
1.198     riastrad 1258:        error = timer_settime(pt);
                   1259:        if (error == ERESTART) {
                   1260:                KASSERT(!CLOCK_VIRTUAL_P(pt->pt_type));
                   1261:                goto restart;
                   1262:        }
                   1263:        KASSERT(error == 0);
1.142     ad       1264:        mutex_spin_exit(&timer_lock);
                   1265:        if (spare != NULL)
                   1266:                pool_put(&ptimer_pool, spare);
1.63      thorpej  1267:
1.1       cgd      1268:        return (0);
                   1269: }
                   1270:
1.63      thorpej  1271: /* Utility routines to manage the array of pointers to timers. */
1.142     ad       1272: struct ptimers *
1.63      thorpej  1273: timers_alloc(struct proc *p)
                   1274: {
1.142     ad       1275:        struct ptimers *pts;
1.63      thorpej  1276:        int i;
                   1277:
1.100     yamt     1278:        pts = pool_get(&ptimers_pool, PR_WAITOK);
1.63      thorpej  1279:        LIST_INIT(&pts->pts_virtual);
                   1280:        LIST_INIT(&pts->pts_prof);
                   1281:        for (i = 0; i < TIMER_MAX; i++)
                   1282:                pts->pts_timers[i] = NULL;
1.142     ad       1283:        mutex_spin_enter(&timer_lock);
                   1284:        if (p->p_timers == NULL) {
                   1285:                p->p_timers = pts;
                   1286:                mutex_spin_exit(&timer_lock);
                   1287:                return pts;
                   1288:        }
                   1289:        mutex_spin_exit(&timer_lock);
                   1290:        pool_put(&ptimers_pool, pts);
                   1291:        return p->p_timers;
1.63      thorpej  1292: }
                   1293:
1.1       cgd      1294: /*
1.63      thorpej  1295:  * Clean up the per-process timers. If "which" is set to TIMERS_ALL,
                   1296:  * then clean up all timers and free all the data structures. If
                   1297:  * "which" is set to TIMERS_POSIX, only clean up the timers allocated
                   1298:  * by timer_create(), not the BSD setitimer() timers, and only free the
                   1299:  * structure if none of those remain.
1.1       cgd      1300:  */
1.3       andrew   1301: void
1.63      thorpej  1302: timers_free(struct proc *p, int which)
1.6       cgd      1303: {
1.63      thorpej  1304:        struct ptimers *pts;
1.142     ad       1305:        struct ptimer *ptn;
1.150     christos 1306:        struct timespec ts;
1.142     ad       1307:        int i;
1.63      thorpej  1308:
1.142     ad       1309:        if (p->p_timers == NULL)
                   1310:                return;
1.63      thorpej  1311:
1.142     ad       1312:        pts = p->p_timers;
                   1313:        mutex_spin_enter(&timer_lock);
                   1314:        if (which == TIMERS_ALL) {
                   1315:                p->p_timers = NULL;
                   1316:                i = 0;
                   1317:        } else {
1.150     christos 1318:                timespecclear(&ts);
1.142     ad       1319:                for (ptn = LIST_FIRST(&pts->pts_virtual);
                   1320:                     ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL];
1.149     christos 1321:                     ptn = LIST_NEXT(ptn, pt_list)) {
1.168     yamt     1322:                        KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
1.150     christos 1323:                        timespecadd(&ts, &ptn->pt_time.it_value, &ts);
1.149     christos 1324:                }
1.142     ad       1325:                LIST_FIRST(&pts->pts_virtual) = NULL;
                   1326:                if (ptn) {
1.168     yamt     1327:                        KASSERT(ptn->pt_type == CLOCK_VIRTUAL);
1.150     christos 1328:                        timespecadd(&ts, &ptn->pt_time.it_value,
1.142     ad       1329:                            &ptn->pt_time.it_value);
                   1330:                        LIST_INSERT_HEAD(&pts->pts_virtual, ptn, pt_list);
                   1331:                }
1.150     christos 1332:                timespecclear(&ts);
1.142     ad       1333:                for (ptn = LIST_FIRST(&pts->pts_prof);
                   1334:                     ptn && ptn != pts->pts_timers[ITIMER_PROF];
1.149     christos 1335:                     ptn = LIST_NEXT(ptn, pt_list)) {
1.168     yamt     1336:                        KASSERT(ptn->pt_type == CLOCK_PROF);
1.150     christos 1337:                        timespecadd(&ts, &ptn->pt_time.it_value, &ts);
1.149     christos 1338:                }
1.142     ad       1339:                LIST_FIRST(&pts->pts_prof) = NULL;
                   1340:                if (ptn) {
1.168     yamt     1341:                        KASSERT(ptn->pt_type == CLOCK_PROF);
1.150     christos 1342:                        timespecadd(&ts, &ptn->pt_time.it_value,
1.142     ad       1343:                            &ptn->pt_time.it_value);
                   1344:                        LIST_INSERT_HEAD(&pts->pts_prof, ptn, pt_list);
1.63      thorpej  1345:                }
1.183     christos 1346:                i = TIMER_MIN;
1.142     ad       1347:        }
                   1348:        for ( ; i < TIMER_MAX; i++) {
                   1349:                if (pts->pts_timers[i] != NULL) {
1.198     riastrad 1350:                        /* Free the timer and release the lock.  */
1.142     ad       1351:                        itimerfree(pts, i);
1.198     riastrad 1352:                        /* Reacquire the lock for the next one.  */
1.142     ad       1353:                        mutex_spin_enter(&timer_lock);
1.1       cgd      1354:                }
                   1355:        }
1.142     ad       1356:        if (pts->pts_timers[0] == NULL && pts->pts_timers[1] == NULL &&
1.183     christos 1357:            pts->pts_timers[2] == NULL && pts->pts_timers[3] == NULL) {
1.142     ad       1358:                p->p_timers = NULL;
                   1359:                mutex_spin_exit(&timer_lock);
                   1360:                pool_put(&ptimers_pool, pts);
                   1361:        } else
                   1362:                mutex_spin_exit(&timer_lock);
                   1363: }
                   1364:
                   1365: static void
                   1366: itimerfree(struct ptimers *pts, int index)
                   1367: {
                   1368:        struct ptimer *pt;
                   1369:
                   1370:        KASSERT(mutex_owned(&timer_lock));
                   1371:
                   1372:        pt = pts->pts_timers[index];
1.198     riastrad 1373:
                   1374:        /*
                   1375:         * Prevent new references, and notify the callout not to
                   1376:         * restart itself.
                   1377:         */
1.142     ad       1378:        pts->pts_timers[index] = NULL;
1.198     riastrad 1379:        pt->pt_dying = true;
                   1380:
                   1381:        /*
                   1382:         * For non-virtual timers, stop the callout, or wait for it to
                   1383:         * run if it has already fired.  It cannot restart again after
                   1384:         * this point: the callout won't restart itself when dying, no
                   1385:         * other users holding the lock can restart it, and any other
                   1386:         * users waiting for callout_halt concurrently (timer_settime)
                   1387:         * will restart from the top.
                   1388:         */
1.168     yamt     1389:        if (!CLOCK_VIRTUAL_P(pt->pt_type))
1.144     ad       1390:                callout_halt(&pt->pt_ch, &timer_lock);
1.198     riastrad 1391:
                   1392:        /* Remove it from the queue to be signalled.  */
1.167     yamt     1393:        if (pt->pt_queued)
1.142     ad       1394:                TAILQ_REMOVE(&timer_queue, pt, pt_chain);
1.198     riastrad 1395:
                   1396:        /* All done with the global state.  */
1.144     ad       1397:        mutex_spin_exit(&timer_lock);
1.198     riastrad 1398:
                   1399:        /* Destroy the callout, if needed, and free the ptimer.  */
1.168     yamt     1400:        if (!CLOCK_VIRTUAL_P(pt->pt_type))
1.149     christos 1401:                callout_destroy(&pt->pt_ch);
1.142     ad       1402:        pool_put(&ptimer_pool, pt);
1.1       cgd      1403: }
                   1404:
                   1405: /*
                   1406:  * Decrement an interval timer by a specified number
1.152     christos 1407:  * of nanoseconds, which must be less than a second,
                   1408:  * i.e. < 1000000000.  If the timer expires, then reload
                   1409:  * it.  In this case, carry over (nsec - old value) to
1.8       cgd      1410:  * reduce the value reloaded into the timer so that
1.1       cgd      1411:  * the timer does not drift.  This routine assumes
                   1412:  * that it is called in a context where the timers
                   1413:  * on which it is operating cannot change in value.
                   1414:  */
1.142     ad       1415: static int
1.152     christos 1416: itimerdecr(struct ptimer *pt, int nsec)
1.63      thorpej  1417: {
1.150     christos 1418:        struct itimerspec *itp;
1.199     mrg      1419:        int error __diagused;
1.1       cgd      1420:
1.142     ad       1421:        KASSERT(mutex_owned(&timer_lock));
1.168     yamt     1422:        KASSERT(CLOCK_VIRTUAL_P(pt->pt_type));
1.142     ad       1423:
1.63      thorpej  1424:        itp = &pt->pt_time;
1.150     christos 1425:        if (itp->it_value.tv_nsec < nsec) {
1.1       cgd      1426:                if (itp->it_value.tv_sec == 0) {
                   1427:                        /* expired, and already in next interval */
1.150     christos 1428:                        nsec -= itp->it_value.tv_nsec;
1.1       cgd      1429:                        goto expire;
                   1430:                }
1.150     christos 1431:                itp->it_value.tv_nsec += 1000000000;
1.1       cgd      1432:                itp->it_value.tv_sec--;
                   1433:        }
1.152     christos 1434:        itp->it_value.tv_nsec -= nsec;
                   1435:        nsec = 0;
1.150     christos 1436:        if (timespecisset(&itp->it_value))
1.1       cgd      1437:                return (1);
                   1438:        /* expired, exactly at end of interval */
                   1439: expire:
1.150     christos 1440:        if (timespecisset(&itp->it_interval)) {
1.1       cgd      1441:                itp->it_value = itp->it_interval;
1.150     christos 1442:                itp->it_value.tv_nsec -= nsec;
                   1443:                if (itp->it_value.tv_nsec < 0) {
                   1444:                        itp->it_value.tv_nsec += 1000000000;
1.1       cgd      1445:                        itp->it_value.tv_sec--;
                   1446:                }
1.198     riastrad 1447:                error = timer_settime(pt);
                   1448:                KASSERT(error == 0); /* virtual, never fails */
1.1       cgd      1449:        } else
1.150     christos 1450:                itp->it_value.tv_nsec = 0;              /* sec is already 0 */
1.1       cgd      1451:        return (0);
1.42      cgd      1452: }
                   1453:
1.142     ad       1454: static void
1.63      thorpej  1455: itimerfire(struct ptimer *pt)
                   1456: {
1.78      cl       1457:
1.142     ad       1458:        KASSERT(mutex_owned(&timer_lock));
                   1459:
                   1460:        /*
                   1461:         * XXX Can overrun, but we don't do signal queueing yet, anyway.
                   1462:         * XXX Relying on the clock interrupt is stupid.
                   1463:         */
1.173     rmind    1464:        if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL || pt->pt_queued) {
1.142     ad       1465:                return;
1.172     rmind    1466:        }
1.142     ad       1467:        TAILQ_INSERT_TAIL(&timer_queue, pt, pt_chain);
                   1468:        pt->pt_queued = true;
                   1469:        softint_schedule(timer_sih);
                   1470: }
                   1471:
                   1472: void
                   1473: timer_tick(lwp_t *l, bool user)
                   1474: {
                   1475:        struct ptimers *pts;
                   1476:        struct ptimer *pt;
                   1477:        proc_t *p;
                   1478:
                   1479:        p = l->l_proc;
                   1480:        if (p->p_timers == NULL)
                   1481:                return;
                   1482:
                   1483:        mutex_spin_enter(&timer_lock);
                   1484:        if ((pts = l->l_proc->p_timers) != NULL) {
1.63      thorpej  1485:                /*
1.142     ad       1486:                 * Run current process's virtual and profile time, as needed.
1.63      thorpej  1487:                 */
1.142     ad       1488:                if (user && (pt = LIST_FIRST(&pts->pts_virtual)) != NULL)
1.152     christos 1489:                        if (itimerdecr(pt, tick * 1000) == 0)
1.142     ad       1490:                                itimerfire(pt);
                   1491:                if ((pt = LIST_FIRST(&pts->pts_prof)) != NULL)
1.152     christos 1492:                        if (itimerdecr(pt, tick * 1000) == 0)
1.142     ad       1493:                                itimerfire(pt);
                   1494:        }
                   1495:        mutex_spin_exit(&timer_lock);
                   1496: }
                   1497:
                   1498: static void
                   1499: timer_intr(void *cookie)
                   1500: {
                   1501:        ksiginfo_t ksi;
                   1502:        struct ptimer *pt;
                   1503:        proc_t *p;
                   1504:
1.158     ad       1505:        mutex_enter(proc_lock);
1.142     ad       1506:        mutex_spin_enter(&timer_lock);
                   1507:        while ((pt = TAILQ_FIRST(&timer_queue)) != NULL) {
                   1508:                TAILQ_REMOVE(&timer_queue, pt, pt_chain);
                   1509:                KASSERT(pt->pt_queued);
                   1510:                pt->pt_queued = false;
                   1511:
1.154     wrstuden 1512:                if (pt->pt_proc->p_timers == NULL) {
                   1513:                        /* Process is dying. */
1.142     ad       1514:                        continue;
1.154     wrstuden 1515:                }
1.142     ad       1516:                p = pt->pt_proc;
1.172     rmind    1517:                if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL) {
1.142     ad       1518:                        continue;
                   1519:                }
                   1520:                if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) {
1.63      thorpej  1521:                        pt->pt_overruns++;
1.142     ad       1522:                        continue;
1.64      nathanw  1523:                }
1.142     ad       1524:
                   1525:                KSI_INIT(&ksi);
                   1526:                ksi.ksi_signo = pt->pt_ev.sigev_signo;
                   1527:                ksi.ksi_code = SI_TIMER;
                   1528:                ksi.ksi_value = pt->pt_ev.sigev_value;
                   1529:                pt->pt_poverruns = pt->pt_overruns;
                   1530:                pt->pt_overruns = 0;
                   1531:                mutex_spin_exit(&timer_lock);
                   1532:                kpsignal(p, &ksi, NULL);
                   1533:                mutex_spin_enter(&timer_lock);
1.63      thorpej  1534:        }
1.142     ad       1535:        mutex_spin_exit(&timer_lock);
1.158     ad       1536:        mutex_exit(proc_lock);
1.63      thorpej  1537: }
1.162     elad     1538:
                   1539: /*
                   1540:  * Check if the time will wrap if set to ts.
                   1541:  *
                   1542:  * ts - timespec describing the new time
                   1543:  * delta - the delta between the current time and ts
                   1544:  */
                   1545: bool
                   1546: time_wraps(struct timespec *ts, struct timespec *delta)
                   1547: {
                   1548:
                   1549:        /*
                   1550:         * Don't allow the time to be set forward so far it
                   1551:         * will wrap and become negative, thus allowing an
                   1552:         * attacker to bypass the next check below.  The
                   1553:         * cutoff is 1 year before rollover occurs, so even
                   1554:         * if the attacker uses adjtime(2) to move the time
                   1555:         * past the cutoff, it will take a very long time
                   1556:         * to get to the wrap point.
                   1557:         */
                   1558:        if ((ts->tv_sec > LLONG_MAX - 365*24*60*60) ||
                   1559:            (delta->tv_sec < 0 || delta->tv_nsec < 0))
                   1560:                return true;
                   1561:
                   1562:        return false;
                   1563: }

CVSweb <webmaster@jp.NetBSD.org>