Annotation of Net2/kern/kern_time.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.2 ! root       33:  *     from: @(#)kern_time.c   7.15 (Berkeley) 3/17/91
        !            34:  *     kern_time.c,v 1.4 1993/07/13 22:13:28 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
1.1.1.2 ! root       38: #include "systm.h"
1.1       root       39: #include "resourcevar.h"
                     40: #include "kernel.h"
                     41: #include "proc.h"
                     42: 
                     43: #include "machine/cpu.h"
                     44: 
                     45: /* 
                     46:  * Time of day and interval timer support.
                     47:  *
                     48:  * These routines provide the kernel entry points to get and set
                     49:  * the time-of-day and per-process interval timers.  Subroutines
                     50:  * here provide support for adding and subtracting timeval structures
                     51:  * and decrementing interval timers, optionally reloading the interval
                     52:  * timers when they expire.
                     53:  */
                     54: 
1.1.1.2 ! root       55: struct gettimeofday_args {
        !            56:        struct  timeval *tp;
        !            57:        struct  timezone *tzp;
        !            58: };
        !            59: 
1.1       root       60: /* ARGSUSED */
1.1.1.2 ! root       61: int
1.1       root       62: gettimeofday(p, uap, retval)
                     63:        struct proc *p;
1.1.1.2 ! root       64:        register struct gettimeofday_args *uap;
1.1       root       65:        int *retval;
                     66: {
                     67:        struct timeval atv;
                     68:        int error = 0;
                     69: 
                     70:        if (uap->tp) {
                     71:                microtime(&atv);
                     72:                if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
                     73:                    sizeof (atv)))
                     74:                        return (error);
                     75:        }
                     76:        if (uap->tzp)
                     77:                error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
                     78:                    sizeof (tz));
                     79:        return (error);
                     80: }
                     81: 
1.1.1.2 ! root       82: struct settimeofday_args {
        !            83:        struct  timeval *tv;
        !            84:        struct  timezone *tzp;
        !            85: };
        !            86: 
1.1       root       87: /* ARGSUSED */
1.1.1.2 ! root       88: int
1.1       root       89: settimeofday(p, uap, retval)
                     90:        struct proc *p;
1.1.1.2 ! root       91:        struct settimeofday_args *uap;
1.1       root       92:        int *retval;
                     93: {
                     94:        struct timeval atv;
                     95:        struct timezone atz;
                     96:        int error, s;
                     97: 
                     98:        if (error = suser(p->p_ucred, &p->p_acflag))
                     99:                return (error);
                    100:        if (uap->tv) {
                    101:                if (error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    102:                    sizeof (struct timeval)))
                    103:                        return (error);
                    104:                /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
                    105:                boottime.tv_sec += atv.tv_sec - time.tv_sec;
                    106:                s = splhigh(); time = atv; splx(s);
                    107:                resettodr();
                    108:        }
                    109:        if (uap->tzp && (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
                    110:            sizeof (atz))) == 0)
                    111:                tz = atz;
                    112:        return (error);
                    113: }
                    114: 
                    115: extern int tickadj;                    /* "standard" clock skew, us./tick */
                    116: int    tickdelta;                      /* current clock skew, us. per tick */
                    117: long   timedelta;                      /* unapplied time correction, us. */
                    118: long   bigadj = 1000000;               /* use 10x skew above bigadj us. */
                    119: 
1.1.1.2 ! root      120: struct adjtime_args {
        !           121:        struct timeval *delta;
        !           122:        struct timeval *olddelta;
        !           123: };
        !           124: 
1.1       root      125: /* ARGSUSED */
1.1.1.2 ! root      126: int
1.1       root      127: adjtime(p, uap, retval)
                    128:        struct proc *p;
