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

1.33    ! fvdl        1: /*     $NetBSD: kern_time.c,v 1.32 1998/02/20 07:22:14 mycroft Exp $   */
1.9       cgd         2:
1.1       cgd         3: /*
1.8       cgd         4:  * Copyright (c) 1982, 1986, 1989, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
1.33    ! fvdl       35:  *     @(#)kern_time.c 8.4 (Berkeley) 5/26/95
1.1       cgd        36:  */
1.31      thorpej    37:
                     38: #include "fs_nfs.h"
1.1       cgd        39:
1.5       mycroft    40: #include <sys/param.h>
                     41: #include <sys/resourcevar.h>
                     42: #include <sys/kernel.h>
1.8       cgd        43: #include <sys/systm.h>
1.5       mycroft    44: #include <sys/proc.h>
1.8       cgd        45: #include <sys/vnode.h>
1.17      christos   46: #include <sys/signalvar.h>
1.25      perry      47: #include <sys/syslog.h>
1.1       cgd        48:
1.11      cgd        49: #include <sys/mount.h>
                     50: #include <sys/syscallargs.h>
1.19      christos   51:
1.26      thorpej    52: #if defined(NFS) || defined(NFSSERVER)
1.20      fvdl       53: #include <nfs/rpcv2.h>
                     54: #include <nfs/nfsproto.h>
1.19      christos   55: #include <nfs/nfs_var.h>
                     56: #endif
1.17      christos   57:
1.5       mycroft    58: #include <machine/cpu.h>
1.1       cgd        59:
1.29      tls        60: static int     settime __P((struct timeval *));
1.23      cgd        61:
                     62: /*
1.1       cgd        63:  * Time of day and interval timer support.
                     64:  *
                     65:  * These routines provide the kernel entry points to get and set
                     66:  * the time-of-day and per-process interval timers.  Subroutines
                     67:  * here provide support for adding and subtracting timeval structures
                     68:  * and decrementing interval timers, optionally reloading the interval
                     69:  * timers when they expire.
                     70:  */
                     71:
1.22      jtc        72: /* This function is used by clock_settime and settimeofday */
1.29      tls        73: static int
1.22      jtc        74: settime(tv)
                     75:        struct timeval *tv;
                     76: {
                     77:        struct timeval delta;
                     78:        int s;
                     79:
                     80:        /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
                     81:        s = splclock();
                     82:        timersub(tv, &time, &delta);
1.29      tls        83:        if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1)
                     84:                return (EPERM);
                     85: #ifdef notyet
                     86:        if ((delta.tv_sec < 86400) && securelevel > 0)
                     87:                return (EPERM);
                     88: #endif
1.22      jtc        89:        time = *tv;
                     90:        (void) splsoftclock();
                     91:        timeradd(&boottime, &delta, &boottime);
                     92:        timeradd(&runtime, &delta, &runtime);
1.26      thorpej    93: #      if defined(NFS) || defined(NFSSERVER)
1.22      jtc        94:                nqnfs_lease_updatetime(delta.tv_sec);
                     95: #      endif
                     96:        splx(s);
                     97:        resettodr();
1.29      tls        98:        return (0);
1.22      jtc        99: }
                    100:
                    101: /* ARGSUSED */
                    102: int
                    103: sys_clock_gettime(p, v, retval)
                    104:        struct proc *p;
                    105:        void *v;
                    106:        register_t *retval;
                    107: {
                    108:        register struct sys_clock_gettime_args /* {
                    109:                syscallarg(clockid_t) clock_id;
1.23      cgd       110:                syscallarg(struct timespec *) tp;
                    111:        } */ *uap = v;
1.22      jtc       112:        clockid_t clock_id;
                    113:        struct timeval atv;
                    114:        struct timespec ats;
                    115:
                    116:        clock_id = SCARG(uap, clock_id);
                    117:        if (clock_id != CLOCK_REALTIME)
                    118:                return (EINVAL);
                    119:
                    120:        microtime(&atv);
                    121:        TIMEVAL_TO_TIMESPEC(&atv,&ats);
                    122:
1.24      cgd       123:        return copyout(&ats, SCARG(uap, tp), sizeof(ats));
1.22      jtc       124: }
                    125:
                    126: /* ARGSUSED */
                    127: int
                    128: sys_clock_settime(p, v, retval)
                    129:        struct proc *p;
                    130:        void *v;
                    131:        register_t *retval;
                    132: {
                    133:        register struct sys_clock_settime_args /* {
                    134:                syscallarg(clockid_t) clock_id;
1.23      cgd       135:                syscallarg(const struct timespec *) tp;
                    136:        } */ *uap = v;
1.22      jtc       137:        clockid_t clock_id;
                    138:        struct timeval atv;
                    139:        struct timespec ats;
                    140:        int error;
                    141:
                    142:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
                    143:                return (error);
                    144:
                    145:        clock_id = SCARG(uap, clock_id);
                    146:        if (clock_id != CLOCK_REALTIME)
                    147:                return (EINVAL);
                    148:
1.24      cgd       149:        if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
1.23      cgd       150:                return (error);
1.22      jtc       151:
                    152:        TIMESPEC_TO_TIMEVAL(&atv,&ats);
1.29      tls       153:        if ((error = settime(&atv)))
                    154:                return (error);
1.22      jtc       155:
                    156:        return 0;
                    157: }
                    158:
                    159: int
                    160: sys_clock_getres(p, v, retval)
                    161:        struct proc *p;
                    162:        void *v;
                    163:        register_t *retval;
                    164: {
                    165:        register struct sys_clock_getres_args /* {
                    166:                syscallarg(clockid_t) clock_id;
1.23      cgd       167:                syscallarg(struct timespec *) tp;
                    168:        } */ *uap = v;
1.22      jtc       169:        clockid_t clock_id;
                    170:        struct timespec ts;
                    171:        int error = 0;
                    172:
                    173:        clock_id = SCARG(uap, clock_id);
                    174:        if (clock_id != CLOCK_REALTIME)
                    175:                return (EINVAL);
                    176:
                    177:        if (SCARG(uap, tp)) {
                    178:                ts.tv_sec = 0;
                    179:                ts.tv_nsec = 1000000000 / hz;
                    180:
1.24      cgd       181:                error = copyout(&ts, SCARG(uap, tp), sizeof (ts));
1.22      jtc       182:        }
                    183:
                    184:        return error;
                    185: }
                    186:
1.27      jtc       187: /* ARGSUSED */
                    188: int
                    189: sys_nanosleep(p, v, retval)
                    190:        struct proc *p;
                    191:        void *v;
                    192:        register_t *retval;
                    193: {
                    194:        static int nanowait;
                    195:        register struct sys_nanosleep_args/* {
                    196:                syscallarg(struct timespec *) rqtp;
                    197:                syscallarg(struct timespec *) rmtp;
                    198:        } */ *uap = v;
                    199:        struct timespec rqt;
                    200:        struct timespec rmt;
                    201:        struct timeval atv, utv;
                    202:        int error, s, timo;
                    203:
                    204:        error = copyin((caddr_t)SCARG(uap, rqtp), (caddr_t)&rqt,
                    205:                       sizeof(struct timespec));
                    206:        if (error)
                    207:                return (error);
                    208:
                    209:        TIMESPEC_TO_TIMEVAL(&atv,&rqt)
                    210:        if (itimerfix(&atv))
                    211:                return (EINVAL);
                    212:
                    213:        s = splclock();
                    214:        timeradd(&atv,&time,&atv);
                    215:        timo = hzto(&atv);
                    216:        /*
                    217:         * Avoid inadvertantly sleeping forever
                    218:         */
                    219:        if (timo == 0)
                    220:                timo = 1;
                    221:        splx(s);
                    222:
                    223:        error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
                    224:        if (error == ERESTART)
                    225:                error = EINTR;
                    226:        if (error == EWOULDBLOCK)
                    227:                error = 0;
                    228:
                    229:        if (SCARG(uap, rmtp)) {
1.28      jtc       230:                int error;
                    231:
1.27      jtc       232:                s = splclock();
                    233:                utv = time;
                    234:                splx(s);
                    235:
                    236:                timersub(&atv, &utv, &utv);
                    237:                if (utv.tv_sec < 0)
                    238:                        timerclear(&utv);
                    239:
                    240:                TIMEVAL_TO_TIMESPEC(&utv,&rmt);
                    241:                error = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
1.28      jtc       242:                        sizeof(rmt));
                    243:                if (error)
                    244:                        return (error);
1.27      jtc       245:        }
                    246:
                    247:        return error;
                    248: }
1.22      jtc       249:
1.1       cgd       250: /* ARGSUSED */
1.3       andrew    251: int
1.16      mycroft   252: sys_gettimeofday(p, v, retval)
1.1       cgd       253:        struct proc *p;
1.15      thorpej   254:        void *v;
                    255:        register_t *retval;
                    256: {
1.16      mycroft   257:        register struct sys_gettimeofday_args /* {
1.11      cgd       258:                syscallarg(struct timeval *) tp;
                    259:                syscallarg(struct timezone *) tzp;
1.15      thorpej   260:        } */ *uap = v;
1.1       cgd       261:        struct timeval atv;
                    262:        int error = 0;
1.25      perry     263:        struct timezone tzfake;
1.1       cgd       264:
1.11      cgd       265:        if (SCARG(uap, tp)) {
1.1       cgd       266:                microtime(&atv);
1.24      cgd       267:                error = copyout(&atv, SCARG(uap, tp), sizeof (atv));
1.17      christos  268:                if (error)
1.1       cgd       269:                        return (error);
                    270:        }
1.25      perry     271:        if (SCARG(uap, tzp)) {
                    272:                /*
1.32      mycroft   273:                 * NetBSD has no kernel notion of time zone, so we just
1.25      perry     274:                 * fake up a timezone struct and return it if demanded.
                    275:                 */
                    276:                tzfake.tz_minuteswest = 0;
                    277:                tzfake.tz_dsttime = 0;
                    278:                error = copyout(&tzfake, SCARG(uap, tzp), sizeof (tzfake));
                    279:        }
1.1       cgd       280:        return (error);
                    281: }
                    282:
                    283: /* ARGSUSED */
1.3       andrew    284: int
1.16      mycroft   285: sys_settimeofday(p, v, retval)
1.1       cgd       286:        struct proc *p;
1.15      thorpej   287:        void *v;
                    288:        register_t *retval;
                    289: {
1.16      mycroft   290:        struct sys_settimeofday_args /* {
1.24      cgd       291:                syscallarg(const struct timeval *) tv;
                    292:                syscallarg(const struct timezone *) tzp;
1.15      thorpej   293:        } */ *uap = v;
1.22      jtc       294:        struct timeval atv;
1.1       cgd       295:        struct timezone atz;
1.22      jtc       296:        int error;
1.1       cgd       297:
1.17      christos  298:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1       cgd       299:                return (error);
1.8       cgd       300:        /* Verify all parameters before changing time. */
1.24      cgd       301:        if (SCARG(uap, tv) && (error = copyin(SCARG(uap, tv),
                    302:            &atv, sizeof(atv))))
1.8       cgd       303:                return (error);
1.25      perry     304:        /* XXX since we don't use tz, probably no point in doing copyin. */
1.24      cgd       305:        if (SCARG(uap, tzp) && (error = copyin(SCARG(uap, tzp),
                    306:            &atz, sizeof(atz))))
1.8       cgd       307:                return (error);
1.22      jtc       308:        if (SCARG(uap, tv))
1.29      tls       309:                if ((error = settime(&atv)))
                    310:                        return (error);
1.25      perry     311:        /*
1.32      mycroft   312:         * NetBSD has no kernel notion of time zone, and only an
1.25      perry     313:         * obsolete program would try to set it, so we log a warning.
                    314:         */
1.11      cgd       315:        if (SCARG(uap, tzp))
1.25      perry     316:                log(LOG_WARNING, "pid %d attempted to set the "
1.32      mycroft   317:                    "(obsolete) kernel time zone\n", p->p_pid);
1.8       cgd       318:        return (0);
1.1       cgd       319: }
                    320:
                    321: int    tickdelta;                      /* current clock skew, us. per tick */
                    322: long   timedelta;                      /* unapplied time correction, us. */
                    323: long   bigadj = 1000000;               /* use 10x skew above bigadj us. */
                    324:
                    325: /* ARGSUSED */
