Merge remote-tracking branch 'stefanha/tracing' into staging

# By Markus Armbruster
# Via Stefan Hajnoczi
* stefanha/tracing:
  trace: Fix location of simpletrace.py in docs
  trace: Clean up the "try to update atomic until it worked" loops
  trace: Direct access of atomics is verboten, use the API
  trace: Fix simple trace dropped event record for big endian
This commit is contained in:
Anthony Liguori 2013-02-06 16:36:16 -06:00
commit 5b2cd9857d
2 changed files with 18 additions and 25 deletions

View File

@ -23,7 +23,7 @@ for debugging, profiling, and observing execution.
4. Pretty-print the binary trace file: 4. Pretty-print the binary trace file:
./simpletrace.py trace-events trace-* ./scripts/simpletrace.py trace-events trace-*
== Trace events == == Trace events ==
@ -198,7 +198,7 @@ The "simple" backend produces binary trace files that can be formatted with the
simpletrace.py script. The script takes the "trace-events" file and the binary simpletrace.py script. The script takes the "trace-events" file and the binary
trace: trace:
./simpletrace.py trace-events trace-12345 ./scripts/simpletrace.py trace-events trace-12345
You must ensure that the same "trace-events" file was used to build QEMU, You must ensure that the same "trace-events" file was used to build QEMU,
otherwise trace event declarations may have changed and output will not be otherwise trace event declarations may have changed and output will not be

View File

@ -53,7 +53,7 @@ enum {
uint8_t trace_buf[TRACE_BUF_LEN]; uint8_t trace_buf[TRACE_BUF_LEN];
static unsigned int trace_idx; static unsigned int trace_idx;
static unsigned int writeout_idx; static unsigned int writeout_idx;
static uint64_t dropped_events; static int dropped_events;
static FILE *trace_fp; static FILE *trace_fp;
static char *trace_file_name; static char *trace_file_name;
@ -63,7 +63,7 @@ typedef struct {
uint64_t timestamp_ns; uint64_t timestamp_ns;
uint32_t length; /* in bytes */ uint32_t length; /* in bytes */
uint32_t reserved; /* unused */ uint32_t reserved; /* unused */
uint8_t arguments[]; uint64_t arguments[];
} TraceRecord; } TraceRecord;
typedef struct { typedef struct {
@ -160,25 +160,22 @@ static gpointer writeout_thread(gpointer opaque)
uint8_t bytes[sizeof(TraceRecord) + sizeof(uint64_t)]; uint8_t bytes[sizeof(TraceRecord) + sizeof(uint64_t)];
} dropped; } dropped;
unsigned int idx = 0; unsigned int idx = 0;
uint64_t dropped_count; int dropped_count;
size_t unused __attribute__ ((unused)); size_t unused __attribute__ ((unused));
for (;;) { for (;;) {
wait_for_trace_records_available(); wait_for_trace_records_available();
if (dropped_events) { if (g_atomic_int_get(&dropped_events)) {
dropped.rec.event = DROPPED_EVENT_ID, dropped.rec.event = DROPPED_EVENT_ID,
dropped.rec.timestamp_ns = get_clock(); dropped.rec.timestamp_ns = get_clock();
dropped.rec.length = sizeof(TraceRecord) + sizeof(dropped_events), dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t),
dropped.rec.reserved = 0; dropped.rec.reserved = 0;
while (1) { do {
dropped_count = dropped_events; dropped_count = g_atomic_int_get(&dropped_events);
if (g_atomic_int_compare_and_exchange((gint *)&dropped_events, } while (!g_atomic_int_compare_and_exchange(&dropped_events,
dropped_count, 0)) { dropped_count, 0));
break; dropped.rec.arguments[0] = dropped_count;
}
}
memcpy(dropped.rec.arguments, &dropped_count, sizeof(uint64_t));
unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp); unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
} }
@ -213,22 +210,17 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
uint32_t rec_len = sizeof(TraceRecord) + datasize; uint32_t rec_len = sizeof(TraceRecord) + datasize;
uint64_t timestamp_ns = get_clock(); uint64_t timestamp_ns = get_clock();
while (1) { do {
old_idx = trace_idx; old_idx = g_atomic_int_get(&trace_idx);
smp_rmb(); smp_rmb();
new_idx = old_idx + rec_len; new_idx = old_idx + rec_len;
if (new_idx - writeout_idx > TRACE_BUF_LEN) { if (new_idx - writeout_idx > TRACE_BUF_LEN) {
/* Trace Buffer Full, Event dropped ! */ /* Trace Buffer Full, Event dropped ! */
g_atomic_int_inc((gint *)&dropped_events); g_atomic_int_inc(&dropped_events);
return -ENOSPC; return -ENOSPC;
} }
} while (!g_atomic_int_compare_and_exchange(&trace_idx, old_idx, new_idx));
if (g_atomic_int_compare_and_exchange((gint *)&trace_idx,
old_idx, new_idx)) {
break;
}
}
idx = old_idx % TRACE_BUF_LEN; idx = old_idx % TRACE_BUF_LEN;
@ -275,7 +267,8 @@ void trace_record_finish(TraceBufferRecord *rec)
record.event |= TRACE_RECORD_VALID; record.event |= TRACE_RECORD_VALID;
write_to_buffer(rec->tbuf_idx, &record, sizeof(TraceRecord)); write_to_buffer(rec->tbuf_idx, &record, sizeof(TraceRecord));
if ((trace_idx - writeout_idx) > TRACE_BUF_FLUSH_THRESHOLD) { if ((g_atomic_int_get(&trace_idx) - writeout_idx)
> TRACE_BUF_FLUSH_THRESHOLD) {
flush_trace_file(false); flush_trace_file(false);
} }
} }