1.1.1.2 ! root      129:        register struct adjtime_args *uap;
1.1       root      130:        int *retval;
                    131: {
                    132:        struct timeval atv, oatv;
                    133:        register long ndelta;
                    134:        int s, error;
                    135: 
                    136:        if (error = suser(p->p_ucred, &p->p_acflag))
                    137:                return (error);
                    138:        if (error =
                    139:            copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof (struct timeval)))
                    140:                return (error);
                    141:        ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
                    142:        if (timedelta == 0)
                    143:                if (ndelta > bigadj)
                    144:                        tickdelta = 10 * tickadj;
                    145:                else
                    146:                        tickdelta = tickadj;
                    147:        if (ndelta % tickdelta)
                    148:                ndelta = ndelta / tickadj * tickadj;
                    149: 
                    150:        s = splclock();
                    151:        if (uap->olddelta) {
                    152:                oatv.tv_sec = timedelta / 1000000;
                    153:                oatv.tv_usec = timedelta % 1000000;
                    154:        }
                    155:        timedelta = ndelta;
                    156:        splx(s);
                    157: 
                    158:        if (uap->olddelta)
                    159:                (void) copyout((caddr_t)&oatv, (caddr_t)uap->olddelta,
                    160:                        sizeof (struct timeval));
                    161:        return (0);
                    162: }
                    163: 
                    164: /*
                    165:  * Get value of an interval timer.  The process virtual and
                    166:  * profiling virtual time timers are kept in the p_stats area, since
                    167:  * they can be swapped out.  These are kept internally in the
                    168:  * way they are specified externally: in time until they expire.
                    169:  *
                    170:  * The real time interval timer is kept in the process table slot
                    171:  * for the process, and its value (it_value) is kept as an
                    172:  * absolute time rather than as a delta, so that it is easy to keep
                    173:  * periodic real-time signals from drifting.
                    174:  *
                    175:  * Virtual time timers are processed in the hardclock() routine of
                    176:  * kern_clock.c.  The real time timer is processed by a timeout
                    177:  * routine, called from the softclock() routine.  Since a callout
                    178:  * may be delayed in real time due to interrupt processing in the system,
                    179:  * it is possible for the real time timeout routine (realitexpire, given below),
                    180:  * to be delayed in real time past when it is supposed to occur.  It
                    181:  * does not suffice, therefore, to reload the real timer .it_value from the
                    182:  * real time timers .it_interval.  Rather, we compute the next time in
                    183:  * absolute time the timer should go off.
                    184:  */
1.1.1.2 ! root      185: 
        !           186: struct getitimer_args {
        !           187:        u_int   which;
        !           188:        struct  itimerval *itv;
        !           189: };
        !           190: 
1.1       root      191: /* ARGSUSED */
1.1.1.2 ! root      192: int
1.1       root      193: getitimer(p, uap, retval)
                    194:        struct proc *p;
1.1.1.2 ! root      195:        register struct getitimer_args *uap;
1.1       root      196:        int *retval;
                    197: {
                    198:        struct itimerval aitv;
                    199:        int s;
                    200: 
                    201:        if (uap->which > ITIMER_PROF)
                    202:                return (EINVAL);
                    203:        s = splclock();
                    204:        if (uap->which == ITIMER_REAL) {
                    205:                /*
                    206:                 * Convert from absoulte to relative time in .it_value
                    207:                 * part of real time timer.  If time for real time timer
                    208:                 * has passed return 0, else return difference between
                    209:                 * current time and time for the timer to go off.
                    210:                 */
                    211:                aitv = p->p_realtimer;
                    212:                if (timerisset(&aitv.it_value))
                    213:                        if (timercmp(&aitv.it_value, &time, <))
                    214:                                timerclear(&aitv.it_value);
                    215:                        else
                    216:                                timevalsub(&aitv.it_value, &time);
                    217:        } else
                    218:                aitv = p->p_stats->p_timer[uap->which];
                    219:        splx(s);
                    220:        return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
                    221:            sizeof (struct itimerval)));
                    222: }
                    223: 
1.1.1.2 ! root      224: struct setitimer_args {
        !           225:        u_int   which;
        !           226:        struct  itimerval *itv, *oitv;
        !           227: };
        !           228: 
1.1       root      229: /* ARGSUSED */
1.1.1.2 ! root      230: int
1.1       root      231: setitimer(p, uap, retval)
                    232:        struct proc *p;
1.1.1.2 ! root      233:        register struct setitimer_args *uap;
1.1       root      234:        int *retval;
                    235: {
                    236:        struct itimerval aitv;
                    237:        register struct itimerval *itvp;
                    238:        int s, error;
                    239: 
                    240:        if (uap->which > ITIMER_PROF)
                    241:                return (EINVAL);
                    242:        itvp = uap->itv;
                    243:        if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
                    244:            sizeof(struct itimerval))))
                    245:                return (error);
                    246:        if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval)))
                    247:                return (error);
                    248:        if (itvp == 0)
                    249:                return (0);
                    250:        if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
                    251:                return (EINVAL);
                    252:        s = splclock();
                    253:        if (uap->which == ITIMER_REAL) {
1.1.1.2 ! root      254:                untimeout((timeout_t)realitexpire, (caddr_t)p);
1.1       root      255:                if (timerisset(&aitv.it_value)) {
                    256:                        timevaladd(&aitv.it_value, &time);
1.1.1.2 ! root      257:                        timeout((timeout_t)realitexpire, (caddr_t)p, hzto(&aitv.it_value));
1.1       root      258:                }
                    259:                p->p_realtimer = aitv;
                    260:        } else
                    261:                p->p_stats->p_timer[uap->which] = aitv;
                    262:        splx(s);
                    263:        return (0);
                    264: }
                    265: 
                    266: /*
                    267:  * Real interval timer expired:
                    268:  * send process whose timer expired an alarm signal.
                    269:  * If time is not set up to reload, then just return.
                    270:  * Else compute next time timer should go off which is > current time.
                    271:  * This is where delay in processing this timeout causes multiple
                    272:  * SIGALRM calls to be compressed into one.
                    273:  */
