[BACK]Return to gmon.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gmon

Annotation of src/lib/libc/gmon/gmon.c, Revision 1.29

1.29    ! christos    1: /*     $NetBSD: gmon.c,v 1.28 2006/10/04 21:23:56 christos Exp $       */
1.22      thorpej     2:
                      3: /*
                      4:  * Copyright (c) 2003, 2004 Wasabi Systems, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Nathan J. Williams for Wasabi Systems, Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed for the NetBSD Project by
                     20:  *     Wasabi Systems, Inc.
                     21:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific prior
                     23:  *    written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
1.3       cgd        37:
1.1       cgd        38: /*-
                     39:  * Copyright (c) 1983, 1992, 1993
                     40:  *     The Regents of the University of California.  All rights reserved.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
1.21      agc        50:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        51:  *    may be used to endorse or promote products derived from this software
                     52:  *    without specific prior written permission.
                     53:  *
                     54:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     55:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     56:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     57:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     58:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     59:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     60:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     61:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     62:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     63:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     64:  * SUCH DAMAGE.
                     65:  */
                     66:
1.10      christos   67: #include <sys/cdefs.h>
1.1       cgd        68: #if !defined(lint) && defined(LIBC_SCCS)
1.3       cgd        69: #if 0
                     70: static char sccsid[] = "@(#)gmon.c     8.1 (Berkeley) 6/4/93";
                     71: #else
1.29    ! christos   72: __RCSID("$NetBSD: gmon.c,v 1.28 2006/10/04 21:23:56 christos Exp $");
1.3       cgd        73: #endif
1.1       cgd        74: #endif
                     75:
1.10      christos   76: #include "namespace.h"
1.1       cgd        77: #include <sys/param.h>
                     78: #include <sys/time.h>
                     79: #include <sys/gmon.h>
1.22      thorpej    80: #include <sys/mman.h>
1.1       cgd        81: #include <sys/sysctl.h>
                     82:
                     83: #include <stdio.h>
1.5       jtc        84: #include <stdlib.h>
1.22      thorpej    85: #include <string.h>
1.1       cgd        86: #include <fcntl.h>
1.5       jtc        87: #include <limits.h>
1.1       cgd        88: #include <unistd.h>
1.10      christos   89: #include <err.h>
1.15      kleink     90: #include "extern.h"
1.22      thorpej    91: #include "reentrant.h"
1.1       cgd        92:
1.29    ! christos   93: struct gmonparam _gmonparam = { .state = GMON_PROF_OFF };
1.1       cgd        94:
1.22      thorpej    95: #ifdef _REENTRANT
                     96: struct gmonparam *_gmonfree;
                     97: struct gmonparam *_gmoninuse;
                     98: mutex_t _gmonlock = MUTEX_INITIALIZER;
                     99: thread_key_t _gmonkey;
                    100: struct gmonparam _gmondummy;
                    101: #endif
                    102:
1.14      christos  103: static u_int   s_scale;
1.1       cgd       104: /* see profil(2) where this is describe (incorrectly) */
                    105: #define                SCALE_1_TO_1    0x10000L
                    106:
1.12      kleink    107: #define ERR(s) write(STDERR_FILENO, s, sizeof(s))
1.1       cgd       108:
                    109: void   moncontrol __P((int));
1.10      christos  110: void   monstartup __P((u_long, u_long));
                    111: void   _mcleanup __P((void));
1.1       cgd       112: static int hertz __P((void));
                    113:
1.22      thorpej   114: #ifdef _REENTRANT
                    115: static void _m_gmon_destructor(void *);
                    116: struct gmonparam *_m_gmon_alloc(void)  __attribute__((__no_instrument_function__));
                    117: static void _m_gmon_merge(void);
                    118: static void _m_gmon_merge_two(struct gmonparam *, struct gmonparam *);
                    119: #endif
1.16      christos  120:
1.1       cgd       121: void
                    122: monstartup(lowpc, highpc)
                    123:        u_long lowpc;
                    124:        u_long highpc;
                    125: {
1.19      thorpej   126:        u_long o;
1.1       cgd       127:        char *cp;
                    128:        struct gmonparam *p = &_gmonparam;
                    129:
                    130:        /*
                    131:         * round lowpc and highpc to multiples of the density we're using
                    132:         * so the rest of the scaling (here and in gprof) stays in ints.
                    133:         */
1.27      dogcow    134:        p->lowpc = rounddown(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
                    135:        p->highpc = roundup(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
1.1       cgd       136:        p->textsize = p->highpc - p->lowpc;
                    137:        p->kcountsize = p->textsize / HISTFRACTION;
                    138:        p->hashfraction = HASHFRACTION;
1.6       cgd       139:        p->fromssize = p->textsize / p->hashfraction;
1.1       cgd       140:        p->tolimit = p->textsize * ARCDENSITY / 100;
                    141:        if (p->tolimit < MINARCS)
                    142:                p->tolimit = MINARCS;
                    143:        else if (p->tolimit > MAXARCS)
                    144:                p->tolimit = MAXARCS;
                    145:        p->tossize = p->tolimit * sizeof(struct tostruct);
                    146:
1.16      christos  147:        cp = sbrk((intptr_t)(p->kcountsize + p->fromssize + p->tossize));
1.1       cgd       148:        if (cp == (char *)-1) {
                    149:                ERR("monstartup: out of memory\n");
                    150:                return;
                    151:        }
                    152: #ifdef notdef
1.13      perry     153:        memset(cp, 0, p->kcountsize + p->fromssize + p->tossize);
1.1       cgd       154: #endif
1.14      christos  155:        p->tos = (struct tostruct *)(void *)cp;
                    156:        cp += (size_t)p->tossize;
                    157:        p->kcount = (u_short *)(void *)cp;
                    158:        cp += (size_t)p->kcountsize;
                    159:        p->froms = (u_short *)(void *)cp;
1.1       cgd       160:
1.16      christos  161:        __minbrk = sbrk((intptr_t)0);
1.1       cgd       162:        p->tos[0].link = 0;
                    163:
                    164:        o = p->highpc - p->lowpc;
                    165:        if (p->kcountsize < o) {
1.2       cgd       166: #ifndef notdef
1.1       cgd       167:                s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
                    168: #else /* avoid floating point */
1.19      thorpej   169:                u_long quot = o / p->kcountsize;
1.1       cgd       170:
                    171:                if (quot >= 0x10000)
                    172:                        s_scale = 1;
                    173:                else if (quot >= 0x100)
                    174:                        s_scale = 0x10000 / quot;
                    175:                else if (o >= 0x800000)
                    176:                        s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
                    177:                else
                    178:                        s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
                    179: #endif
                    180:        } else
                    181:                s_scale = SCALE_1_TO_1;
                    182:
1.22      thorpej   183: #ifdef _REENTRANT
                    184:        _gmondummy.state = GMON_PROF_BUSY;
                    185:        thr_keycreate(&_gmonkey, _m_gmon_destructor);
                    186: #endif
1.1       cgd       187:        moncontrol(1);
                    188: }
                    189:
1.22      thorpej   190: #ifdef _REENTRANT
                    191: static void
                    192: _m_gmon_destructor(void *arg)
                    193: {
                    194:        struct gmonparam *p = arg, *q, **prev;
                    195:
                    196:        if (p == &_gmondummy)
                    197:                return;
                    198:
                    199:        thr_setspecific(_gmonkey, &_gmondummy);
                    200:
                    201:        mutex_lock(&_gmonlock);
                    202:        /* XXX eww, linear list traversal. */
                    203:        for (q = _gmoninuse, prev = &_gmoninuse;
                    204:             q != NULL;
1.26      mrg       205:             prev = (struct gmonparam **)(void *)&q->kcount,    /* XXX */
1.22      thorpej   206:                 q = (struct gmonparam *)(void *)q->kcount) {
                    207:                if (q == p)
                    208:                        *prev = (struct gmonparam *)(void *)q->kcount;
                    209:        }
                    210:        p->kcount = (u_short *)(void *)_gmonfree;
                    211:        _gmonfree = p;
                    212:        mutex_unlock(&_gmonlock);
                    213:
                    214:        thr_setspecific(_gmonkey, NULL);
                    215: }
                    216:
                    217: struct gmonparam *
                    218: _m_gmon_alloc(void)
                    219: {
                    220:        struct gmonparam *p;
                    221:        char *cp;
                    222:
                    223:        mutex_lock(&_gmonlock);
                    224:        if (_gmonfree != NULL) {
                    225:                p = _gmonfree;
                    226:                _gmonfree = (struct gmonparam *)(void *)p->kcount;
                    227:                p->kcount = (u_short *)(void *)_gmoninuse;
                    228:                _gmoninuse = p;
                    229:        } else {
                    230:                mutex_unlock(&_gmonlock);
                    231:                cp = mmap(NULL,
                    232:                    (size_t)(sizeof (struct gmonparam) +
                    233:                        _gmonparam.fromssize + _gmonparam.tossize),
                    234:                    PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0LL);
                    235:                p = (void *)cp;
                    236:                *p = _gmonparam;
                    237:                p->kcount = NULL;
                    238:                cp += sizeof (struct gmonparam);
                    239:                memset(cp, 0, (size_t)(p->fromssize + p->tossize));
                    240:                p->froms = (u_short *)(void *)cp;
                    241:                p->tos = (struct tostruct *)(void *)(cp + p->fromssize);
                    242:                mutex_lock(&_gmonlock);
                    243:                p->kcount = (u_short *)(void *)_gmoninuse;
                    244:                _gmoninuse = p;
                    245:        }
                    246:        mutex_unlock(&_gmonlock);
                    247:        thr_setspecific(_gmonkey, p);
                    248:
                    249:        return p;
                    250: }
                    251:
                    252: static void
                    253: _m_gmon_merge_two(struct gmonparam *p, struct gmonparam *q)
                    254: {
                    255:        u_long fromindex;
                    256:        u_short *frompcindex, qtoindex, toindex;
                    257:        u_long selfpc;
                    258:        int endfrom;
                    259:        long count;
                    260:        struct tostruct *top;
                    261:
                    262:        endfrom = (int)(q->fromssize / sizeof(*q->froms));
                    263:        for (fromindex = 0; fromindex < endfrom; fromindex++) {
                    264:                if (q->froms[fromindex] == 0)
                    265:                        continue;
                    266:                for (qtoindex = q->froms[fromindex]; qtoindex != 0;
                    267:                     qtoindex = q->tos[qtoindex].link) {
                    268:                        selfpc = q->tos[qtoindex].selfpc;
                    269:                        count = q->tos[qtoindex].count;
                    270:                        /* cribbed from mcount */
                    271:                        frompcindex = &p->froms[fromindex];
                    272:                        toindex = *frompcindex;
                    273:                        if (toindex == 0) {
                    274:                                /*
                    275:                                 *      first time traversing this arc
                    276:                                 */
                    277:                                toindex = ++p->tos[0].link;
                    278:                                if (toindex >= p->tolimit)
                    279:                                        /* halt further profiling */
                    280:                                        goto overflow;
                    281:
                    282:                                *frompcindex = (u_short)toindex;
                    283:                                top = &p->tos[(size_t)toindex];
                    284:                                top->selfpc = selfpc;
                    285:                                top->count = count;
                    286:                                top->link = 0;
                    287:                                goto done;
                    288:                        }
                    289:                        top = &p->tos[(size_t)toindex];
                    290:                        if (top->selfpc == selfpc) {
                    291:                                /*
                    292:                                 * arc at front of chain; usual case.
                    293:                                 */
                    294:                                top->count+= count;
                    295:                                goto done;
                    296:                        }
                    297:                        /*
                    298:                         * have to go looking down chain for it.
                    299:                         * top points to what we are looking at,
                    300:                         * we know it is not at the head of the chain.
                    301:                         */
                    302:                        for (; /* goto done */; ) {
                    303:                                if (top->link == 0) {
                    304:                                        /*
                    305:                                         * top is end of the chain and
                    306:                                         * none of the chain had
                    307:                                         * top->selfpc == selfpc.  so
                    308:                                         * we allocate a new tostruct
                    309:                                         * and link it to the head of
                    310:                                         * the chain.
                    311:                                         */
                    312:                                        toindex = ++p->tos[0].link;
                    313:                                        if (toindex >= p->tolimit)
                    314:                                                goto overflow;
                    315:
                    316:                                        top = &p->tos[(size_t)toindex];
                    317:                                        top->selfpc = selfpc;
                    318:                                        top->count = count;
                    319:                                        top->link = *frompcindex;
                    320:                                        *frompcindex = (u_short)toindex;
                    321:                                        goto done;
                    322:                                }
                    323:                                /*
                    324:                                 * otherwise, check the next arc on the chain.
                    325:                                 */
                    326:                                top = &p->tos[top->link];
                    327:                                if (top->selfpc == selfpc) {
                    328:                                        /*
                    329:                                         * there it is.
                    330:                                         * add to its count.
                    331:                                         */
                    332:                                        top->count += count;
                    333:                                        goto done;
                    334:                                }
                    335:
                    336:                        }
                    337:
                    338:                done: ;
                    339:                }
                    340:
                    341:        }
                    342:  overflow: ;
                    343:
                    344: }
                    345:
                    346: static void
                    347: _m_gmon_merge(void)
                    348: {
                    349:        struct gmonparam *q;
                    350:
                    351:        mutex_lock(&_gmonlock);
                    352:
                    353:        for (q = _gmonfree; q != NULL; q = (struct gmonparam *)(void *)q->kcount)
                    354:                _m_gmon_merge_two(&_gmonparam, q);
                    355:
                    356:        for (q = _gmoninuse; q != NULL; q = (struct gmonparam *)(void *)q->kcount) {
                    357:                q->state = GMON_PROF_OFF;
                    358:                _m_gmon_merge_two(&_gmonparam, q);
                    359:        }
                    360:
                    361:        mutex_unlock(&_gmonlock);
                    362: }
                    363: #endif
                    364:
1.1       cgd       365: void
                    366: _mcleanup()
                    367: {
                    368:        int fd;
                    369:        int fromindex;
                    370:        int endfrom;
                    371:        u_long frompc;
                    372:        int toindex;
                    373:        struct rawarc rawarc;
                    374:        struct gmonparam *p = &_gmonparam;
                    375:        struct gmonhdr gmonhdr, *hdr;
                    376:        struct clockinfo clockinfo;
                    377:        int mib[2];
                    378:        size_t size;
1.5       jtc       379:        char *profdir;
1.23      christos  380:        const char *proffile;
1.5       jtc       381:        char  buf[PATH_MAX];
1.1       cgd       382: #ifdef DEBUG
1.25      christos  383:        int logfd, len;
1.9       mrg       384:        char buf2[200];
1.1       cgd       385: #endif
1.18      christos  386:
                    387:        /*
                    388:         * We disallow writing to the profiling file, if we are a
                    389:         * set{u,g}id program and our effective {u,g}id does not match
                    390:         * our real one.
                    391:         */
                    392:        if (issetugid() && (geteuid() != getuid() || getegid() != getgid())) {
                    393:                warnx("mcount: Profiling of set{u,g}id binaries is not"
                    394:                    " allowed");
                    395:                return;
                    396:        }
1.1       cgd       397:
                    398:        if (p->state == GMON_PROF_ERROR)
                    399:                ERR("_mcleanup: tos overflow\n");
                    400:
                    401:        size = sizeof(clockinfo);
                    402:        mib[0] = CTL_KERN;
                    403:        mib[1] = KERN_CLOCKRATE;
                    404:        if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) < 0) {
                    405:                /*
                    406:                 * Best guess
                    407:                 */
                    408:                clockinfo.profhz = hertz();
                    409:        } else if (clockinfo.profhz == 0) {
                    410:                if (clockinfo.hz != 0)
                    411:                        clockinfo.profhz = clockinfo.hz;
                    412:                else
                    413:                        clockinfo.profhz = hertz();
                    414:        }
                    415:
                    416:        moncontrol(0);
1.5       jtc       417:
                    418:        if ((profdir = getenv("PROFDIR")) != NULL) {
                    419:                /* If PROFDIR contains a null value, no profiling
                    420:                   output is produced */
1.20      dsl       421:                if (*profdir == '\0')
                    422:                        return;
                    423:
                    424:                if (snprintf(buf, sizeof buf, "%s/%d.%s",
                    425:                            profdir, getpid(), getprogname()) >= sizeof buf) {
                    426:                        warnx("_mcleanup: internal buffer overflow, PROFDIR too long");
1.5       jtc       427:                        return;
                    428:                }
                    429:
                    430:                proffile = buf;
                    431:        } else {
                    432:                proffile = "gmon.out";
                    433:        }
                    434:
                    435:        fd = open(proffile , O_CREAT|O_TRUNC|O_WRONLY, 0666);
1.1       cgd       436:        if (fd < 0) {
1.10      christos  437:                warn("mcount: Cannot open `%s'", proffile);
1.1       cgd       438:                return;
                    439:        }
                    440: #ifdef DEBUG
1.25      christos  441:        logfd = open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664);
                    442:        if (logfd < 0) {
1.10      christos  443:                warn("mcount: Cannot open `gmon.log'");
1.1       cgd       444:                return;
                    445:        }
1.25      christos  446:        len = snprintf(buf2, sizeof buf2, "[mcleanup1] kcount %p ssiz %lu\n",
1.1       cgd       447:            p->kcount, p->kcountsize);
1.25      christos  448:        (void)write(logfd, buf2, (size_t)len);
1.1       cgd       449: #endif
1.22      thorpej   450: #ifdef _REENTRANT
                    451:        _m_gmon_merge();
                    452: #endif
1.1       cgd       453:        hdr = (struct gmonhdr *)&gmonhdr;
                    454:        hdr->lpc = p->lowpc;
                    455:        hdr->hpc = p->highpc;
1.14      christos  456:        hdr->ncnt = (int)(p->kcountsize + sizeof(gmonhdr));
1.1       cgd       457:        hdr->version = GMONVERSION;
                    458:        hdr->profrate = clockinfo.profhz;
1.14      christos  459:        (void)write(fd, hdr, sizeof *hdr);
                    460:        (void)write(fd, p->kcount, (size_t)p->kcountsize);
                    461:        endfrom = (int)(p->fromssize / sizeof(*p->froms));
1.1       cgd       462:        for (fromindex = 0; fromindex < endfrom; fromindex++) {
                    463:                if (p->froms[fromindex] == 0)
                    464:                        continue;
                    465:
                    466:                frompc = p->lowpc;
                    467:                frompc += fromindex * p->hashfraction * sizeof(*p->froms);
                    468:                for (toindex = p->froms[fromindex]; toindex != 0;
                    469:                     toindex = p->tos[toindex].link) {
                    470: #ifdef DEBUG
1.9       mrg       471:                        len = snprintf(buf2, sizeof buf2,
1.25      christos  472:                        "[mcleanup2] frompc 0x%lx selfpc 0x%lx count %lu\n" ,
                    473:                                (u_long)frompc, (u_long)p->tos[toindex].selfpc,
                    474:                                (u_long)p->tos[toindex].count);
                    475:                        (void)write(logfd, buf2, (size_t)len);
1.1       cgd       476: #endif
                    477:                        rawarc.raw_frompc = frompc;
                    478:                        rawarc.raw_selfpc = p->tos[toindex].selfpc;
                    479:                        rawarc.raw_count = p->tos[toindex].count;
                    480:                        write(fd, &rawarc, sizeof rawarc);
                    481:                }
                    482:        }
                    483:        close(fd);
                    484: }
                    485:
                    486: /*
                    487:  * Control profiling
                    488:  *     profiling is what mcount checks to see if
                    489:  *     all the data structures are ready.
                    490:  */
                    491: void
                    492: moncontrol(mode)
                    493:        int mode;
                    494: {
                    495:        struct gmonparam *p = &_gmonparam;
                    496:
                    497:        if (mode) {
                    498:                /* start */
1.14      christos  499:                profil((char *)(void *)p->kcount, (size_t)p->kcountsize,
                    500:                    p->lowpc, s_scale);
1.1       cgd       501:                p->state = GMON_PROF_ON;
                    502:        } else {
                    503:                /* stop */
1.14      christos  504:                profil(NULL, 0, (u_long)0, 0);
1.1       cgd       505:                p->state = GMON_PROF_OFF;
                    506:        }
                    507: }
                    508:
                    509: /*
                    510:  * discover the tick frequency of the machine
                    511:  * if something goes wrong, we return 0, an impossible hertz.
                    512:  */
                    513: static int
                    514: hertz()
                    515: {
                    516:        struct itimerval tim;
                    517:
                    518:        tim.it_interval.tv_sec = 0;
                    519:        tim.it_interval.tv_usec = 1;
                    520:        tim.it_value.tv_sec = 0;
                    521:        tim.it_value.tv_usec = 0;
                    522:        setitimer(ITIMER_REAL, &tim, 0);
                    523:        setitimer(ITIMER_REAL, 0, &tim);
                    524:        if (tim.it_interval.tv_usec < 2)
                    525:                return(0);
1.14      christos  526:        return (int)(1000000 / tim.it_interval.tv_usec);
1.1       cgd       527: }

CVSweb <webmaster@jp.NetBSD.org>