1.3       andrew    326: int
1.16      mycroft   327: sys_adjtime(p, v, retval)
1.1       cgd       328:        struct proc *p;
1.15      thorpej   329:        void *v;
                    330:        register_t *retval;
                    331: {
1.16      mycroft   332:        register struct sys_adjtime_args /* {
1.24      cgd       333:                syscallarg(const struct timeval *) delta;
1.11      cgd       334:                syscallarg(struct timeval *) olddelta;
1.15      thorpej   335:        } */ *uap = v;
1.8       cgd       336:        struct timeval atv;
                    337:        register long ndelta, ntickdelta, odelta;
1.1       cgd       338:        int s, error;
                    339:
1.17      christos  340:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1       cgd       341:                return (error);
1.17      christos  342:
1.24      cgd       343:        error = copyin(SCARG(uap, delta), &atv, sizeof(struct timeval));
1.17      christos  344:        if (error)
1.1       cgd       345:                return (error);
1.8       cgd       346:
                    347:        /*
                    348:         * Compute the total correction and the rate at which to apply it.
                    349:         * Round the adjustment down to a whole multiple of the per-tick
                    350:         * delta, so that after some number of incremental changes in
                    351:         * hardclock(), tickdelta will become zero, lest the correction
                    352:         * overshoot and start taking us away from the desired final time.
                    353:         */
1.1       cgd       354:        ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
1.8       cgd       355:        if (ndelta > bigadj)
                    356:                ntickdelta = 10 * tickadj;
                    357:        else
                    358:                ntickdelta = tickadj;
                    359:        if (ndelta % ntickdelta)
                    360:                ndelta = ndelta / ntickdelta * ntickdelta;
                    361:
                    362:        /*
                    363:         * To make hardclock()'s job easier, make the per-tick delta negative
                    364:         * if we want time to run slower; then hardclock can simply compute
                    365:         * tick + tickdelta, and subtract tickdelta from timedelta.
                    366:         */
                    367:        if (ndelta < 0)
                    368:                ntickdelta = -ntickdelta;
1.1       cgd       369:        s = splclock();
1.8       cgd       370:        odelta = timedelta;
1.1       cgd       371:        timedelta = ndelta;
1.8       cgd       372:        tickdelta = ntickdelta;
1.1       cgd       373:        splx(s);
                    374:
1.11      cgd       375:        if (SCARG(uap, olddelta)) {
1.8       cgd       376:                atv.tv_sec = odelta / 1000000;
                    377:                atv.tv_usec = odelta % 1000000;
1.24      cgd       378:                (void) copyout(&atv, SCARG(uap, olddelta),
1.8       cgd       379:                    sizeof(struct timeval));
                    380:        }
1.1       cgd       381:        return (0);
                    382: }
                    383:
                    384: /*
                    385:  * Get value of an interval timer.  The process virtual and
                    386:  * profiling virtual time timers are kept in the p_stats area, since
                    387:  * they can be swapped out.  These are kept internally in the
                    388:  * way they are specified externally: in time until they expire.
                    389:  *
                    390:  * The real time interval timer is kept in the process table slot
                    391:  * for the process, and its value (it_value) is kept as an
                    392:  * absolute time rather than as a delta, so that it is easy to keep
                    393:  * periodic real-time signals from drifting.
                    394:  *
                    395:  * Virtual time timers are processed in the hardclock() routine of
                    396:  * kern_clock.c.  The real time timer is processed by a timeout
                    397:  * routine, called from the softclock() routine.  Since a callout
                    398:  * may be delayed in real time due to interrupt processing in the system,
                    399:  * it is possible for the real time timeout routine (realitexpire, given below),
                    400:  * to be delayed in real time past when it is supposed to occur.  It
                    401:  * does not suffice, therefore, to reload the real timer .it_value from the
                    402:  * real time timers .it_interval.  Rather, we compute the next time in
                    403:  * absolute time the timer should go off.
                    404:  */
                    405: /* ARGSUSED */
