root / trace / simple.c @ 454e202d
History | View | Annotate | Download (9.7 kB)
1 | 26f7227b | Stefan Hajnoczi | /*
|
---|---|---|---|
2 | 26f7227b | Stefan Hajnoczi | * Simple trace backend
|
3 | 26f7227b | Stefan Hajnoczi | *
|
4 | 26f7227b | Stefan Hajnoczi | * Copyright IBM, Corp. 2010
|
5 | 26f7227b | Stefan Hajnoczi | *
|
6 | 26f7227b | Stefan Hajnoczi | * This work is licensed under the terms of the GNU GPL, version 2. See
|
7 | 26f7227b | Stefan Hajnoczi | * the COPYING file in the top-level directory.
|
8 | 26f7227b | Stefan Hajnoczi | *
|
9 | 26f7227b | Stefan Hajnoczi | */
|
10 | 26f7227b | Stefan Hajnoczi | |
11 | 26f7227b | Stefan Hajnoczi | #include <stdlib.h> |
12 | 26f7227b | Stefan Hajnoczi | #include <stdint.h> |
13 | 26f7227b | Stefan Hajnoczi | #include <stdio.h> |
14 | 26f7227b | Stefan Hajnoczi | #include <time.h> |
15 | 85aff158 | Stefan Hajnoczi | #ifndef _WIN32
|
16 | 0b5538c3 | Stefan Hajnoczi | #include <signal.h> |
17 | 0b5538c3 | Stefan Hajnoczi | #include <pthread.h> |
18 | 85aff158 | Stefan Hajnoczi | #endif
|
19 | c57c846a | Blue Swirl | #include "qemu-timer.h" |
20 | 26f7227b | Stefan Hajnoczi | #include "trace.h" |
21 | e4858974 | Lluís | #include "trace/control.h" |
22 | 26f7227b | Stefan Hajnoczi | |
23 | 26f7227b | Stefan Hajnoczi | /** Trace file header event ID */
|
24 | 26f7227b | Stefan Hajnoczi | #define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ |
25 | 26f7227b | Stefan Hajnoczi | |
26 | 26f7227b | Stefan Hajnoczi | /** Trace file magic number */
|
27 | 26f7227b | Stefan Hajnoczi | #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL |
28 | 26f7227b | Stefan Hajnoczi | |
29 | 26f7227b | Stefan Hajnoczi | /** Trace file version number, bump if format changes */
|
30 | 26f7227b | Stefan Hajnoczi | #define HEADER_VERSION 0 |
31 | 26f7227b | Stefan Hajnoczi | |
32 | 0b5538c3 | Stefan Hajnoczi | /** Records were dropped event ID */
|
33 | 0b5538c3 | Stefan Hajnoczi | #define DROPPED_EVENT_ID (~(uint64_t)0 - 1) |
34 | 0b5538c3 | Stefan Hajnoczi | |
35 | 0b5538c3 | Stefan Hajnoczi | /** Trace record is valid */
|
36 | 0b5538c3 | Stefan Hajnoczi | #define TRACE_RECORD_VALID ((uint64_t)1 << 63) |
37 | 0b5538c3 | Stefan Hajnoczi | |
38 | 26f7227b | Stefan Hajnoczi | /** Trace buffer entry */
|
39 | 26f7227b | Stefan Hajnoczi | typedef struct { |
40 | 26f7227b | Stefan Hajnoczi | uint64_t event; |
41 | 26f7227b | Stefan Hajnoczi | uint64_t timestamp_ns; |
42 | 26f7227b | Stefan Hajnoczi | uint64_t x1; |
43 | 26f7227b | Stefan Hajnoczi | uint64_t x2; |
44 | 26f7227b | Stefan Hajnoczi | uint64_t x3; |
45 | 26f7227b | Stefan Hajnoczi | uint64_t x4; |
46 | 26f7227b | Stefan Hajnoczi | uint64_t x5; |
47 | 26f7227b | Stefan Hajnoczi | uint64_t x6; |
48 | 26f7227b | Stefan Hajnoczi | } TraceRecord; |
49 | 26f7227b | Stefan Hajnoczi | |
50 | 26f7227b | Stefan Hajnoczi | enum {
|
51 | 0b5538c3 | Stefan Hajnoczi | TRACE_BUF_LEN = 4096,
|
52 | 0b5538c3 | Stefan Hajnoczi | TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4,
|
53 | 26f7227b | Stefan Hajnoczi | }; |
54 | 26f7227b | Stefan Hajnoczi | |
55 | 0b5538c3 | Stefan Hajnoczi | /*
|
56 | 0b5538c3 | Stefan Hajnoczi | * Trace records are written out by a dedicated thread. The thread waits for
|
57 | 0b5538c3 | Stefan Hajnoczi | * records to become available, writes them out, and then waits again.
|
58 | 0b5538c3 | Stefan Hajnoczi | */
|
59 | 85aff158 | Stefan Hajnoczi | static GStaticMutex trace_lock = G_STATIC_MUTEX_INIT;
|
60 | 85aff158 | Stefan Hajnoczi | static GCond *trace_available_cond;
|
61 | 85aff158 | Stefan Hajnoczi | static GCond *trace_empty_cond;
|
62 | 0b5538c3 | Stefan Hajnoczi | static bool trace_available; |
63 | 0b5538c3 | Stefan Hajnoczi | static bool trace_writeout_enabled; |
64 | 0b5538c3 | Stefan Hajnoczi | |
65 | 26f7227b | Stefan Hajnoczi | static TraceRecord trace_buf[TRACE_BUF_LEN];
|
66 | 26f7227b | Stefan Hajnoczi | static unsigned int trace_idx; |
67 | 26f7227b | Stefan Hajnoczi | static FILE *trace_fp;
|
68 | c5ceb523 | Stefan Hajnoczi | static char *trace_file_name = NULL; |
69 | 26f7227b | Stefan Hajnoczi | |
70 | c5ceb523 | Stefan Hajnoczi | /**
|
71 | 0b5538c3 | Stefan Hajnoczi | * Read a trace record from the trace buffer
|
72 | 0b5538c3 | Stefan Hajnoczi | *
|
73 | 0b5538c3 | Stefan Hajnoczi | * @idx Trace buffer index
|
74 | 0b5538c3 | Stefan Hajnoczi | * @record Trace record to fill
|
75 | 0b5538c3 | Stefan Hajnoczi | *
|
76 | 0b5538c3 | Stefan Hajnoczi | * Returns false if the record is not valid.
|
77 | c5ceb523 | Stefan Hajnoczi | */
|
78 | 0b5538c3 | Stefan Hajnoczi | static bool get_trace_record(unsigned int idx, TraceRecord *record) |
79 | 9410b56c | Prerna Saxena | { |
80 | 0b5538c3 | Stefan Hajnoczi | if (!(trace_buf[idx].event & TRACE_RECORD_VALID)) {
|
81 | 0b5538c3 | Stefan Hajnoczi | return false; |
82 | 9410b56c | Prerna Saxena | } |
83 | 9410b56c | Prerna Saxena | |
84 | 0b5538c3 | Stefan Hajnoczi | __sync_synchronize(); /* read memory barrier before accessing record */
|
85 | 0b5538c3 | Stefan Hajnoczi | |
86 | 0b5538c3 | Stefan Hajnoczi | *record = trace_buf[idx]; |
87 | 0b5538c3 | Stefan Hajnoczi | record->event &= ~TRACE_RECORD_VALID; |
88 | c5ceb523 | Stefan Hajnoczi | return true; |
89 | 9410b56c | Prerna Saxena | } |
90 | 9410b56c | Prerna Saxena | |
91 | 0b5538c3 | Stefan Hajnoczi | /**
|
92 | 0b5538c3 | Stefan Hajnoczi | * Kick writeout thread
|
93 | 0b5538c3 | Stefan Hajnoczi | *
|
94 | 0b5538c3 | Stefan Hajnoczi | * @wait Whether to wait for writeout thread to complete
|
95 | 0b5538c3 | Stefan Hajnoczi | */
|
96 | 0b5538c3 | Stefan Hajnoczi | static void flush_trace_file(bool wait) |
97 | 26f7227b | Stefan Hajnoczi | { |
98 | 85aff158 | Stefan Hajnoczi | g_static_mutex_lock(&trace_lock); |
99 | 0b5538c3 | Stefan Hajnoczi | trace_available = true;
|
100 | 85aff158 | Stefan Hajnoczi | g_cond_signal(trace_available_cond); |
101 | c5ceb523 | Stefan Hajnoczi | |
102 | 0b5538c3 | Stefan Hajnoczi | if (wait) {
|
103 | 85aff158 | Stefan Hajnoczi | g_cond_wait(trace_empty_cond, g_static_mutex_get_mutex(&trace_lock)); |
104 | 26f7227b | Stefan Hajnoczi | } |
105 | 0b5538c3 | Stefan Hajnoczi | |
106 | 85aff158 | Stefan Hajnoczi | g_static_mutex_unlock(&trace_lock); |
107 | c5ceb523 | Stefan Hajnoczi | } |
108 | c5ceb523 | Stefan Hajnoczi | |
109 | 0b5538c3 | Stefan Hajnoczi | static void wait_for_trace_records_available(void) |
110 | c5ceb523 | Stefan Hajnoczi | { |
111 | 85aff158 | Stefan Hajnoczi | g_static_mutex_lock(&trace_lock); |
112 | 0b5538c3 | Stefan Hajnoczi | while (!(trace_available && trace_writeout_enabled)) {
|
113 | 85aff158 | Stefan Hajnoczi | g_cond_signal(trace_empty_cond); |
114 | 85aff158 | Stefan Hajnoczi | g_cond_wait(trace_available_cond, |
115 | 85aff158 | Stefan Hajnoczi | g_static_mutex_get_mutex(&trace_lock)); |
116 | c5ceb523 | Stefan Hajnoczi | } |
117 | 0b5538c3 | Stefan Hajnoczi | trace_available = false;
|
118 | 85aff158 | Stefan Hajnoczi | g_static_mutex_unlock(&trace_lock); |
119 | 26f7227b | Stefan Hajnoczi | } |
120 | 26f7227b | Stefan Hajnoczi | |
121 | 85aff158 | Stefan Hajnoczi | static gpointer writeout_thread(gpointer opaque)
|
122 | 26f7227b | Stefan Hajnoczi | { |
123 | 0b5538c3 | Stefan Hajnoczi | TraceRecord record; |
124 | 0b5538c3 | Stefan Hajnoczi | unsigned int writeout_idx = 0; |
125 | 0b5538c3 | Stefan Hajnoczi | unsigned int num_available, idx; |
126 | 0caf448b | Blue Swirl | size_t unused __attribute__ ((unused)); |
127 | 0b5538c3 | Stefan Hajnoczi | |
128 | 0b5538c3 | Stefan Hajnoczi | for (;;) {
|
129 | 0b5538c3 | Stefan Hajnoczi | wait_for_trace_records_available(); |
130 | 0b5538c3 | Stefan Hajnoczi | |
131 | 0b5538c3 | Stefan Hajnoczi | num_available = trace_idx - writeout_idx; |
132 | 0b5538c3 | Stefan Hajnoczi | if (num_available > TRACE_BUF_LEN) {
|
133 | 0b5538c3 | Stefan Hajnoczi | record = (TraceRecord){ |
134 | 0b5538c3 | Stefan Hajnoczi | .event = DROPPED_EVENT_ID, |
135 | 0b5538c3 | Stefan Hajnoczi | .x1 = num_available, |
136 | 0b5538c3 | Stefan Hajnoczi | }; |
137 | 0b5538c3 | Stefan Hajnoczi | unused = fwrite(&record, sizeof(record), 1, trace_fp); |
138 | 0b5538c3 | Stefan Hajnoczi | writeout_idx += num_available; |
139 | 0b5538c3 | Stefan Hajnoczi | } |
140 | 26f7227b | Stefan Hajnoczi | |
141 | 0b5538c3 | Stefan Hajnoczi | idx = writeout_idx % TRACE_BUF_LEN; |
142 | 0b5538c3 | Stefan Hajnoczi | while (get_trace_record(idx, &record)) {
|
143 | 0b5538c3 | Stefan Hajnoczi | trace_buf[idx].event = 0; /* clear valid bit */ |
144 | 0b5538c3 | Stefan Hajnoczi | unused = fwrite(&record, sizeof(record), 1, trace_fp); |
145 | 0b5538c3 | Stefan Hajnoczi | idx = ++writeout_idx % TRACE_BUF_LEN; |
146 | 0b5538c3 | Stefan Hajnoczi | } |
147 | 26f7227b | Stefan Hajnoczi | |
148 | 0b5538c3 | Stefan Hajnoczi | fflush(trace_fp); |
149 | 26f7227b | Stefan Hajnoczi | } |
150 | 0b5538c3 | Stefan Hajnoczi | return NULL; |
151 | 26f7227b | Stefan Hajnoczi | } |
152 | 26f7227b | Stefan Hajnoczi | |
153 | 26f7227b | Stefan Hajnoczi | static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, |
154 | 26f7227b | Stefan Hajnoczi | uint64_t x4, uint64_t x5, uint64_t x6) |
155 | 26f7227b | Stefan Hajnoczi | { |
156 | 0b5538c3 | Stefan Hajnoczi | unsigned int idx; |
157 | 0b5538c3 | Stefan Hajnoczi | uint64_t timestamp; |
158 | 26f7227b | Stefan Hajnoczi | |
159 | 22890ab5 | Prerna Saxena | if (!trace_list[event].state) {
|
160 | 22890ab5 | Prerna Saxena | return;
|
161 | 22890ab5 | Prerna Saxena | } |
162 | 22890ab5 | Prerna Saxena | |
163 | 0b5538c3 | Stefan Hajnoczi | timestamp = get_clock(); |
164 | 0b5538c3 | Stefan Hajnoczi | |
165 | 85aff158 | Stefan Hajnoczi | idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
|
166 | 0b5538c3 | Stefan Hajnoczi | trace_buf[idx] = (TraceRecord){ |
167 | 0b5538c3 | Stefan Hajnoczi | .event = event, |
168 | 0b5538c3 | Stefan Hajnoczi | .timestamp_ns = timestamp, |
169 | 0b5538c3 | Stefan Hajnoczi | .x1 = x1, |
170 | 0b5538c3 | Stefan Hajnoczi | .x2 = x2, |
171 | 0b5538c3 | Stefan Hajnoczi | .x3 = x3, |
172 | 0b5538c3 | Stefan Hajnoczi | .x4 = x4, |
173 | 0b5538c3 | Stefan Hajnoczi | .x5 = x5, |
174 | 0b5538c3 | Stefan Hajnoczi | .x6 = x6, |
175 | 0b5538c3 | Stefan Hajnoczi | }; |
176 | 0b5538c3 | Stefan Hajnoczi | __sync_synchronize(); /* write barrier before marking as valid */
|
177 | 0b5538c3 | Stefan Hajnoczi | trace_buf[idx].event |= TRACE_RECORD_VALID; |
178 | 0b5538c3 | Stefan Hajnoczi | |
179 | 0b5538c3 | Stefan Hajnoczi | if ((idx + 1) % TRACE_BUF_FLUSH_THRESHOLD == 0) { |
180 | 0b5538c3 | Stefan Hajnoczi | flush_trace_file(false);
|
181 | 26f7227b | Stefan Hajnoczi | } |
182 | 26f7227b | Stefan Hajnoczi | } |
183 | 26f7227b | Stefan Hajnoczi | |
184 | 26f7227b | Stefan Hajnoczi | void trace0(TraceEventID event)
|
185 | 26f7227b | Stefan Hajnoczi | { |
186 | 26f7227b | Stefan Hajnoczi | trace(event, 0, 0, 0, 0, 0, 0); |
187 | 26f7227b | Stefan Hajnoczi | } |
188 | 26f7227b | Stefan Hajnoczi | |
189 | 26f7227b | Stefan Hajnoczi | void trace1(TraceEventID event, uint64_t x1)
|
190 | 26f7227b | Stefan Hajnoczi | { |
191 | 26f7227b | Stefan Hajnoczi | trace(event, x1, 0, 0, 0, 0, 0); |
192 | 26f7227b | Stefan Hajnoczi | } |
193 | 26f7227b | Stefan Hajnoczi | |
194 | 26f7227b | Stefan Hajnoczi | void trace2(TraceEventID event, uint64_t x1, uint64_t x2)
|
195 | 26f7227b | Stefan Hajnoczi | { |
196 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, 0, 0, 0, 0); |
197 | 26f7227b | Stefan Hajnoczi | } |
198 | 26f7227b | Stefan Hajnoczi | |
199 | 26f7227b | Stefan Hajnoczi | void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3)
|
200 | 26f7227b | Stefan Hajnoczi | { |
201 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, 0, 0, 0); |
202 | 26f7227b | Stefan Hajnoczi | } |
203 | 26f7227b | Stefan Hajnoczi | |
204 | 26f7227b | Stefan Hajnoczi | void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4)
|
205 | 26f7227b | Stefan Hajnoczi | { |
206 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, 0, 0); |
207 | 26f7227b | Stefan Hajnoczi | } |
208 | 26f7227b | Stefan Hajnoczi | |
209 | 26f7227b | Stefan Hajnoczi | void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5)
|
210 | 26f7227b | Stefan Hajnoczi | { |
211 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, x5, 0);
|
212 | 26f7227b | Stefan Hajnoczi | } |
213 | 26f7227b | Stefan Hajnoczi | |
214 | 26f7227b | Stefan Hajnoczi | void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6)
|
215 | 26f7227b | Stefan Hajnoczi | { |
216 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, x5, x6); |
217 | 26f7227b | Stefan Hajnoczi | } |
218 | 26f7227b | Stefan Hajnoczi | |
219 | 0b5538c3 | Stefan Hajnoczi | void st_set_trace_file_enabled(bool enable) |
220 | 0b5538c3 | Stefan Hajnoczi | { |
221 | 0b5538c3 | Stefan Hajnoczi | if (enable == !!trace_fp) {
|
222 | 0b5538c3 | Stefan Hajnoczi | return; /* no change */ |
223 | 0b5538c3 | Stefan Hajnoczi | } |
224 | 0b5538c3 | Stefan Hajnoczi | |
225 | 0b5538c3 | Stefan Hajnoczi | /* Halt trace writeout */
|
226 | 0b5538c3 | Stefan Hajnoczi | flush_trace_file(true);
|
227 | 0b5538c3 | Stefan Hajnoczi | trace_writeout_enabled = false;
|
228 | 0b5538c3 | Stefan Hajnoczi | flush_trace_file(true);
|
229 | 0b5538c3 | Stefan Hajnoczi | |
230 | 0b5538c3 | Stefan Hajnoczi | if (enable) {
|
231 | 0b5538c3 | Stefan Hajnoczi | static const TraceRecord header = { |
232 | 0b5538c3 | Stefan Hajnoczi | .event = HEADER_EVENT_ID, |
233 | 0b5538c3 | Stefan Hajnoczi | .timestamp_ns = HEADER_MAGIC, |
234 | 0b5538c3 | Stefan Hajnoczi | .x1 = HEADER_VERSION, |
235 | 0b5538c3 | Stefan Hajnoczi | }; |
236 | 0b5538c3 | Stefan Hajnoczi | |
237 | 6c2a4074 | Stefan Hajnoczi | trace_fp = fopen(trace_file_name, "wb");
|
238 | 0b5538c3 | Stefan Hajnoczi | if (!trace_fp) {
|
239 | 0b5538c3 | Stefan Hajnoczi | return;
|
240 | 0b5538c3 | Stefan Hajnoczi | } |
241 | 0b5538c3 | Stefan Hajnoczi | |
242 | 0b5538c3 | Stefan Hajnoczi | if (fwrite(&header, sizeof header, 1, trace_fp) != 1) { |
243 | 0b5538c3 | Stefan Hajnoczi | fclose(trace_fp); |
244 | 0b5538c3 | Stefan Hajnoczi | trace_fp = NULL;
|
245 | 0b5538c3 | Stefan Hajnoczi | return;
|
246 | 0b5538c3 | Stefan Hajnoczi | } |
247 | 0b5538c3 | Stefan Hajnoczi | |
248 | 0b5538c3 | Stefan Hajnoczi | /* Resume trace writeout */
|
249 | 0b5538c3 | Stefan Hajnoczi | trace_writeout_enabled = true;
|
250 | 0b5538c3 | Stefan Hajnoczi | flush_trace_file(false);
|
251 | 0b5538c3 | Stefan Hajnoczi | } else {
|
252 | 0b5538c3 | Stefan Hajnoczi | fclose(trace_fp); |
253 | 0b5538c3 | Stefan Hajnoczi | trace_fp = NULL;
|
254 | 0b5538c3 | Stefan Hajnoczi | } |
255 | 0b5538c3 | Stefan Hajnoczi | } |
256 | 0b5538c3 | Stefan Hajnoczi | |
257 | 26f7227b | Stefan Hajnoczi | /**
|
258 | 0b5538c3 | Stefan Hajnoczi | * Set the name of a trace file
|
259 | 0b5538c3 | Stefan Hajnoczi | *
|
260 | 0b5538c3 | Stefan Hajnoczi | * @file The trace file name or NULL for the default name-<pid> set at
|
261 | 0b5538c3 | Stefan Hajnoczi | * config time
|
262 | 26f7227b | Stefan Hajnoczi | */
|
263 | 0b5538c3 | Stefan Hajnoczi | bool st_set_trace_file(const char *file) |
264 | 26f7227b | Stefan Hajnoczi | { |
265 | 0b5538c3 | Stefan Hajnoczi | st_set_trace_file_enabled(false);
|
266 | 0b5538c3 | Stefan Hajnoczi | |
267 | 0b5538c3 | Stefan Hajnoczi | free(trace_file_name); |
268 | 0b5538c3 | Stefan Hajnoczi | |
269 | 0b5538c3 | Stefan Hajnoczi | if (!file) {
|
270 | 0b5538c3 | Stefan Hajnoczi | if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) { |
271 | 0b5538c3 | Stefan Hajnoczi | trace_file_name = NULL;
|
272 | 0b5538c3 | Stefan Hajnoczi | return false; |
273 | 0b5538c3 | Stefan Hajnoczi | } |
274 | 0b5538c3 | Stefan Hajnoczi | } else {
|
275 | 0b5538c3 | Stefan Hajnoczi | if (asprintf(&trace_file_name, "%s", file) < 0) { |
276 | 0b5538c3 | Stefan Hajnoczi | trace_file_name = NULL;
|
277 | 0b5538c3 | Stefan Hajnoczi | return false; |
278 | 0b5538c3 | Stefan Hajnoczi | } |
279 | 0b5538c3 | Stefan Hajnoczi | } |
280 | 0b5538c3 | Stefan Hajnoczi | |
281 | 0b5538c3 | Stefan Hajnoczi | st_set_trace_file_enabled(true);
|
282 | 0b5538c3 | Stefan Hajnoczi | return true; |
283 | 0b5538c3 | Stefan Hajnoczi | } |
284 | 0b5538c3 | Stefan Hajnoczi | |
285 | 0b5538c3 | Stefan Hajnoczi | void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) |
286 | 0b5538c3 | Stefan Hajnoczi | { |
287 | 0b5538c3 | Stefan Hajnoczi | stream_printf(stream, "Trace file \"%s\" %s.\n",
|
288 | 0b5538c3 | Stefan Hajnoczi | trace_file_name, trace_fp ? "on" : "off"); |
289 | 26f7227b | Stefan Hajnoczi | } |
290 | 22890ab5 | Prerna Saxena | |
291 | 22890ab5 | Prerna Saxena | void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) |
292 | 22890ab5 | Prerna Saxena | { |
293 | 22890ab5 | Prerna Saxena | unsigned int i; |
294 | 22890ab5 | Prerna Saxena | |
295 | 0b5538c3 | Stefan Hajnoczi | for (i = 0; i < TRACE_BUF_LEN; i++) { |
296 | 0b5538c3 | Stefan Hajnoczi | TraceRecord record; |
297 | 0b5538c3 | Stefan Hajnoczi | |
298 | 0b5538c3 | Stefan Hajnoczi | if (!get_trace_record(i, &record)) {
|
299 | 0b5538c3 | Stefan Hajnoczi | continue;
|
300 | 0b5538c3 | Stefan Hajnoczi | } |
301 | a12c668f | Blue Swirl | stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64 |
302 | a12c668f | Blue Swirl | " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n", |
303 | 0b5538c3 | Stefan Hajnoczi | record.event, record.x1, record.x2, |
304 | 0b5538c3 | Stefan Hajnoczi | record.x3, record.x4, record.x5, |
305 | 0b5538c3 | Stefan Hajnoczi | record.x6); |
306 | 22890ab5 | Prerna Saxena | } |
307 | 22890ab5 | Prerna Saxena | } |
308 | 22890ab5 | Prerna Saxena | |
309 | fc764105 | Lluís | void st_flush_trace_buffer(void) |
310 | fc764105 | Lluís | { |
311 | fc764105 | Lluís | flush_trace_file(true);
|
312 | fc764105 | Lluís | } |
313 | fc764105 | Lluís | |
314 | fc764105 | Lluís | void trace_print_events(FILE *stream, fprintf_function stream_printf)
|
315 | 22890ab5 | Prerna Saxena | { |
316 | 22890ab5 | Prerna Saxena | unsigned int i; |
317 | 22890ab5 | Prerna Saxena | |
318 | 22890ab5 | Prerna Saxena | for (i = 0; i < NR_TRACE_EVENTS; i++) { |
319 | 22890ab5 | Prerna Saxena | stream_printf(stream, "%s [Event ID %u] : state %u\n",
|
320 | 22890ab5 | Prerna Saxena | trace_list[i].tp_name, i, trace_list[i].state); |
321 | 22890ab5 | Prerna Saxena | } |
322 | 22890ab5 | Prerna Saxena | } |
323 | 22890ab5 | Prerna Saxena | |
324 | fc764105 | Lluís | bool trace_event_set_state(const char *name, bool state) |
325 | 22890ab5 | Prerna Saxena | { |
326 | 22890ab5 | Prerna Saxena | unsigned int i; |
327 | 454e202d | Mark Wu | unsigned int len; |
328 | 454e202d | Mark Wu | bool wildcard = false; |
329 | 454e202d | Mark Wu | bool matched = false; |
330 | 454e202d | Mark Wu | |
331 | 454e202d | Mark Wu | len = strlen(name); |
332 | 454e202d | Mark Wu | if (len > 0 && name[len - 1] == '*') { |
333 | 454e202d | Mark Wu | wildcard = true;
|
334 | 454e202d | Mark Wu | len -= 1;
|
335 | 454e202d | Mark Wu | } |
336 | 22890ab5 | Prerna Saxena | for (i = 0; i < NR_TRACE_EVENTS; i++) { |
337 | 454e202d | Mark Wu | if (wildcard) {
|
338 | 454e202d | Mark Wu | if (!strncmp(trace_list[i].tp_name, name, len)) {
|
339 | 454e202d | Mark Wu | trace_list[i].state = state; |
340 | 454e202d | Mark Wu | matched = true;
|
341 | 454e202d | Mark Wu | } |
342 | 454e202d | Mark Wu | continue;
|
343 | 454e202d | Mark Wu | } |
344 | 0b5538c3 | Stefan Hajnoczi | if (!strcmp(trace_list[i].tp_name, name)) {
|
345 | fc764105 | Lluís | trace_list[i].state = state; |
346 | 0b5538c3 | Stefan Hajnoczi | return true; |
347 | 22890ab5 | Prerna Saxena | } |
348 | 22890ab5 | Prerna Saxena | } |
349 | 454e202d | Mark Wu | return matched;
|
350 | 0b5538c3 | Stefan Hajnoczi | } |
351 | 0b5538c3 | Stefan Hajnoczi | |
352 | 85aff158 | Stefan Hajnoczi | /* Helper function to create a thread with signals blocked. Use glib's
|
353 | 85aff158 | Stefan Hajnoczi | * portable threads since QEMU abstractions cannot be used due to reentrancy in
|
354 | 85aff158 | Stefan Hajnoczi | * the tracer. Also note the signal masking on POSIX hosts so that the thread
|
355 | 85aff158 | Stefan Hajnoczi | * does not steal signals when the rest of the program wants them blocked.
|
356 | 85aff158 | Stefan Hajnoczi | */
|
357 | 85aff158 | Stefan Hajnoczi | static GThread *trace_thread_create(GThreadFunc fn)
|
358 | 22890ab5 | Prerna Saxena | { |
359 | 85aff158 | Stefan Hajnoczi | GThread *thread; |
360 | 85aff158 | Stefan Hajnoczi | #ifndef _WIN32
|
361 | 0b5538c3 | Stefan Hajnoczi | sigset_t set, oldset; |
362 | 22890ab5 | Prerna Saxena | |
363 | 0b5538c3 | Stefan Hajnoczi | sigfillset(&set); |
364 | 0b5538c3 | Stefan Hajnoczi | pthread_sigmask(SIG_SETMASK, &set, &oldset); |
365 | 85aff158 | Stefan Hajnoczi | #endif
|
366 | 85aff158 | Stefan Hajnoczi | thread = g_thread_create(writeout_thread, NULL, FALSE, NULL); |
367 | 85aff158 | Stefan Hajnoczi | #ifndef _WIN32
|
368 | 0b5538c3 | Stefan Hajnoczi | pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
369 | 85aff158 | Stefan Hajnoczi | #endif
|
370 | 0b5538c3 | Stefan Hajnoczi | |
371 | 85aff158 | Stefan Hajnoczi | return thread;
|
372 | 85aff158 | Stefan Hajnoczi | } |
373 | 85aff158 | Stefan Hajnoczi | |
374 | 85aff158 | Stefan Hajnoczi | bool trace_backend_init(const char *events, const char *file) |
375 | 85aff158 | Stefan Hajnoczi | { |
376 | 85aff158 | Stefan Hajnoczi | GThread *thread; |
377 | 85aff158 | Stefan Hajnoczi | |
378 | 85aff158 | Stefan Hajnoczi | if (!g_thread_supported()) {
|
379 | 85aff158 | Stefan Hajnoczi | g_thread_init(NULL);
|
380 | 85aff158 | Stefan Hajnoczi | } |
381 | 85aff158 | Stefan Hajnoczi | |
382 | 85aff158 | Stefan Hajnoczi | trace_available_cond = g_cond_new(); |
383 | 85aff158 | Stefan Hajnoczi | trace_empty_cond = g_cond_new(); |
384 | 85aff158 | Stefan Hajnoczi | |
385 | 85aff158 | Stefan Hajnoczi | thread = trace_thread_create(writeout_thread); |
386 | 85aff158 | Stefan Hajnoczi | if (!thread) {
|
387 | e4858974 | Lluís | fprintf(stderr, "warning: unable to initialize simple trace backend\n");
|
388 | 85aff158 | Stefan Hajnoczi | return false; |
389 | 22890ab5 | Prerna Saxena | } |
390 | 0b5538c3 | Stefan Hajnoczi | |
391 | 85aff158 | Stefan Hajnoczi | atexit(st_flush_trace_buffer); |
392 | 85aff158 | Stefan Hajnoczi | trace_backend_init_events(events); |
393 | 85aff158 | Stefan Hajnoczi | st_set_trace_file(file); |
394 | 31d3c9b8 | Stefan Hajnoczi | return true; |
395 | 22890ab5 | Prerna Saxena | } |