1.1.1.2 ! root      274: void
1.1       root      275: realitexpire(p)
                    276:        register struct proc *p;
                    277: {
                    278:        int s;
                    279: 
                    280:        psignal(p, SIGALRM);
                    281:        if (!timerisset(&p->p_realtimer.it_interval)) {
                    282:                timerclear(&p->p_realtimer.it_value);
                    283:                return;
                    284:        }
                    285:        for (;;) {
                    286:                s = splclock();
                    287:                timevaladd(&p->p_realtimer.it_value,
                    288:                    &p->p_realtimer.it_interval);
                    289:                if (timercmp(&p->p_realtimer.it_value, &time, >)) {
1.1.1.2 ! root      290:                        timeout((timeout_t)realitexpire, (caddr_t)p,
1.1       root      291:                            hzto(&p->p_realtimer.it_value));
                    292:                        splx(s);
                    293:                        return;
                    294:                }
                    295:                splx(s);
                    296:        }
                    297: }
                    298: 
                    299: /*
                    300:  * Check that a proposed value to load into the .it_value or
                    301:  * .it_interval part of an interval timer is acceptable, and
                    302:  * fix it to have at least minimal value (i.e. if it is less
                    303:  * than the resolution of the clock, round it up.)
                    304:  */
1.1.1.2 ! root      305: int
1.1       root      306: itimerfix(tv)
                    307:        struct timeval *tv;
                    308: {
                    309: 
                    310:        if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
                    311:            tv->tv_usec < 0 || tv->tv_usec >= 1000000)
                    312:                return (EINVAL);
                    313:        if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
                    314:                tv->tv_usec = tick;
                    315:        return (0);
                    316: }
                    317: 
                    318: /*
                    319:  * Decrement an interval timer by a specified number
                    320:  * of microseconds, which must be less than a second,
                    321:  * i.e. < 1000000.  If the timer expires, then reload
                    322:  * it.  In this case, carry over (usec - old value) to
                    323:  * reducint the value reloaded into the timer so that
                    324:  * the timer does not drift.  This routine assumes
                    325:  * that it is called in a context where the timers
                    326:  * on which it is operating cannot change in value.
                    327:  */
1.1.1.2 ! root      328: int
1.1       root      329: itimerdecr(itp, usec)
                    330:        register struct itimerval *itp;
                    331:        int usec;
                    332: {
                    333: 
                    334:        if (itp->it_value.tv_usec < usec) {
                    335:                if (itp->it_value.tv_sec == 0) {
                    336:                        /* expired, and already in next interval */
                    337:                        usec -= itp->it_value.tv_usec;
                    338:                        goto expire;
                    339:                }
                    340:                itp->it_value.tv_usec += 1000000;
                    341:                itp->it_value.tv_sec--;
                    342:        }
                    343:        itp->it_value.tv_usec -= usec;
                    344:        usec = 0;
                    345:        if (timerisset(&itp->it_value))
                    346:                return (1);
                    347:        /* expired, exactly at end of interval */
                    348: expire:
                    349:        if (timerisset(&itp->it_interval)) {
                    350:                itp->it_value = itp->it_interval;
                    351:                itp->it_value.tv_usec -= usec;
                    352:                if (itp->it_value.tv_usec < 0) {
                    353:                        itp->it_value.tv_usec += 1000000;
                    354:                        itp->it_value.tv_sec--;
                    355:                }
                    356:        } else
                    357:                itp->it_value.tv_usec = 0;              /* sec is already 0 */
                    358:        return (0);
                    359: }
                    360: 
                    361: /*
                    362:  * Add and subtract routines for timevals.
                    363:  * N.B.: subtract routine doesn't deal with
                    364:  * results which are before the beginning,
                    365:  * it just gets very confused in this case.
                    366:  * Caveat emptor.
                    367:  */
1.1.1.2 ! root      368: void
1.1       root      369: timevaladd(t1, t2)
                    370:        struct timeval *t1, *t2;
                    371: {
                    372: 
                    373:        t1->tv_sec += t2->tv_sec;
                    374:        t1->tv_usec += t2->tv_usec;
                    375:        timevalfix(t1);
                    376: }
                    377: 
1.1.1.2 ! root      378: void
1.1       root      379: timevalsub(t1, t2)
                    380:        struct timeval *t1, *t2;
                    381: {
                    382: 
                    383:        t1->tv_sec -= t2->tv_sec;
                    384:        t1->tv_usec -= t2->tv_usec;
                    385:        timevalfix(t1);
                    386: }
                    387: 
1.1.1.2 ! root      388: void
1.1       root      389: timevalfix(t1)
                    390:        struct timeval *t1;
                    391: {
                    392: 
                    393:        if (t1->tv_usec < 0) {
                    394:                t1->tv_sec--;
                    395:                t1->tv_usec += 1000000;
                    396:        }
                    397:        if (t1->tv_usec >= 1000000) {
                    398:                t1->tv_sec++;
                    399:                t1->tv_usec -= 1000000;
                    400:        }
                    401: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.