Annotation of XNU/osfmk/ddb/tr.c, revision 1.1.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.