From patchwork Wed Aug 31 16:52:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?Q?Llu=C3=ADs?= X-Patchwork-Id: 112617 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4DF52B6F7C for ; Thu, 1 Sep 2011 02:53:24 +1000 (EST) Received: from localhost ([::1]:43462 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qyo2S-00022q-5I for incoming@patchwork.ozlabs.org; Wed, 31 Aug 2011 12:53:20 -0400 Received: from eggs.gnu.org ([140.186.70.92]:53810) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qyo2H-0001qM-II for qemu-devel@nongnu.org; Wed, 31 Aug 2011 12:53:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qyo2E-0000aU-QW for qemu-devel@nongnu.org; Wed, 31 Aug 2011 12:53:09 -0400 Received: from mailout-de.gmx.net ([213.165.64.23]:44395) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1Qyo2E-0000aO-9G for qemu-devel@nongnu.org; Wed, 31 Aug 2011 12:53:06 -0400 Received: (qmail invoked by alias); 31 Aug 2011 16:53:04 -0000 Received: from unknown (EHLO localhost) [84.88.53.92] by mail.gmx.net (mp055) with SMTP; 31 Aug 2011 18:53:04 +0200 X-Authenticated: #12333383 X-Provags-ID: V01U2FsdGVkX1+Lgvlyjy+LpnWQiRw3uTf67NXfLKaL+egoPI/gKP G5sIvPZMSUS15E To: qemu-devel@nongnu.org, chouteau@adacore.com From: =?utf-8?b?TGx1w61z?= Date: Wed, 31 Aug 2011 18:52:40 +0200 Message-ID: <20110831165240.4389.1867.stgit@ginnungagap.bsc.es> In-Reply-To: <20110831165206.4389.17250.stgit@ginnungagap.bsc.es> References: <20110831165206.4389.17250.stgit@ginnungagap.bsc.es> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Y-GMX-Trusted: 0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 213.165.64.23 Cc: stefanha@gmail.com Subject: [Qemu-devel] [PATCH v8 05/14] trace: move backend-specific code into the trace/ directory X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: LluĂ­s Vilanova --- Makefile | 1 Makefile.objs | 6 + scripts/tracetool | 2 simpletrace.c | 355 ----------------------------------------------------- simpletrace.h | 48 ------- trace/simple.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++++ trace/simple.h | 48 +++++++ vl.c | 2 8 files changed, 410 insertions(+), 407 deletions(-) delete mode 100644 simpletrace.c delete mode 100644 simpletrace.h create mode 100644 trace/simple.c create mode 100644 trace/simple.h diff --git a/Makefile b/Makefile index 8606849..13be25a 100644 --- a/Makefile +++ b/Makefile @@ -209,6 +209,7 @@ clean: rm -Rf .libs rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d rm -f qemu-img-cmds.h + rm -f trace/*.o trace/*.d rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp rm -f trace-dtrace.h trace-dtrace.h-timestamp diff --git a/Makefile.objs b/Makefile.objs index 833158b..4f8b0ed 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -372,16 +372,18 @@ trace-dtrace.lo: trace-dtrace.dtrace $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN trace-dtrace.o") endif -simpletrace.o: simpletrace.c $(GENERATED_HEADERS) +trace/simple.o: trace/simple.c $(GENERATED_HEADERS) trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace.o ifneq ($(TRACE_BACKEND),dtrace) trace-obj-y = trace.o endif -trace-obj-$(CONFIG_TRACE_SIMPLE) += simpletrace.o +trace-nested-$(CONFIG_TRACE_SIMPLE) += simple.o trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o +trace-obj-y += $(addprefix trace/, $(trace-nested-y)) + ###################################################################### # smartcard diff --git a/scripts/tracetool b/scripts/tracetool index 2155a57..9ed4fae 100755 --- a/scripts/tracetool +++ b/scripts/tracetool @@ -158,7 +158,7 @@ linetoc_end_nop() linetoh_begin_simple() { cat < -#include -#include -#include -#include -#include -#include "qemu-timer.h" -#include "trace.h" - -/** Trace file header event ID */ -#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ - -/** Trace file magic number */ -#define HEADER_MAGIC 0xf2b177cb0aa429b4ULL - -/** Trace file version number, bump if format changes */ -#define HEADER_VERSION 0 - -/** Records were dropped event ID */ -#define DROPPED_EVENT_ID (~(uint64_t)0 - 1) - -/** Trace record is valid */ -#define TRACE_RECORD_VALID ((uint64_t)1 << 63) - -/** Trace buffer entry */ -typedef struct { - uint64_t event; - uint64_t timestamp_ns; - uint64_t x1; - uint64_t x2; - uint64_t x3; - uint64_t x4; - uint64_t x5; - uint64_t x6; -} TraceRecord; - -enum { - TRACE_BUF_LEN = 4096, - TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4, -}; - -/* - * Trace records are written out by a dedicated thread. The thread waits for - * records to become available, writes them out, and then waits again. - */ -static pthread_mutex_t trace_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t trace_available_cond = PTHREAD_COND_INITIALIZER; -static pthread_cond_t trace_empty_cond = PTHREAD_COND_INITIALIZER; -static bool trace_available; -static bool trace_writeout_enabled; - -static TraceRecord trace_buf[TRACE_BUF_LEN]; -static unsigned int trace_idx; -static FILE *trace_fp; -static char *trace_file_name = NULL; - -/** - * Read a trace record from the trace buffer - * - * @idx Trace buffer index - * @record Trace record to fill - * - * Returns false if the record is not valid. - */ -static bool get_trace_record(unsigned int idx, TraceRecord *record) -{ - if (!(trace_buf[idx].event & TRACE_RECORD_VALID)) { - return false; - } - - __sync_synchronize(); /* read memory barrier before accessing record */ - - *record = trace_buf[idx]; - record->event &= ~TRACE_RECORD_VALID; - return true; -} - -/** - * Kick writeout thread - * - * @wait Whether to wait for writeout thread to complete - */ -static void flush_trace_file(bool wait) -{ - pthread_mutex_lock(&trace_lock); - trace_available = true; - pthread_cond_signal(&trace_available_cond); - - if (wait) { - pthread_cond_wait(&trace_empty_cond, &trace_lock); - } - - pthread_mutex_unlock(&trace_lock); -} - -static void wait_for_trace_records_available(void) -{ - pthread_mutex_lock(&trace_lock); - while (!(trace_available && trace_writeout_enabled)) { - pthread_cond_signal(&trace_empty_cond); - pthread_cond_wait(&trace_available_cond, &trace_lock); - } - trace_available = false; - pthread_mutex_unlock(&trace_lock); -} - -static void *writeout_thread(void *opaque) -{ - TraceRecord record; - unsigned int writeout_idx = 0; - unsigned int num_available, idx; - size_t unused __attribute__ ((unused)); - - for (;;) { - wait_for_trace_records_available(); - - num_available = trace_idx - writeout_idx; - if (num_available > TRACE_BUF_LEN) { - record = (TraceRecord){ - .event = DROPPED_EVENT_ID, - .x1 = num_available, - }; - unused = fwrite(&record, sizeof(record), 1, trace_fp); - writeout_idx += num_available; - } - - idx = writeout_idx % TRACE_BUF_LEN; - while (get_trace_record(idx, &record)) { - trace_buf[idx].event = 0; /* clear valid bit */ - unused = fwrite(&record, sizeof(record), 1, trace_fp); - idx = ++writeout_idx % TRACE_BUF_LEN; - } - - fflush(trace_fp); - } - return NULL; -} - -static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, - uint64_t x4, uint64_t x5, uint64_t x6) -{ - unsigned int idx; - uint64_t timestamp; - - if (!trace_list[event].state) { - return; - } - - timestamp = get_clock(); - - idx = __sync_fetch_and_add(&trace_idx, 1) % TRACE_BUF_LEN; - trace_buf[idx] = (TraceRecord){ - .event = event, - .timestamp_ns = timestamp, - .x1 = x1, - .x2 = x2, - .x3 = x3, - .x4 = x4, - .x5 = x5, - .x6 = x6, - }; - __sync_synchronize(); /* write barrier before marking as valid */ - trace_buf[idx].event |= TRACE_RECORD_VALID; - - if ((idx + 1) % TRACE_BUF_FLUSH_THRESHOLD == 0) { - flush_trace_file(false); - } -} - -void trace0(TraceEventID event) -{ - trace(event, 0, 0, 0, 0, 0, 0); -} - -void trace1(TraceEventID event, uint64_t x1) -{ - trace(event, x1, 0, 0, 0, 0, 0); -} - -void trace2(TraceEventID event, uint64_t x1, uint64_t x2) -{ - trace(event, x1, x2, 0, 0, 0, 0); -} - -void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3) -{ - trace(event, x1, x2, x3, 0, 0, 0); -} - -void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4) -{ - trace(event, x1, x2, x3, x4, 0, 0); -} - -void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5) -{ - trace(event, x1, x2, x3, x4, x5, 0); -} - -void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6) -{ - trace(event, x1, x2, x3, x4, x5, x6); -} - -void st_set_trace_file_enabled(bool enable) -{ - if (enable == !!trace_fp) { - return; /* no change */ - } - - /* Halt trace writeout */ - flush_trace_file(true); - trace_writeout_enabled = false; - flush_trace_file(true); - - if (enable) { - static const TraceRecord header = { - .event = HEADER_EVENT_ID, - .timestamp_ns = HEADER_MAGIC, - .x1 = HEADER_VERSION, - }; - - trace_fp = fopen(trace_file_name, "w"); - if (!trace_fp) { - return; - } - - if (fwrite(&header, sizeof header, 1, trace_fp) != 1) { - fclose(trace_fp); - trace_fp = NULL; - return; - } - - /* Resume trace writeout */ - trace_writeout_enabled = true; - flush_trace_file(false); - } else { - fclose(trace_fp); - trace_fp = NULL; - } -} - -/** - * Set the name of a trace file - * - * @file The trace file name or NULL for the default name- set at - * config time - */ -bool st_set_trace_file(const char *file) -{ - st_set_trace_file_enabled(false); - - free(trace_file_name); - - 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; - } - } - - st_set_trace_file_enabled(true); - return true; -} - -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_fp ? "on" : "off"); -} - -void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) -{ - unsigned int i; - - for (i = 0; i < TRACE_BUF_LEN; i++) { - TraceRecord record; - - if (!get_trace_record(i, &record)) { - continue; - } - stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64 - " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n", - record.event, record.x1, record.x2, - record.x3, record.x4, record.x5, - record.x6); - } -} - -void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) -{ - unsigned int i; - - for (i = 0; i < NR_TRACE_EVENTS; i++) { - stream_printf(stream, "%s [Event ID %u] : state %u\n", - trace_list[i].tp_name, i, trace_list[i].state); - } -} - -bool st_change_trace_event_state(const char *name, bool enabled) -{ - unsigned int i; - - for (i = 0; i < NR_TRACE_EVENTS; i++) { - if (!strcmp(trace_list[i].tp_name, name)) { - trace_list[i].state = enabled; - return true; - } - } - return false; -} - -void st_flush_trace_buffer(void) -{ - flush_trace_file(true); -} - -bool st_init(const char *file) -{ - pthread_t thread; - pthread_attr_t attr; - sigset_t set, oldset; - int ret; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - sigfillset(&set); - pthread_sigmask(SIG_SETMASK, &set, &oldset); - ret = pthread_create(&thread, &attr, writeout_thread, NULL); - pthread_sigmask(SIG_SETMASK, &oldset, NULL); - - if (ret != 0) { - return false; - } - - atexit(st_flush_trace_buffer); - st_set_trace_file(file); - return true; -} diff --git a/simpletrace.h b/simpletrace.h deleted file mode 100644 index 507dd87..0000000 --- a/simpletrace.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Simple trace backend - * - * Copyright IBM, Corp. 2010 - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef SIMPLETRACE_H -#define SIMPLETRACE_H - -#include -#include -#include - -#ifdef CONFIG_TRACE_SIMPLE -typedef uint64_t TraceEventID; - -typedef struct { - const char *tp_name; - bool state; -} TraceEvent; - -void trace0(TraceEventID event); -void trace1(TraceEventID event, uint64_t x1); -void trace2(TraceEventID event, uint64_t x1, uint64_t x2); -void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3); -void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4); -void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5); -void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6); -void st_print_trace(FILE *stream, fprintf_function stream_printf); -void st_print_trace_events(FILE *stream, fprintf_function stream_printf); -bool st_change_trace_event_state(const char *tname, bool tstate); -void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); -void st_set_trace_file_enabled(bool enable); -bool st_set_trace_file(const char *file); -void st_flush_trace_buffer(void); -bool st_init(const char *file); -#else -static inline bool st_init(const char *file) -{ - return true; -} -#endif /* !CONFIG_TRACE_SIMPLE */ - -#endif /* SIMPLETRACE_H */ diff --git a/trace/simple.c b/trace/simple.c new file mode 100644 index 0000000..de355e9 --- /dev/null +++ b/trace/simple.c @@ -0,0 +1,355 @@ +/* + * Simple trace backend + * + * Copyright IBM, Corp. 2010 + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include +#include +#include +#include +#include +#include +#include "qemu-timer.h" +#include "trace.h" + +/** Trace file header event ID */ +#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ + +/** Trace file magic number */ +#define HEADER_MAGIC 0xf2b177cb0aa429b4ULL + +/** Trace file version number, bump if format changes */ +#define HEADER_VERSION 0 + +/** Records were dropped event ID */ +#define DROPPED_EVENT_ID (~(uint64_t)0 - 1) + +/** Trace record is valid */ +#define TRACE_RECORD_VALID ((uint64_t)1 << 63) + +/** Trace buffer entry */ +typedef struct { + uint64_t event; + uint64_t timestamp_ns; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; +} TraceRecord; + +enum { + TRACE_BUF_LEN = 4096, + TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4, +}; + +/* + * Trace records are written out by a dedicated thread. The thread waits for + * records to become available, writes them out, and then waits again. + */ +static pthread_mutex_t trace_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t trace_available_cond = PTHREAD_COND_INITIALIZER; +static pthread_cond_t trace_empty_cond = PTHREAD_COND_INITIALIZER; +static bool trace_available; +static bool trace_writeout_enabled; + +static TraceRecord trace_buf[TRACE_BUF_LEN]; +static unsigned int trace_idx; +static FILE *trace_fp; +static char *trace_file_name = NULL; + +/** + * Read a trace record from the trace buffer + * + * @idx Trace buffer index + * @record Trace record to fill + * + * Returns false if the record is not valid. + */ +static bool get_trace_record(unsigned int idx, TraceRecord *record) +{ + if (!(trace_buf[idx].event & TRACE_RECORD_VALID)) { + return false; + } + + __sync_synchronize(); /* read memory barrier before accessing record */ + + *record = trace_buf[idx]; + record->event &= ~TRACE_RECORD_VALID; + return true; +} + +/** + * Kick writeout thread + * + * @wait Whether to wait for writeout thread to complete + */ +static void flush_trace_file(bool wait) +{ + pthread_mutex_lock(&trace_lock); + trace_available = true; + pthread_cond_signal(&trace_available_cond); + + if (wait) { + pthread_cond_wait(&trace_empty_cond, &trace_lock); + } + + pthread_mutex_unlock(&trace_lock); +} + +static void wait_for_trace_records_available(void) +{ + pthread_mutex_lock(&trace_lock); + while (!(trace_available && trace_writeout_enabled)) { + pthread_cond_signal(&trace_empty_cond); + pthread_cond_wait(&trace_available_cond, &trace_lock); + } + trace_available = false; + pthread_mutex_unlock(&trace_lock); +} + +static void *writeout_thread(void *opaque) +{ + TraceRecord record; + unsigned int writeout_idx = 0; + unsigned int num_available, idx; + size_t unused __attribute__ ((unused)); + + for (;;) { + wait_for_trace_records_available(); + + num_available = trace_idx - writeout_idx; + if (num_available > TRACE_BUF_LEN) { + record = (TraceRecord){ + .event = DROPPED_EVENT_ID, + .x1 = num_available, + }; + unused = fwrite(&record, sizeof(record), 1, trace_fp); + writeout_idx += num_available; + } + + idx = writeout_idx % TRACE_BUF_LEN; + while (get_trace_record(idx, &record)) { + trace_buf[idx].event = 0; /* clear valid bit */ + unused = fwrite(&record, sizeof(record), 1, trace_fp); + idx = ++writeout_idx % TRACE_BUF_LEN; + } + + fflush(trace_fp); + } + return NULL; +} + +static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, uint64_t x5, uint64_t x6) +{ + unsigned int idx; + uint64_t timestamp; + + if (!trace_list[event].state) { + return; + } + + timestamp = get_clock(); + + idx = __sync_fetch_and_add(&trace_idx, 1) % TRACE_BUF_LEN; + trace_buf[idx] = (TraceRecord){ + .event = event, + .timestamp_ns = timestamp, + .x1 = x1, + .x2 = x2, + .x3 = x3, + .x4 = x4, + .x5 = x5, + .x6 = x6, + }; + __sync_synchronize(); /* write barrier before marking as valid */ + trace_buf[idx].event |= TRACE_RECORD_VALID; + + if ((idx + 1) % TRACE_BUF_FLUSH_THRESHOLD == 0) { + flush_trace_file(false); + } +} + +void trace0(TraceEventID event) +{ + trace(event, 0, 0, 0, 0, 0, 0); +} + +void trace1(TraceEventID event, uint64_t x1) +{ + trace(event, x1, 0, 0, 0, 0, 0); +} + +void trace2(TraceEventID event, uint64_t x1, uint64_t x2) +{ + trace(event, x1, x2, 0, 0, 0, 0); +} + +void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3) +{ + trace(event, x1, x2, x3, 0, 0, 0); +} + +void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4) +{ + trace(event, x1, x2, x3, x4, 0, 0); +} + +void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5) +{ + trace(event, x1, x2, x3, x4, x5, 0); +} + +void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6) +{ + trace(event, x1, x2, x3, x4, x5, x6); +} + +void st_set_trace_file_enabled(bool enable) +{ + if (enable == !!trace_fp) { + return; /* no change */ + } + + /* Halt trace writeout */ + flush_trace_file(true); + trace_writeout_enabled = false; + flush_trace_file(true); + + if (enable) { + static const TraceRecord header = { + .event = HEADER_EVENT_ID, + .timestamp_ns = HEADER_MAGIC, + .x1 = HEADER_VERSION, + }; + + trace_fp = fopen(trace_file_name, "w"); + if (!trace_fp) { + return; + } + + if (fwrite(&header, sizeof header, 1, trace_fp) != 1) { + fclose(trace_fp); + trace_fp = NULL; + return; + } + + /* Resume trace writeout */ + trace_writeout_enabled = true; + flush_trace_file(false); + } else { + fclose(trace_fp); + trace_fp = NULL; + } +} + +/** + * Set the name of a trace file + * + * @file The trace file name or NULL for the default name- set at + * config time + */ +bool st_set_trace_file(const char *file) +{ + st_set_trace_file_enabled(false); + + free(trace_file_name); + + 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; + } + } + + st_set_trace_file_enabled(true); + return true; +} + +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_fp ? "on" : "off"); +} + +void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) +{ + unsigned int i; + + for (i = 0; i < TRACE_BUF_LEN; i++) { + TraceRecord record; + + if (!get_trace_record(i, &record)) { + continue; + } + stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64 + " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n", + record.event, record.x1, record.x2, + record.x3, record.x4, record.x5, + record.x6); + } +} + +void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) +{ + unsigned int i; + + for (i = 0; i < NR_TRACE_EVENTS; i++) { + stream_printf(stream, "%s [Event ID %u] : state %u\n", + trace_list[i].tp_name, i, trace_list[i].state); + } +} + +bool st_change_trace_event_state(const char *name, bool enabled) +{ + unsigned int i; + + for (i = 0; i < NR_TRACE_EVENTS; i++) { + if (!strcmp(trace_list[i].tp_name, name)) { + trace_list[i].state = enabled; + return true; + } + } + return false; +} + +void st_flush_trace_buffer(void) +{ + flush_trace_file(true); +} + +bool st_init(const char *file) +{ + pthread_t thread; + pthread_attr_t attr; + sigset_t set, oldset; + int ret; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + sigfillset(&set); + pthread_sigmask(SIG_SETMASK, &set, &oldset); + ret = pthread_create(&thread, &attr, writeout_thread, NULL); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + + if (ret != 0) { + return false; + } + + atexit(st_flush_trace_buffer); + st_set_trace_file(file); + return true; +} diff --git a/trace/simple.h b/trace/simple.h new file mode 100644 index 0000000..77633ab --- /dev/null +++ b/trace/simple.h @@ -0,0 +1,48 @@ +/* + * Simple trace backend + * + * Copyright IBM, Corp. 2010 + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef TRACE_SIMPLE_H +#define TRACE_SIMPLE_H + +#include +#include +#include + +#ifdef CONFIG_TRACE_SIMPLE +typedef uint64_t TraceEventID; + +typedef struct { + const char *tp_name; + bool state; +} TraceEvent; + +void trace0(TraceEventID event); +void trace1(TraceEventID event, uint64_t x1); +void trace2(TraceEventID event, uint64_t x1, uint64_t x2); +void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3); +void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4); +void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5); +void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6); +void st_print_trace(FILE *stream, fprintf_function stream_printf); +void st_print_trace_events(FILE *stream, fprintf_function stream_printf); +bool st_change_trace_event_state(const char *tname, bool tstate); +void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); +void st_set_trace_file_enabled(bool enable); +bool st_set_trace_file(const char *file); +void st_flush_trace_buffer(void); +bool st_init(const char *file); +#else +static inline bool st_init(const char *file) +{ + return true; +} +#endif /* !CONFIG_TRACE_SIMPLE */ + +#endif /* TRACE_SIMPLE_H */ diff --git a/vl.c b/vl.c index 8c7aaaa..145d738 100644 --- a/vl.c +++ b/vl.c @@ -156,7 +156,7 @@ int main(int argc, char **argv) #include "slirp/libslirp.h" #include "trace.h" -#include "simpletrace.h" +#include "trace/simple.h" #include "qemu-queue.h" #include "cpus.h" #include "arch_init.h"