aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--monitor.c23
-rw-r--r--qemu-monitor.hx14
-rw-r--r--simpletrace.c60
-rw-r--r--simpletrace.h4
4 files changed, 88 insertions, 13 deletions
diff --git a/monitor.c b/monitor.c
index 0e69bc8b9d..e602480ebb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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 */