@@ -540,6 +540,23 @@ static void do_change_trace_event_state(Monitor *mon, const QDict *qdict)
bool new_state = qdict_get_bool(qdict, "option");
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");
+
+ 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 {
+ monitor_printf(mon, "unexpected argument \"%s\"\n", op);
+ }
+}
#endif
static void user_monitor_complete(void *opaque, QObject *ret_data)
@@ -273,6 +273,20 @@ STEXI
@findex trace-event
changes status of a trace event
ETEXI
+
+ {
+ .name = "trace-file",
+ .args_type = "op:s?",
+ .params = "op [on|off|flush]",
+ .help = "open, close, or flush trace file",
+ .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
{
@@ -20,6 +20,13 @@ enum {
static TraceRecord trace_buf[TRACE_BUF_LEN];
static unsigned int trace_idx;
static FILE *trace_fp;
+static bool trace_file_enabled = true;
+
+void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
+{
+ stream_printf(stream, "Trace file \"" CONFIG_TRACE_FILE "\" %s.\n",
+ getpid(), trace_file_enabled ? "on" : "off");
+}
static bool open_trace_file(void)
{
@@ -34,22 +41,52 @@ static bool open_trace_file(void)
return trace_fp != NULL;
}
-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) {
- if (open_trace_file()) {
- atexit(flush_trace_buffer);
+ if (!open_trace_file()) {
+ /* Avoid repeatedly trying to open file on failure */
+ trace_file_enabled = false;
+ return;
}
+ atexit(st_flush_trace_buffer);
}
+
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;
}
+void st_set_trace_file_enabled(bool enable)
+{
+ if (enable == trace_file_enabled) {
+ return; /* no change */
+ }
+
+ /* Flush/discard trace buffer */
+ st_flush_trace_buffer();
+
+ /* To disable, close trace file */
+ if (!enable) {
+ fclose(trace_fp);
+ trace_fp = NULL;
+ }
+
+ trace_file_enabled = enable;
+}
+
static void trace(TraceEventID event, unsigned long x1,
unsigned long x2, unsigned long x3,
unsigned long x4, unsigned long x5)
@@ -76,7 +113,7 @@ static void trace(TraceEventID event, unsigned long x1,
rec->x5 = x5;
if (++trace_idx == TRACE_BUF_LEN) {
- flush_trace_buffer();
+ st_flush_trace_buffer();
}
}
@@ -141,6 +141,9 @@ void trace4(TraceEventID event, unsigned long x1, unsigned long x2, unsigned lon
void trace5(TraceEventID event, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long x4, unsigned long x5);
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_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...));
+void st_flush_trace_buffer(void);
+void st_set_trace_file_enabled(bool enable);
void change_trace_event_state(const char *tname, bool tstate);
EOF
This patch adds the trace-file command: trace-file [on|off|flush] Open, close, or flush the trace file. If no argument is given, the status of the trace file is displayed. The trace file is turned on by default but is only written out when the trace buffer becomes full. The flush operation can be used to force write out at any time. Turning off the trace file does not change the state of trace events; tracing will continue to the trace buffer. When the trace file is off, use "info trace" to display the contents of the trace buffer in memory. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> --- monitor.c | 17 +++++++++++++++++ qemu-monitor.hx | 14 ++++++++++++++ simpletrace.c | 45 +++++++++++++++++++++++++++++++++++++++++---- tracetool | 3 +++ 4 files changed, 75 insertions(+), 4 deletions(-)