Annotation of qemu/simpletrace.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Simple trace backend
                      3:  *
                      4:  * Copyright IBM, Corp. 2010
                      5:  *
                      6:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                      7:  * the COPYING file in the top-level directory.
                      8:  *
                      9:  */
                     10: 
                     11: #include <stdlib.h>
                     12: #include <stdint.h>
                     13: #include <stdio.h>
                     14: #include <time.h>
                     15: #include "qemu-timer.h"
                     16: #include "trace.h"
                     17: 
                     18: /** Trace file header event ID */
                     19: #define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */
                     20: 
                     21: /** Trace file magic number */
                     22: #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
                     23: 
                     24: /** Trace file version number, bump if format changes */
                     25: #define HEADER_VERSION 0
                     26: 
                     27: /** Trace buffer entry */
                     28: typedef struct {
                     29:     uint64_t event;
                     30:     uint64_t timestamp_ns;
                     31:     uint64_t x1;
                     32:     uint64_t x2;
                     33:     uint64_t x3;
                     34:     uint64_t x4;
                     35:     uint64_t x5;
                     36:     uint64_t x6;
                     37: } TraceRecord;
                     38: 
                     39: enum {
                     40:     TRACE_BUF_LEN = 64 * 1024 / sizeof(TraceRecord),
                     41: };
                     42: 
                     43: static TraceRecord trace_buf[TRACE_BUF_LEN];
                     44: static unsigned int trace_idx;
                     45: static FILE *trace_fp;
                     46: static char *trace_file_name = NULL;
                     47: static bool trace_file_enabled = false;
                     48: 
                     49: void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
                     50: {
                     51:     stream_printf(stream, "Trace file \"%s\" %s.\n",
                     52:                   trace_file_name, trace_file_enabled ? "on" : "off");
                     53: }
                     54: 
                     55: static bool write_header(FILE *fp)
                     56: {
                     57:     static const TraceRecord header = {
                     58:         .event = HEADER_EVENT_ID,
                     59:         .timestamp_ns = HEADER_MAGIC,
                     60:         .x1 = HEADER_VERSION,
                     61:     };
                     62: 
                     63:     return fwrite(&header, sizeof header, 1, fp) == 1;
                     64: }
                     65: 
                     66: /**
                     67:  * set_trace_file : To set the name of a trace file.
                     68:  * @file : pointer to the name to be set.
                     69:  *         If NULL, set to the default name-<pid> set at config time.
                     70:  */
                     71: bool st_set_trace_file(const char *file)
                     72: {
                     73:     st_set_trace_file_enabled(false);
                     74: 
                     75:     free(trace_file_name);
                     76: 
                     77:     if (!file) {
                     78:         if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) {
                     79:             trace_file_name = NULL;
                     80:             return false;
                     81:         }
                     82:     } else {
                     83:         if (asprintf(&trace_file_name, "%s", file) < 0) {
                     84:             trace_file_name = NULL;
                     85:             return false;
                     86:         }
                     87:     }
                     88: 
                     89:     st_set_trace_file_enabled(true);
                     90:     return true;
                     91: }
                     92: 
                     93: static void flush_trace_file(void)
                     94: {
                     95:     /* If the trace file is not open yet, open it now */
                     96:     if (!trace_fp) {
                     97:         trace_fp = fopen(trace_file_name, "w");
                     98:         if (!trace_fp) {
                     99:             /* Avoid repeatedly trying to open file on failure */
                    100:             trace_file_enabled = false;
                    101:             return;
                    102:         }
                    103:         write_header(trace_fp);
                    104:     }
                    105: 
                    106:     if (trace_fp) {
                    107:         size_t unused; /* for when fwrite(3) is declared warn_unused_result */
                    108:         unused = fwrite(trace_buf, trace_idx * sizeof(trace_buf[0]), 1, trace_fp);
                    109:     }
                    110: }
                    111: 
                    112: void st_flush_trace_buffer(void)
                    113: {
                    114:     if (trace_file_enabled) {
                    115:         flush_trace_file();
                    116:     }
                    117: 
                    118:     /* Discard written trace records */
                    119:     trace_idx = 0;
                    120: }
                    121: 
                    122: void st_set_trace_file_enabled(bool enable)
                    123: {
                    124:     if (enable == trace_file_enabled) {
                    125:         return; /* no change */
                    126:     }
                    127: 
                    128:     /* Flush/discard trace buffer */
                    129:     st_flush_trace_buffer();
                    130: 
                    131:     /* To disable, close trace file */
                    132:     if (!enable) {
                    133:         fclose(trace_fp);
                    134:         trace_fp = NULL;
                    135:     }
                    136: 
                    137:     trace_file_enabled = enable;
                    138: }
                    139: 
                    140: static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
                    141:                   uint64_t x4, uint64_t x5, uint64_t x6)
                    142: {
                    143:     TraceRecord *rec = &trace_buf[trace_idx];
                    144: 
                    145:     if (!trace_list[event].state) {
                    146:         return;
                    147:     }
                    148: 
                    149:     rec->event = event;
                    150:     rec->timestamp_ns = get_clock();
                    151:     rec->x1 = x1;
                    152:     rec->x2 = x2;
                    153:     rec->x3 = x3;
                    154:     rec->x4 = x4;
                    155:     rec->x5 = x5;
                    156:     rec->x6 = x6;
                    157: 
                    158:     if (++trace_idx == TRACE_BUF_LEN) {
                    159:         st_flush_trace_buffer();
                    160:     }
                    161: }
                    162: 
                    163: void trace0(TraceEventID event)
                    164: {
                    165:     trace(event, 0, 0, 0, 0, 0, 0);
                    166: }
                    167: 
                    168: void trace1(TraceEventID event, uint64_t x1)
                    169: {
                    170:     trace(event, x1, 0, 0, 0, 0, 0);
                    171: }
                    172: 
                    173: void trace2(TraceEventID event, uint64_t x1, uint64_t x2)
                    174: {
                    175:     trace(event, x1, x2, 0, 0, 0, 0);
                    176: }
                    177: 
                    178: void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3)
                    179: {
                    180:     trace(event, x1, x2, x3, 0, 0, 0);
                    181: }
                    182: 
                    183: void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4)
                    184: {
                    185:     trace(event, x1, x2, x3, x4, 0, 0);
                    186: }
                    187: 
                    188: void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5)
                    189: {
                    190:     trace(event, x1, x2, x3, x4, x5, 0);
                    191: }
                    192: 
                    193: void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6)
                    194: {
                    195:     trace(event, x1, x2, x3, x4, x5, x6);
                    196: }
                    197: 
                    198: /**
                    199:  * Flush the trace buffer on exit
                    200:  */
                    201: static void __attribute__((constructor)) st_init(void)
                    202: {
                    203:     atexit(st_flush_trace_buffer);
                    204: }
                    205: 
                    206: void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
                    207: {
                    208:     unsigned int i;
                    209: 
                    210:     for (i = 0; i < trace_idx; i++) {
                    211:         stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64
                    212:                       " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n",
                    213:                       trace_buf[i].event, trace_buf[i].x1, trace_buf[i].x2,
                    214:                       trace_buf[i].x3, trace_buf[i].x4, trace_buf[i].x5,
                    215:                       trace_buf[i].x6);
                    216:     }
                    217: }
                    218: 
                    219: void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
                    220: {
                    221:     unsigned int i;
                    222: 
                    223:     for (i = 0; i < NR_TRACE_EVENTS; i++) {
                    224:         stream_printf(stream, "%s [Event ID %u] : state %u\n",
                    225:                       trace_list[i].tp_name, i, trace_list[i].state);
                    226:     }
                    227: }
                    228: 
                    229: static TraceEvent* find_trace_event_by_name(const char *tname)
                    230: {
                    231:     unsigned int i;
                    232: 
                    233:     if (!tname) {
                    234:         return NULL;
                    235:     }
                    236: 
                    237:     for (i = 0; i < NR_TRACE_EVENTS; i++) {
                    238:         if (!strcmp(trace_list[i].tp_name, tname)) {
                    239:             return &trace_list[i];
                    240:         }
                    241:     }
                    242:     return NULL; /* indicates end of list reached without a match */
                    243: }
                    244: 
                    245: bool st_change_trace_event_state(const char *tname, bool tstate)
                    246: {
                    247:     TraceEvent *tp;
                    248: 
                    249:     tp = find_trace_event_by_name(tname);
                    250:     if (tp) {
                    251:         tp->state = tstate;
                    252:         return true;
                    253:     }
                    254:     return false;
                    255: }

unix.superglobalmegacorp.com