mirror of https://gitee.com/openkylin/qemu.git
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:
commit
5b2cd9857d
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue