[BACK]Return to kern_clock.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_clock.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: kern_clock.c,v 1.64 2007/05/16 17:27:30 art Exp $     */
                      2: /*     $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $   */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1982, 1986, 1991, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  * (c) UNIX System Laboratories, Inc.
                      8:  * All or some portions of this file are derived from material licensed
                      9:  * to the University of California by American Telephone and Telegraph
                     10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     11:  * the permission of UNIX System Laboratories, Inc.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  *     @(#)kern_clock.c        8.5 (Berkeley) 1/21/94
                     38:  */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/dkstat.h>
                     43: #include <sys/timeout.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/limits.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/user.h>
                     48: #include <sys/resourcevar.h>
                     49: #include <sys/signalvar.h>
                     50: #include <uvm/uvm_extern.h>
                     51: #include <sys/sysctl.h>
                     52: #include <sys/sched.h>
                     53: #ifdef __HAVE_TIMECOUNTER
                     54: #include <sys/timetc.h>
                     55: #endif
                     56:
                     57: #include <machine/cpu.h>
                     58:
                     59: #ifdef GPROF
                     60: #include <sys/gmon.h>
                     61: #endif
                     62:
                     63: /*
                     64:  * Clock handling routines.
                     65:  *
                     66:  * This code is written to operate with two timers that run independently of
                     67:  * each other.  The main clock, running hz times per second, is used to keep
                     68:  * track of real time.  The second timer handles kernel and user profiling,
                     69:  * and does resource use estimation.  If the second timer is programmable,
                     70:  * it is randomized to avoid aliasing between the two clocks.  For example,
                     71:  * the randomization prevents an adversary from always giving up the cpu
                     72:  * just before its quantum expires.  Otherwise, it would never accumulate
                     73:  * cpu ticks.  The mean frequency of the second timer is stathz.
                     74:  *
                     75:  * If no second timer exists, stathz will be zero; in this case we drive
                     76:  * profiling and statistics off the main clock.  This WILL NOT be accurate;
                     77:  * do not do it unless absolutely necessary.
                     78:  *
                     79:  * The statistics clock may (or may not) be run at a higher rate while
                     80:  * profiling.  This profile clock runs at profhz.  We require that profhz
                     81:  * be an integral multiple of stathz.
                     82:  *
                     83:  * If the statistics clock is running fast, it must be divided by the ratio
                     84:  * profhz/stathz for statistics.  (For profiling, every tick counts.)
                     85:  */
                     86:
                     87: /*
                     88:  * Bump a timeval by a small number of usec's.
                     89:  */
                     90: #define BUMPTIME(t, usec) { \
                     91:        volatile struct timeval *tp = (t); \
                     92:        long us; \
                     93:  \
                     94:        tp->tv_usec = us = tp->tv_usec + (usec); \
                     95:        if (us >= 1000000) { \
                     96:                tp->tv_usec = us - 1000000; \
                     97:                tp->tv_sec++; \
                     98:        } \
                     99: }
                    100:
                    101: int    stathz;
                    102: int    schedhz;
                    103: int    profhz;
                    104: int    profprocs;
                    105: int    ticks;
                    106: static int psdiv, pscnt;               /* prof => stat divider */
                    107: int    psratio;                        /* ratio: prof / stat */
                    108:
                    109: long cp_time[CPUSTATES];
                    110:
                    111: #ifndef __HAVE_TIMECOUNTER
                    112: int    tickfix, tickfixinterval;       /* used if tick not really integral */
                    113: static int tickfixcnt;                 /* accumulated fractional error */
                    114:
                    115: volatile time_t time_second;
                    116: volatile time_t time_uptime;
                    117:
                    118: volatile struct        timeval time
                    119:        __attribute__((__aligned__(__alignof__(quad_t))));
                    120: volatile struct        timeval mono_time;
                    121: #endif
                    122:
                    123: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                    124: void   *softclock_si;
                    125: void   generic_softclock(void *);
                    126:
                    127: void
                    128: generic_softclock(void *ignore)
                    129: {
                    130:        /*
                    131:         * XXX - don't commit, just a dummy wrapper until we learn everyone
                    132:         *       deal with a changed proto for softclock().
                    133:         */
                    134:        softclock();
                    135: }
                    136: #endif
                    137:
                    138: /*
                    139:  * Initialize clock frequencies and start both clocks running.
                    140:  */
                    141: void
                    142: initclocks(void)
                    143: {
                    144:        int i;
                    145: #ifdef __HAVE_TIMECOUNTER
                    146:        extern void inittimecounter(void);
                    147: #endif
                    148:
                    149: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                    150:        softclock_si = softintr_establish(IPL_SOFTCLOCK, generic_softclock, NULL);
                    151:        if (softclock_si == NULL)
                    152:                panic("initclocks: unable to register softclock intr");
                    153: #endif
                    154:
                    155:        /*
                    156:         * Set divisors to 1 (normal case) and let the machine-specific
                    157:         * code do its bit.
                    158:         */
                    159:        psdiv = pscnt = 1;
                    160:        cpu_initclocks();
                    161:
                    162:        /*
                    163:         * Compute profhz/stathz, and fix profhz if needed.
                    164:         */
                    165:        i = stathz ? stathz : hz;
                    166:        if (profhz == 0)
                    167:                profhz = i;
                    168:        psratio = profhz / i;
                    169: #ifdef __HAVE_TIMECOUNTER
                    170:        inittimecounter();
                    171: #endif
                    172: }
                    173:
                    174: /*
                    175:  * hardclock does the accounting needed for ITIMER_PROF and ITIMER_VIRTUAL.
                    176:  * We don't want to send signals with psignal from hardclock because it makes
                    177:  * MULTIPROCESSOR locking very complicated. Instead we use a small trick
                    178:  * to send the signals safely and without blocking too many interrupts
                    179:  * while doing that (signal handling can be heavy).
                    180:  *
                    181:  * hardclock detects that the itimer has expired, and schedules a timeout
                    182:  * to deliver the signal. This works because of the following reasons:
                    183:  *  - The timeout structures can be in struct pstats because the timers
                    184:  *    can be only activated on curproc (never swapped). Swapout can
                    185:  *    only happen from a kernel thread and softclock runs before threads
                    186:  *    are scheduled.
                    187:  *  - The timeout can be scheduled with a 1 tick time because we're
                    188:  *    doing it before the timeout processing in hardclock. So it will
                    189:  *    be scheduled to run as soon as possible.
                    190:  *  - The timeout will be run in softclock which will run before we
                    191:  *    return to userland and process pending signals.
                    192:  *  - If the system is so busy that several VIRTUAL/PROF ticks are
                    193:  *    sent before softclock processing, we'll send only one signal.
                    194:  *    But if we'd send the signal from hardclock only one signal would
                    195:  *    be delivered to the user process. So userland will only see one
                    196:  *    signal anyway.
                    197:  */
                    198:
                    199: void
                    200: virttimer_trampoline(void *v)
                    201: {
                    202:        struct proc *p = v;
                    203:
                    204:        psignal(p, SIGVTALRM);
                    205: }
                    206:
                    207: void
                    208: proftimer_trampoline(void *v)
                    209: {
                    210:        struct proc *p = v;
                    211:
                    212:        psignal(p, SIGPROF);
                    213: }
                    214:
                    215: /*
                    216:  * The real-time timer, interrupting hz times per second.
                    217:  */
                    218: void
                    219: hardclock(struct clockframe *frame)
                    220: {
                    221:        struct proc *p;
                    222: #ifndef __HAVE_TIMECOUNTER
                    223:        int delta;
                    224:        extern int tickdelta;
                    225:        extern long timedelta;
                    226:        extern int64_t ntp_tick_permanent;
                    227:        extern int64_t ntp_tick_acc;
                    228: #endif
                    229:        struct cpu_info *ci = curcpu();
                    230:
                    231:        p = curproc;
                    232:        if (p && ((p->p_flag & (P_SYSTEM | P_WEXIT)) == 0)) {
                    233:                struct pstats *pstats;
                    234:
                    235:                /*
                    236:                 * Run current process's virtual and profile time, as needed.
                    237:                 */
                    238:                pstats = p->p_stats;
                    239:                if (CLKF_USERMODE(frame) &&
                    240:                    timerisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
                    241:                    itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0)
                    242:                        timeout_add(&pstats->p_virt_to, 1);
                    243:                if (timerisset(&pstats->p_timer[ITIMER_PROF].it_value) &&
                    244:                    itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0)
                    245:                        timeout_add(&pstats->p_prof_to, 1);
                    246:        }
                    247:
                    248:        /*
                    249:         * If no separate statistics clock is available, run it from here.
                    250:         */
                    251:        if (stathz == 0)
                    252:                statclock(frame);
                    253:
                    254:        if (--ci->ci_schedstate.spc_rrticks <= 0)
                    255:                roundrobin(ci);
                    256:
                    257:        /*
                    258:         * If we are not the primary CPU, we're not allowed to do
                    259:         * any more work.
                    260:         */
                    261:        if (CPU_IS_PRIMARY(ci) == 0)
                    262:                return;
                    263:
                    264: #ifndef __HAVE_TIMECOUNTER
                    265:        /*
                    266:         * Increment the time-of-day.  The increment is normally just
                    267:         * ``tick''.  If the machine is one which has a clock frequency
                    268:         * such that ``hz'' would not divide the second evenly into
                    269:         * milliseconds, a periodic adjustment must be applied.  Finally,
                    270:         * if we are still adjusting the time (see adjtime()),
                    271:         * ``tickdelta'' may also be added in.
                    272:         */
                    273:
                    274:        delta = tick;
                    275:
                    276:        if (tickfix) {
                    277:                tickfixcnt += tickfix;
                    278:                if (tickfixcnt >= tickfixinterval) {
                    279:                        delta++;
                    280:                        tickfixcnt -= tickfixinterval;
                    281:                }
                    282:        }
                    283:        /* Imprecise 4bsd adjtime() handling */
                    284:        if (timedelta != 0) {
                    285:                delta += tickdelta;
                    286:                timedelta -= tickdelta;
                    287:        }
                    288:
                    289:        /*
                    290:         * ntp_tick_permanent accumulates the clock correction each
                    291:         * tick. The unit is ns per tick shifted left 32 bits. If we have
                    292:         * accumulated more than 1us, we bump delta in the right
                    293:         * direction. Use a loop to avoid long long div; typicallly
                    294:         * the loops will be executed 0 or 1 iteration.
                    295:         */
                    296:        if (ntp_tick_permanent != 0) {
                    297:                ntp_tick_acc += ntp_tick_permanent;
                    298:                while (ntp_tick_acc >= (1000LL << 32)) {
                    299:                        delta++;
                    300:                        ntp_tick_acc -= (1000LL << 32);
                    301:                }
                    302:                while (ntp_tick_acc <= -(1000LL << 32)) {
                    303:                        delta--;
                    304:                        ntp_tick_acc += (1000LL << 32);
                    305:                }
                    306:        }
                    307:
                    308:        BUMPTIME(&time, delta);
                    309:        BUMPTIME(&mono_time, delta);
                    310:        time_second = time.tv_sec;
                    311:        time_uptime = mono_time.tv_sec;
                    312: #else
                    313:        tc_ticktock();
                    314: #endif
                    315:
                    316:        /*
                    317:         * Update real-time timeout queue.
                    318:         * Process callouts at a very low cpu priority, so we don't keep the
                    319:         * relatively high clock interrupt priority any longer than necessary.
                    320:         */
                    321:        if (timeout_hardclock_update()) {
                    322: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                    323:                softintr_schedule(softclock_si);
                    324: #else
                    325:                setsoftclock();
                    326: #endif
                    327:        }
                    328: }
                    329:
                    330: /*
                    331:  * Compute number of hz until specified time.  Used to
                    332:  * compute the second argument to timeout_add() from an absolute time.
                    333:  */
                    334: int
                    335: hzto(struct timeval *tv)
                    336: {
                    337:        struct timeval now;
                    338:        unsigned long ticks;
                    339:        long sec, usec;
                    340:
                    341:        /*
                    342:         * If the number of usecs in the whole seconds part of the time
                    343:         * difference fits in a long, then the total number of usecs will
                    344:         * fit in an unsigned long.  Compute the total and convert it to
                    345:         * ticks, rounding up and adding 1 to allow for the current tick
                    346:         * to expire.  Rounding also depends on unsigned long arithmetic
                    347:         * to avoid overflow.
                    348:         *
                    349:         * Otherwise, if the number of ticks in the whole seconds part of
                    350:         * the time difference fits in a long, then convert the parts to
                    351:         * ticks separately and add, using similar rounding methods and
                    352:         * overflow avoidance.  This method would work in the previous
                    353:         * case but it is slightly slower and assumes that hz is integral.
                    354:         *
                    355:         * Otherwise, round the time difference down to the maximum
                    356:         * representable value.
                    357:         *
                    358:         * If ints have 32 bits, then the maximum value for any timeout in
                    359:         * 10ms ticks is 248 days.
                    360:         */
                    361:        getmicrotime(&now);
                    362:        sec = tv->tv_sec - now.tv_sec;
                    363:        usec = tv->tv_usec - now.tv_usec;
                    364:        if (usec < 0) {
                    365:                sec--;
                    366:                usec += 1000000;
                    367:        }
                    368:        if (sec < 0 || (sec == 0 && usec <= 0)) {
                    369:                ticks = 0;
                    370:        } else if (sec <= LONG_MAX / 1000000)
                    371:                ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
                    372:                    / tick + 1;
                    373:        else if (sec <= LONG_MAX / hz)
                    374:                ticks = sec * hz
                    375:                    + ((unsigned long)usec + (tick - 1)) / tick + 1;
                    376:        else
                    377:                ticks = LONG_MAX;
                    378:        if (ticks > INT_MAX)
                    379:                ticks = INT_MAX;
                    380:        return ((int)ticks);
                    381: }
                    382:
                    383: /*
                    384:  * Compute number of hz in the specified amount of time.
                    385:  */
                    386: int
                    387: tvtohz(struct timeval *tv)
                    388: {
                    389:        unsigned long ticks;
                    390:        long sec, usec;
                    391:
                    392:        /*
                    393:         * If the number of usecs in the whole seconds part of the time
                    394:         * fits in a long, then the total number of usecs will
                    395:         * fit in an unsigned long.  Compute the total and convert it to
                    396:         * ticks, rounding up and adding 1 to allow for the current tick
                    397:         * to expire.  Rounding also depends on unsigned long arithmetic
                    398:         * to avoid overflow.
                    399:         *
                    400:         * Otherwise, if the number of ticks in the whole seconds part of
                    401:         * the time fits in a long, then convert the parts to
                    402:         * ticks separately and add, using similar rounding methods and
                    403:         * overflow avoidance.  This method would work in the previous
                    404:         * case but it is slightly slower and assumes that hz is integral.
                    405:         *
                    406:         * Otherwise, round the time down to the maximum
                    407:         * representable value.
                    408:         *
                    409:         * If ints have 32 bits, then the maximum value for any timeout in
                    410:         * 10ms ticks is 248 days.
                    411:         */
                    412:        sec = tv->tv_sec;
                    413:        usec = tv->tv_usec;
                    414:        if (sec < 0 || (sec == 0 && usec <= 0))
                    415:                ticks = 0;
                    416:        else if (sec <= LONG_MAX / 1000000)
                    417:                ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
                    418:                    / tick + 1;
                    419:        else if (sec <= LONG_MAX / hz)
                    420:                ticks = sec * hz
                    421:                    + ((unsigned long)usec + (tick - 1)) / tick + 1;
                    422:        else
                    423:                ticks = LONG_MAX;
                    424:        if (ticks > INT_MAX)
                    425:                ticks = INT_MAX;
                    426:        return ((int)ticks);
                    427: }
                    428:
                    429: /*
                    430:  * Start profiling on a process.
                    431:  *
                    432:  * Kernel profiling passes proc0 which never exits and hence
                    433:  * keeps the profile clock running constantly.
                    434:  */
                    435: void
                    436: startprofclock(struct proc *p)
                    437: {
                    438:        int s;
                    439:
                    440:        if ((p->p_flag & P_PROFIL) == 0) {
                    441:                atomic_setbits_int(&p->p_flag, P_PROFIL);
                    442:                if (++profprocs == 1 && stathz != 0) {
                    443:                        s = splstatclock();
                    444:                        psdiv = pscnt = psratio;
                    445:                        setstatclockrate(profhz);
                    446:                        splx(s);
                    447:                }
                    448:        }
                    449: }
                    450:
                    451: /*
                    452:  * Stop profiling on a process.
                    453:  */
                    454: void
                    455: stopprofclock(struct proc *p)
                    456: {
                    457:        int s;
                    458:
                    459:        if (p->p_flag & P_PROFIL) {
                    460:                atomic_clearbits_int(&p->p_flag, P_PROFIL);
                    461:                if (--profprocs == 0 && stathz != 0) {
                    462:                        s = splstatclock();
                    463:                        psdiv = pscnt = 1;
                    464:                        setstatclockrate(stathz);
                    465:                        splx(s);
                    466:                }
                    467:        }
                    468: }
                    469:
                    470: /*
                    471:  * Statistics clock.  Grab profile sample, and if divider reaches 0,
                    472:  * do process and kernel statistics.
                    473:  */
                    474: void
                    475: statclock(struct clockframe *frame)
                    476: {
                    477: #ifdef GPROF
                    478:        struct gmonparam *g;
                    479:        int i;
                    480: #endif
                    481:        struct cpu_info *ci = curcpu();
                    482:        struct schedstate_percpu *spc = &ci->ci_schedstate;
                    483:        struct proc *p = curproc;
                    484:
                    485:        /*
                    486:         * Notice changes in divisor frequency, and adjust clock
                    487:         * frequency accordingly.
                    488:         */
                    489:        if (spc->spc_psdiv != psdiv) {
                    490:                spc->spc_psdiv = psdiv;
                    491:                spc->spc_pscnt = psdiv;
                    492:                if (psdiv == 1) {
                    493:                        setstatclockrate(stathz);
                    494:                } else {
                    495:                        setstatclockrate(profhz);
                    496:                }
                    497:        }
                    498:
                    499:        if (CLKF_USERMODE(frame)) {
                    500:                if (p->p_flag & P_PROFIL)
                    501:                        addupc_intr(p, CLKF_PC(frame));
                    502:                if (--spc->spc_pscnt > 0)
                    503:                        return;
                    504:                /*
                    505:                 * Came from user mode; CPU was in user state.
                    506:                 * If this process is being profiled record the tick.
                    507:                 */
                    508:                p->p_uticks++;
                    509:                if (p->p_nice > NZERO)
                    510:                        spc->spc_cp_time[CP_NICE]++;
                    511:                else
                    512:                        spc->spc_cp_time[CP_USER]++;
                    513:        } else {
                    514: #ifdef GPROF
                    515:                /*
                    516:                 * Kernel statistics are just like addupc_intr, only easier.
                    517:                 */
                    518:                g = &_gmonparam;
                    519:                if (g->state == GMON_PROF_ON) {
                    520:                        i = CLKF_PC(frame) - g->lowpc;
                    521:                        if (i < g->textsize) {
                    522:                                i /= HISTFRACTION * sizeof(*g->kcount);
                    523:                                g->kcount[i]++;
                    524:                        }
                    525:                }
                    526: #endif
                    527: #if defined(PROC_PC)
                    528:                if (p != NULL && p->p_flag & P_PROFIL)
                    529:                        addupc_intr(p, PROC_PC(p));
                    530: #endif
                    531:                if (--spc->spc_pscnt > 0)
                    532:                        return;
                    533:                /*
                    534:                 * Came from kernel mode, so we were:
                    535:                 * - handling an interrupt,
                    536:                 * - doing syscall or trap work on behalf of the current
                    537:                 *   user process, or
                    538:                 * - spinning in the idle loop.
                    539:                 * Whichever it is, charge the time as appropriate.
                    540:                 * Note that we charge interrupts to the current process,
                    541:                 * regardless of whether they are ``for'' that process,
                    542:                 * so that we know how much of its real time was spent
                    543:                 * in ``non-process'' (i.e., interrupt) work.
                    544:                 */
                    545:                if (CLKF_INTR(frame)) {
                    546:                        if (p != NULL)
                    547:                                p->p_iticks++;
                    548:                        spc->spc_cp_time[CP_INTR]++;
                    549:                } else if (p != NULL) {
                    550:                        p->p_sticks++;
                    551:                        spc->spc_cp_time[CP_SYS]++;
                    552:                } else
                    553:                        spc->spc_cp_time[CP_IDLE]++;
                    554:        }
                    555:        spc->spc_pscnt = psdiv;
                    556:
                    557:        if (p != NULL) {
                    558:                p->p_cpticks++;
                    559:                /*
                    560:                 * If no schedclock is provided, call it here at ~~12-25 Hz;
                    561:                 * ~~16 Hz is best
                    562:                 */
                    563:                if (schedhz == 0) {
                    564:                        if ((++curcpu()->ci_schedstate.spc_schedticks & 3) ==
                    565:                            0)
                    566:                                schedclock(p);
                    567:                }
                    568:        }
                    569: }
                    570:
                    571: /*
                    572:  * Return information about system clocks.
                    573:  */
                    574: int
                    575: sysctl_clockrate(char *where, size_t *sizep)
                    576: {
                    577:        struct clockinfo clkinfo;
                    578:
                    579:        /*
                    580:         * Construct clockinfo structure.
                    581:         */
                    582:        clkinfo.tick = tick;
                    583:        clkinfo.tickadj = tickadj;
                    584:        clkinfo.hz = hz;
                    585:        clkinfo.profhz = profhz;
                    586:        clkinfo.stathz = stathz ? stathz : hz;
                    587:        return (sysctl_rdstruct(where, sizep, NULL, &clkinfo, sizeof(clkinfo)));
                    588: }
                    589:
                    590: #ifndef __HAVE_TIMECOUNTER
                    591: /*
                    592:  * Placeholders until everyone uses the timecounters code.
                    593:  * Won't improve anything except maybe removing a bunch of bugs in fixed code.
                    594:  */
                    595:
                    596: void
                    597: getmicrotime(struct timeval *tvp)
                    598: {
                    599:        int s;
                    600:
                    601:        s = splhigh();
                    602:        *tvp = time;
                    603:        splx(s);
                    604: }
                    605:
                    606: void
                    607: nanotime(struct timespec *tsp)
                    608: {
                    609:        struct timeval tv;
                    610:
                    611:        microtime(&tv);
                    612:        TIMEVAL_TO_TIMESPEC(&tv, tsp);
                    613: }
                    614:
                    615: void
                    616: getnanotime(struct timespec *tsp)
                    617: {
                    618:        struct timeval tv;
                    619:
                    620:        getmicrotime(&tv);
                    621:        TIMEVAL_TO_TIMESPEC(&tv, tsp);
                    622: }
                    623:
                    624: void
                    625: nanouptime(struct timespec *tsp)
                    626: {
                    627:        struct timeval tv;
                    628:
                    629:        microuptime(&tv);
                    630:        TIMEVAL_TO_TIMESPEC(&tv, tsp);
                    631: }
                    632:
                    633:
                    634: void
                    635: getnanouptime(struct timespec *tsp)
                    636: {
                    637:        struct timeval tv;
                    638:
                    639:        getmicrouptime(&tv);
                    640:        TIMEVAL_TO_TIMESPEC(&tv, tsp);
                    641: }
                    642:
                    643: void
                    644: microuptime(struct timeval *tvp)
                    645: {
                    646:        struct timeval tv;
                    647:
                    648:        microtime(&tv);
                    649:        timersub(&tv, &boottime, tvp);
                    650: }
                    651:
                    652: void
                    653: getmicrouptime(struct timeval *tvp)
                    654: {
                    655:        int s;
                    656:
                    657:        s = splhigh();
                    658:        *tvp = mono_time;
                    659:        splx(s);
                    660: }
                    661: #endif /* __HAVE_TIMECOUNTER */

CVSweb