Annotation of XNU/osfmk/ddb/tr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  *     File:           ddb/tr.c
        !            27:  *     Authors:        Alan Langerman, Jeffrey Heller
        !            28:  *     Date:           1992
        !            29:  *
        !            30:  *     Internal trace routines.  Like old-style XPRs but
        !            31:  *     less formatting.
        !            32:  */
        !            33: 
        !            34: #include <ddb/tr.h>
        !            35: 
        !            36: #if    TRACE_BUFFER
        !            37: #include <string.h>
        !            38: #include <ddb/db_command.h>
        !            39: #include <mach_kdb.h>
        !            40: #include <kern/lock.h>
        !            41: #include <kern/spl.h>
        !            42: 
        !            43: extern void fc_get(int *);
        !            44: 
        !            45: /*
        !            46:  *     Primitive event tracing facility for kernel debugging.  Yes,
        !            47:  *     this has some resemblance to XPRs.  However, it is primarily
        !            48:  *     intended for post-mortem analysis through ddb.
        !            49:  */
        !            50: 
        !            51: #define        TRACE_MAX       (4 * 1024)
        !            52: #define        TRACE_WINDOW    40
        !            53: 
        !            54: typedef struct trace_event {
        !            55:        char            *funcname;
        !            56:        char            *file;
        !            57:        char            *fmt;
        !            58: #if    NCPUS > 1
        !            59:        char            cpu_number;
        !            60: #endif /* NCPUS > 1 */
        !            61:        unsigned int    lineno;
        !            62:        unsigned int    tag1;
        !            63:        unsigned int    tag2;
        !            64:        unsigned int    tag3;
        !            65:        unsigned int    tag4;
        !            66:        int             indent;
        !            67:        int             timestamp[2]; /* largest needed by any clock */
        !            68: } trace_event;
        !            69: 
        !            70: trace_event    trace_buffer[TRACE_MAX];
        !            71: unsigned long  trace_index;
        !            72: #if    NCPUS == 1
        !            73: int            tr_indent = 0;
        !            74: #else  /* NCPUS == 1 */
        !            75: int            tr_indent[NCPUS];
        !            76: int            tr_limit = -1;
        !            77: #endif /* NCPUS == 1 */
        !            78: 
        !            79: decl_simple_lock_data(,trace_lock)
        !            80: 
        !            81: void
        !            82: tr_init(void)
        !            83: {
        !            84: #if    NCPUS > 1
        !            85:        int i;
        !            86: 
        !            87:        for(i=0;i<NCPUS;i++)
        !            88:            tr_indent[i]=0;
        !            89: #endif /* NCPUS > 1 */
        !            90: 
        !            91:        simple_lock_init(&trace_lock, ETAP_DIPC_TRACE);
        !            92: }
        !            93: 
        !            94: void
        !            95: tr(
        !            96:        char            *funcname,
        !            97:        char            *file,
        !            98:        unsigned int    lineno,
        !            99:        char            *fmt,
        !           100:        unsigned int    tag1,
        !           101:        unsigned int    tag2,
        !           102:        unsigned int    tag3,
        !           103:        unsigned int    tag4)
        !           104: {
        !           105:        int     s;
        !           106:        register unsigned long ti, tn;
        !           107: #if    NCPUS > 1
        !           108:        char cpu;
        !           109: #endif /* NCPUS > 1 */
        !           110: 
        !           111: #if    PARAGON860
        !           112:        /*
        !           113:         * The following loop replaces the spl_and_lock sequence that
        !           114:         * would normally be here, as they are too heavy weight.  The
        !           115:         * cmpsw (compare-and-swap) call returns -1 if unsuccessful.
        !           116:         */
        !           117:        do {
        !           118:                ti = trace_index;
        !           119:                tn = ti + 1;
        !           120:                if (tn >= TRACE_MAX - 1)
        !           121:                        tn = 0;
        !           122:        } while (cmpsw(ti, tn, &trace_index) == -1);
        !           123:        fc_get(trace_buffer[ti].timestamp);
        !           124: #else  /* PARAGON860 */
        !           125:        /*
        !           126:         * Until someone does a cmpsw for other platforms, do it
        !           127:         * the slow way
        !           128:         */
        !           129:        s = splimp();
        !           130:        simple_lock(&trace_lock);
        !           131: 
        !           132:        ti = trace_index++;
        !           133:        if (trace_index >= TRACE_MAX - 1)
        !           134:                trace_index = 0;
        !           135: 
        !           136:        simple_unlock(&trace_lock);
        !           137:        splx(s);
        !           138: 
        !           139:        fc_get(trace_buffer[ti].timestamp);
        !           140: /*     get_uniq_timestamp(trace_buffer[ti].timestamp);*/
        !           141: #endif /* PARAGON860 */
        !           142: 
        !           143:        trace_buffer[ti].funcname = funcname;
        !           144:        trace_buffer[ti].file = file;
        !           145:        trace_buffer[ti].lineno = lineno;
        !           146:        trace_buffer[ti].fmt = fmt;
        !           147:        trace_buffer[ti].tag1 = tag1;
        !           148:        trace_buffer[ti].tag2 = tag2;
        !           149:        trace_buffer[ti].tag3 = tag3;
        !           150:        trace_buffer[ti].tag4 = tag4;
        !           151: #if    NCPUS == 1
        !           152:        trace_buffer[ti].indent = tr_indent;
        !           153: #else  /* NCPUS == 1 */
        !           154:        mp_disable_preemption();
        !           155:        cpu = cpu_number();
        !           156:        trace_buffer[ti].indent = tr_indent[cpu];
        !           157:        trace_buffer[ti].cpu_number = cpu;
        !           158:        mp_enable_preemption();
        !           159: #endif /* NCPUS == 1 */
        !           160: }
        !           161: 
        !           162: #if    MACH_KDB
        !           163: #include <ddb/db_output.h>
        !           164: 
        !           165: /*
        !           166:  * Forward.
        !           167:  */
        !           168: void   show_tr(
        !           169:                unsigned long   index,
        !           170:                unsigned long   range,
        !           171:                unsigned long   show_extra);
        !           172: 
        !           173: int    matches(
        !           174:                char    *pattern,
        !           175:                char    *target);
        !           176: 
        !           177: void   parse_tr(
        !           178:                unsigned long   index,
        !           179:                unsigned long   range);
        !           180: 
        !           181: /*
        !           182:  *     The blank array must be a bit bigger than
        !           183:  *     MAX_BLANKS to leave room for a terminating NULL.
        !           184:  */
        !           185: #define        MAX_BLANKS      16
        !           186: char                   blanks[MAX_BLANKS+4];
        !           187: 
        !           188: void
        !           189: show_tr(
        !           190:        unsigned long   index,
        !           191:        unsigned long   range,
        !           192:        unsigned long   show_extra)
        !           193: {
        !           194:        char            *filename, *cp;
        !           195: #if    PARAGON860
        !           196:        trace_event     *last_trace;
        !           197: #endif /* PARAGON860 */
        !           198:        unsigned int    level;
        !           199:        int             old_history;
        !           200:        int             i;
        !           201: 
        !           202:        if (index == -1) {
        !           203:                index = trace_index - (TRACE_WINDOW-4);
        !           204:                range = TRACE_WINDOW;
        !           205:        } else if (index == 0) {
        !           206:                index = trace_index - (TRACE_WINDOW-4);
        !           207:                range = TRACE_WINDOW;
        !           208:                show_extra = 0;
        !           209:        }
        !           210:        if (index + range > TRACE_MAX)
        !           211:                range = TRACE_MAX - index;
        !           212: #if    PARAGON860
        !           213:        last_trace = &trace_buffer[index-1];
        !           214: #endif /* PARAGON860 */
        !           215:        level = trace_buffer[index-1].indent;
        !           216:        /*
        !           217:         * Set up the indentation buffer
        !           218:         */
        !           219:        memset(blanks, ' ', trace_buffer[index].indent);
        !           220:        blanks[trace_buffer[index].indent] = '\0';
        !           221:        for (i = index; i < index + range; ++i) {
        !           222: #if    NCPUS > 1
        !           223:                if ((tr_limit != -1) &&
        !           224:                    (trace_buffer[i].cpu_number != tr_limit))
        !           225:                    continue;
        !           226: #endif /* NCPUS > 1 */
        !           227:                if (trace_buffer[i].file == (char *) 0 ||
        !           228:                    trace_buffer[i].funcname == (char *) 0 ||
        !           229:                    trace_buffer[i].lineno == 0 ||
        !           230:                    trace_buffer[i].fmt == 0) {
        !           231:                        db_printf("[%04x%s]\n", i,
        !           232:                                  i >= trace_index ? "*" : "");
        !           233:                        continue;
        !           234:                }
        !           235: 
        !           236:                old_history = (i >= trace_index);
        !           237: 
        !           238:                /*
        !           239:                 * Adjust the blank count if necessary
        !           240:                 */
        !           241:                if (level != trace_buffer[i].indent) {
        !           242:                        level = trace_buffer[i].indent;
        !           243:                        if (level >= MAX_BLANKS)
        !           244:                                level = MAX_BLANKS;
        !           245:                        memset(blanks, ' ', level);
        !           246:                        blanks[level] = '\0';
        !           247:                } 
        !           248: 
        !           249:                for (cp = trace_buffer[i].file; *cp; ++cp)
        !           250:                        if (*cp == '/')
        !           251:                                filename = cp + 1;
        !           252: #if    NCPUS > 1
        !           253:                db_printf("{%02d}",trace_buffer[i].cpu_number);
        !           254: #endif /* NCPUS > 1 */
        !           255:                db_printf("[%04x%s] %s%-16s", i, old_history ? "*" : "",
        !           256:                          blanks, trace_buffer[i].funcname);
        !           257: 
        !           258:                if (show_extra) {
        !           259:                        if (show_extra > 0) {
        !           260:                                db_printf(" (%x/%8x)", 
        !           261:                                          trace_buffer[i].timestamp[0],
        !           262:                                          trace_buffer[i].timestamp[1]);
        !           263: #if    PARAGON860
        !           264:                                /*
        !           265:                                 *      For Paragon only, we compute and
        !           266:                                 *      print out deltas on the timestamps
        !           267:                                 *      accumulated in the tr buffer.  One
        !           268:                                 *      interesting case:  it is meaningless
        !           269:                                 *      to compute this delta for the last
        !           270:                                 *      current entry in the log.
        !           271:                                 */
        !           272:                                if (old_history &&
        !           273:                                    ((last_trace - trace_buffer)
        !           274:                                     < trace_index))
        !           275:                                        db_printf("(N/A)");
        !           276:                                else
        !           277:                                        db_printf("(%d)", 
        !           278:                                                  timer_subtime(
        !           279:                                                     trace_buffer[i].timestamp,
        !           280:                                                     last_trace->timestamp));
        !           281: #endif /*PARAGON860*/
        !           282:                                db_printf(" ");
        !           283:                        }
        !           284:                        if (show_extra > 1) {
        !           285:                                db_printf("(%s:%05d):\n\t", 
        !           286:                                          filename, trace_buffer[i].lineno);
        !           287:                        }
        !           288:                } else
        !           289:                        db_printf(":  ");
        !           290:                db_printf(trace_buffer[i].fmt, trace_buffer[i].tag1,
        !           291:                          trace_buffer[i].tag2, trace_buffer[i].tag3,
        !           292:                          trace_buffer[i].tag4);
        !           293:                db_printf("\n");
        !           294: #if    PARAGON860
        !           295:                last_trace = &trace_buffer[i];
        !           296: #endif /* PARAGON860 */
        !           297:        }
        !           298: }
        !           299: 
        !           300: 
        !           301: int
        !           302: matches(
        !           303:        char    *pattern,
        !           304:        char    *target)
        !           305: {
        !           306:        char    *cp, *cp1, *cp2;
        !           307: 
        !           308:        for (cp = target; *cp; ++cp) {
        !           309:                for (cp2 = pattern, cp1 = cp; *cp2 && *cp1; ++cp2, ++cp1)
        !           310:                        if (*cp2 != *cp1)
        !           311:                                break;
        !           312:                if (!*cp2)
        !           313:                        return 1;
        !           314:        }
        !           315:        return 0;
        !           316: }
        !           317: 
        !           318: 
        !           319: char   parse_tr_buffer[100] = "KMSG";
        !           320: 
        !           321: void
        !           322: parse_tr(
        !           323:        unsigned long   index,
        !           324:        unsigned long   range)
        !           325: {
        !           326:        int             i;
        !           327:        char            *filename, *cp;
        !           328:        char            *string = parse_tr_buffer;
        !           329: 
        !           330:        if (index == 0) {
        !           331:                index = trace_index - (TRACE_WINDOW-4);
        !           332:                range = TRACE_WINDOW;
        !           333:        }
        !           334:        if (index + range > TRACE_MAX)
        !           335:                range = TRACE_MAX - index;
        !           336:        for (i = index; i < index + range; ++i) {
        !           337: #if    NCPUS > 1
        !           338:                if ((tr_limit != -1) &&
        !           339:                    (trace_buffer[i].cpu_number != tr_limit))
        !           340:                    continue;
        !           341: #endif /* NCPUS > 1 */
        !           342:                if (trace_buffer[i].file == (char *) 0 ||
        !           343:                    trace_buffer[i].funcname == (char *) 0 ||
        !           344:                    trace_buffer[i].lineno == 0 ||
        !           345:                    trace_buffer[i].fmt == 0) {
        !           346:                        db_printf("[%04x%s]\n", i,
        !           347:                                  i >= trace_index ? "*" : "");
        !           348:                        continue;
        !           349:                }
        !           350:                if (!matches(string, trace_buffer[i].fmt))
        !           351:                        continue;
        !           352:                for (cp = trace_buffer[i].file; *cp; ++cp)
        !           353:                        if (*cp == '/')
        !           354:                                filename = cp + 1;
        !           355: #if    NCPUS > 1
        !           356:                db_printf("{%02d}",trace_buffer[i].cpu_number);
        !           357: #endif /* NCPUS > 1 */
        !           358:                db_printf("[%04x%s] %s", i, i >= trace_index ? "*" : "",
        !           359:                       trace_buffer[i].funcname);
        !           360:                db_printf(":  ");
        !           361:                db_printf(trace_buffer[i].fmt, trace_buffer[i].tag1,
        !           362:                          trace_buffer[i].tag2, trace_buffer[i].tag3,
        !           363:                          trace_buffer[i].tag4);
        !           364:                db_printf("\n");
        !           365:        }
        !           366: }
        !           367: 
        !           368: 
        !           369: void
        !           370: db_show_tr(
        !           371:        db_expr_t       addr,
        !           372:        boolean_t       have_addr,
        !           373:        db_expr_t       count,
        !           374:        char *          modif)
        !           375: {
        !           376:        int             flag, level;
        !           377: 
        !           378:        flag = 0, level = 0;
        !           379:        if (db_option(modif, 'l')) {
        !           380:                flag = 1;
        !           381:                level = -1;
        !           382:        }
        !           383:        if (db_option(modif, 'a')) {
        !           384:                flag = 2;
        !           385:                level = -1;
        !           386:        }
        !           387: 
        !           388:        TR_SHOW(level, 0, flag);
        !           389: }
        !           390: 
        !           391: #endif /* MACH_KDB */
        !           392: 
        !           393: #endif /* TRACE_BUFFER */

unix.superglobalmegacorp.com

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