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

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

CVSweb <webmaster@jp.NetBSD.org>