1.3       andrew    406: int
1.16      mycroft   407: sys_getitimer(p, v, retval)
1.1       cgd       408:        struct proc *p;
1.15      thorpej   409:        void *v;
                    410:        register_t *retval;
                    411: {
1.16      mycroft   412:        register struct sys_getitimer_args /* {
1.30      mycroft   413:                syscallarg(int) which;
1.11      cgd       414:                syscallarg(struct itimerval *) itv;
1.15      thorpej   415:        } */ *uap = v;
1.30      mycroft   416:        int which = SCARG(uap, which);
1.1       cgd       417:        struct itimerval aitv;
                    418:        int s;
                    419:
1.30      mycroft   420:        if ((u_int)which > ITIMER_PROF)
1.1       cgd       421:                return (EINVAL);
                    422:        s = splclock();
1.30      mycroft   423:        if (which == ITIMER_REAL) {
1.1       cgd       424:                /*
1.12      mycroft   425:                 * Convert from absolute to relative time in .it_value
1.1       cgd       426:                 * part of real time timer.  If time for real time timer
                    427:                 * has passed return 0, else return difference between
                    428:                 * current time and time for the timer to go off.
                    429:                 */
                    430:                aitv = p->p_realtimer;
                    431:                if (timerisset(&aitv.it_value))
                    432:                        if (timercmp(&aitv.it_value, &time, <))
                    433:                                timerclear(&aitv.it_value);
                    434:                        else
1.14      mycroft   435:                                timersub(&aitv.it_value, &time, &aitv.it_value);
1.1       cgd       436:        } else
1.30      mycroft   437:                aitv = p->p_stats->p_timer[which];
1.1       cgd       438:        splx(s);
1.24      cgd       439:        return (copyout(&aitv, SCARG(uap, itv), sizeof (struct itimerval)));
1.1       cgd       440: }
                    441:
                    442: /* ARGSUSED */
1.3       andrew    443: int
1.16      mycroft   444: sys_setitimer(p, v, retval)
1.1       cgd       445:        struct proc *p;
1.17      christos  446:        register void *v;
1.15      thorpej   447:        register_t *retval;
                    448: {
1.16      mycroft   449:        register struct sys_setitimer_args /* {
1.30      mycroft   450:                syscallarg(int) which;
1.24      cgd       451:                syscallarg(const struct itimerval *) itv;
1.11      cgd       452:                syscallarg(struct itimerval *) oitv;
1.15      thorpej   453:        } */ *uap = v;
1.30      mycroft   454:        int which = SCARG(uap, which);
1.21      cgd       455:        struct sys_getitimer_args getargs;
1.1       cgd       456:        struct itimerval aitv;
1.24      cgd       457:        register const struct itimerval *itvp;
1.1       cgd       458:        int s, error;
                    459:
1.30      mycroft   460:        if ((u_int)which > ITIMER_PROF)
1.1       cgd       461:                return (EINVAL);
1.11      cgd       462:        itvp = SCARG(uap, itv);
1.24      cgd       463:        if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
1.1       cgd       464:                return (error);
1.21      cgd       465:        if (SCARG(uap, oitv) != NULL) {
1.30      mycroft   466:                SCARG(&getargs, which) = which;
1.21      cgd       467:                SCARG(&getargs, itv) = SCARG(uap, oitv);
1.23      cgd       468:                if ((error = sys_getitimer(p, &getargs, retval)) != 0)
1.21      cgd       469:                        return (error);
                    470:        }
1.1       cgd       471:        if (itvp == 0)
                    472:                return (0);
                    473:        if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
                    474:                return (EINVAL);
                    475:        s = splclock();
1.30      mycroft   476:        if (which == ITIMER_REAL) {
1.7       mycroft   477:                untimeout(realitexpire, p);
1.1       cgd       478:                if (timerisset(&aitv.it_value)) {
1.14      mycroft   479:                        timeradd(&aitv.it_value, &time, &aitv.it_value);
1.7       mycroft   480:                        timeout(realitexpire, p, hzto(&aitv.it_value));
1.1       cgd       481:                }
                    482:                p->p_realtimer = aitv;
                    483:        } else
1.30      mycroft   484:                p->p_stats->p_timer[which] = aitv;
1.1       cgd       485:        splx(s);
                    486:        return (0);
                    487: }
                    488:
                    489: /*
                    490:  * Real interval timer expired:
                    491:  * send process whose timer expired an alarm signal.
                    492:  * If time is not set up to reload, then just return.
                    493:  * Else compute next time timer should go off which is > current time.
                    494:  * This is where delay in processing this timeout causes multiple
                    495:  * SIGALRM calls to be compressed into one.
                    496:  */
