Statistics
| Branch: | Revision:

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
}