diff options
-rw-r--r-- | monitor.c | 23 | ||||
-rw-r--r-- | qemu-monitor.hx | 14 | ||||
-rw-r--r-- | simpletrace.c | 60 | ||||
-rw-r--r-- | simpletrace.h | 4 |
4 files changed, 88 insertions, 13 deletions
@@ -549,6 +549,29 @@ static void do_change_trace_event_state(Monitor *mon, const QDict *qdict) bool new_state = qdict_get_bool(qdict, "option"); st_change_trace_event_state(tp_name, new_state); } + +static void do_trace_file(Monitor *mon, const QDict *qdict) +{ + const char *op = qdict_get_try_str(qdict, "op"); + const char *arg = qdict_get_try_str(qdict, "arg"); + + if (!op) { + st_print_trace_file_status((FILE *)mon, &monitor_fprintf); + } else if (!strcmp(op, "on")) { + st_set_trace_file_enabled(true); + } else if (!strcmp(op, "off")) { + st_set_trace_file_enabled(false); + } else if (!strcmp(op, "flush")) { + st_flush_trace_buffer(); + } else if (!strcmp(op, "set")) { + if (arg) { + st_set_trace_file(arg); + } + } else { + monitor_printf(mon, "unexpected argument \"%s\"\n", op); + help_cmd(mon, "trace-file"); + } +} #endif static void user_monitor_complete(void *opaque, QObject *ret_data) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index c264c7d539..49bcd8d324 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -295,6 +295,20 @@ STEXI @findex trace-event changes status of a trace event ETEXI + + { + .name = "trace-file", + .args_type = "op:s?,arg:F?", + .params = "on|off|flush|set [arg]", + .help = "open, close, or flush trace file, or set a new file name", + .mhandler.cmd = do_trace_file, + }, + +STEXI +@item trace-file on|off|flush +@findex trace-file +Open, close, or flush the trace file. If no argument is given, the status of the trace file is displayed. +ETEXI #endif { diff --git a/simpletrace.c b/simpletrace.c index 97045a6732..f849e42914 100644 --- a/simpletrace.c +++ b/simpletrace.c @@ -42,6 +42,14 @@ enum { static TraceRecord trace_buf[TRACE_BUF_LEN]; static unsigned int trace_idx; static FILE *trace_fp; +static char *trace_file_name = NULL; +static bool trace_file_enabled = false; + +void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) +{ + stream_printf(stream, "Trace file \"%s\" %s.\n", + trace_file_name, trace_file_enabled ? "on" : "off"); +} static bool write_header(FILE *fp) { @@ -54,31 +62,57 @@ static bool write_header(FILE *fp) return fwrite(&header, sizeof header, 1, fp) == 1; } -static bool open_trace_file(void) +/** + * set_trace_file : To set the name of a trace file. + * @file : pointer to the name to be set. + * If NULL, set to the default name-<pid> set at config time. + */ +bool st_set_trace_file(const char *file) { - char *filename; + st_set_trace_file_enabled(false); - if (asprintf(&filename, CONFIG_TRACE_FILE, getpid()) < 0) { - return false; - } + free(trace_file_name); - trace_fp = fopen(filename, "w"); - free(filename); - if (!trace_fp) { - return false; + if (!file) { + if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) { + trace_file_name = NULL; + return false; + } + } else { + if (asprintf(&trace_file_name, "%s", file) < 0) { + trace_file_name = NULL; + return false; + } } - return write_header(trace_fp); + + st_set_trace_file_enabled(true); + return true; } -static void flush_trace_buffer(void) +static void flush_trace_file(void) { + /* If the trace file is not open yet, open it now */ if (!trace_fp) { - open_trace_file(); + trace_fp = fopen(trace_file_name, "w"); + if (!trace_fp) { + /* Avoid repeatedly trying to open file on failure */ + trace_file_enabled = false; + return; + } + write_header(trace_fp); } + if (trace_fp) { size_t unused; /* for when fwrite(3) is declared warn_unused_result */ unused = fwrite(trace_buf, trace_idx * sizeof(trace_buf[0]), 1, trace_fp); } +} + +void st_flush_trace_buffer(void) +{ + if (trace_file_enabled) { + flush_trace_file(); + } /* Discard written trace records */ trace_idx = 0; @@ -128,7 +162,7 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, rec->x6 = x6; if (++trace_idx == TRACE_BUF_LEN) { - flush_trace_buffer(); + st_flush_trace_buffer(); } } diff --git a/simpletrace.h b/simpletrace.h index b0161d1ff4..cf3589774b 100644 --- a/simpletrace.h +++ b/simpletrace.h @@ -32,5 +32,9 @@ void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); void st_change_trace_event_state(const char *tname, bool tstate); +void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); +void st_set_trace_file_enabled(bool enable); +bool st_set_trace_file(const char *file); +void st_flush_trace_buffer(void); #endif /* SIMPLETRACE_H */ |