1.3       andrew    497: void
1.6       cgd       498: realitexpire(arg)
                    499:        void *arg;
                    500: {
1.1       cgd       501:        register struct proc *p;
                    502:        int s;
                    503:
1.6       cgd       504:        p = (struct proc *)arg;
1.1       cgd       505:        psignal(p, SIGALRM);
                    506:        if (!timerisset(&p->p_realtimer.it_interval)) {
                    507:                timerclear(&p->p_realtimer.it_value);
                    508:                return;
                    509:        }
                    510:        for (;;) {
                    511:                s = splclock();
1.14      mycroft   512:                timeradd(&p->p_realtimer.it_value,
                    513:                    &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
1.1       cgd       514:                if (timercmp(&p->p_realtimer.it_value, &time, >)) {
1.7       mycroft   515:                        timeout(realitexpire, p,
1.1       cgd       516:                            hzto(&p->p_realtimer.it_value));
                    517:                        splx(s);
                    518:                        return;
                    519:                }
                    520:                splx(s);
                    521:        }
                    522: }
                    523:
                    524: /*
                    525:  * Check that a proposed value to load into the .it_value or
                    526:  * .it_interval part of an interval timer is acceptable, and
                    527:  * fix it to have at least minimal value (i.e. if it is less
                    528:  * than the resolution of the clock, round it up.)
                    529:  */
1.3       andrew    530: int
1.1       cgd       531: itimerfix(tv)
                    532:        struct timeval *tv;
                    533: {
                    534:
                    535:        if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
                    536:            tv->tv_usec < 0 || tv->tv_usec >= 1000000)
                    537:                return (EINVAL);
                    538:        if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
                    539:                tv->tv_usec = tick;
                    540:        return (0);
                    541: }
                    542:
                    543: /*
                    544:  * Decrement an interval timer by a specified number
                    545:  * of microseconds, which must be less than a second,
                    546:  * i.e. < 1000000.  If the timer expires, then reload
                    547:  * it.  In this case, carry over (usec - old value) to
1.8       cgd       548:  * reduce the value reloaded into the timer so that
1.1       cgd       549:  * the timer does not drift.  This routine assumes
                    550:  * that it is called in a context where the timers
                    551:  * on which it is operating cannot change in value.
                    552:  */
1.3       andrew    553: int
1.1       cgd       554: itimerdecr(itp, usec)
                    555:        register struct itimerval *itp;
                    556:        int usec;
                    557: {
                    558:
                    559:        if (itp->it_value.tv_usec < usec) {
                    560:                if (itp->it_value.tv_sec == 0) {
                    561:                        /* expired, and already in next interval */
                    562:                        usec -= itp->it_value.tv_usec;
                    563:                        goto expire;
                    564:                }
                    565:                itp->it_value.tv_usec += 1000000;
                    566:                itp->it_value.tv_sec--;
                    567:        }
                    568:        itp->it_value.tv_usec -= usec;
                    569:        usec = 0;
                    570:        if (timerisset(&itp->it_value))
                    571:                return (1);
                    572:        /* expired, exactly at end of interval */
                    573: expire:
                    574:        if (timerisset(&itp->it_interval)) {
                    575:                itp->it_value = itp->it_interval;
                    576:                itp->it_value.tv_usec -= usec;
                    577:                if (itp->it_value.tv_usec < 0) {
                    578:                        itp->it_value.tv_usec += 1000000;
                    579:                        itp->it_value.tv_sec--;
                    580:                }
                    581:        } else
                    582:                itp->it_value.tv_usec = 0;              /* sec is already 0 */
                    583:        return (0);
                    584: }

CVSweb <webmaster@jp.NetBSD.org>