Annotation of 43BSDReno/sys/kern/kern_time.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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