root / simpletrace.c @ 5dba48a8
History | View | Annotate | Download (5.9 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 | c57c846a | Blue Swirl | #include "qemu-timer.h" |
16 | 26f7227b | Stefan Hajnoczi | #include "trace.h" |
17 | 26f7227b | Stefan Hajnoczi | |
18 | 26f7227b | Stefan Hajnoczi | /** Trace file header event ID */
|
19 | 26f7227b | Stefan Hajnoczi | #define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ |
20 | 26f7227b | Stefan Hajnoczi | |
21 | 26f7227b | Stefan Hajnoczi | /** Trace file magic number */
|
22 | 26f7227b | Stefan Hajnoczi | #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL |
23 | 26f7227b | Stefan Hajnoczi | |
24 | 26f7227b | Stefan Hajnoczi | /** Trace file version number, bump if format changes */
|
25 | 26f7227b | Stefan Hajnoczi | #define HEADER_VERSION 0 |
26 | 26f7227b | Stefan Hajnoczi | |
27 | 26f7227b | Stefan Hajnoczi | /** Trace buffer entry */
|
28 | 26f7227b | Stefan Hajnoczi | typedef struct { |
29 | 26f7227b | Stefan Hajnoczi | uint64_t event; |
30 | 26f7227b | Stefan Hajnoczi | uint64_t timestamp_ns; |
31 | 26f7227b | Stefan Hajnoczi | uint64_t x1; |
32 | 26f7227b | Stefan Hajnoczi | uint64_t x2; |
33 | 26f7227b | Stefan Hajnoczi | uint64_t x3; |
34 | 26f7227b | Stefan Hajnoczi | uint64_t x4; |
35 | 26f7227b | Stefan Hajnoczi | uint64_t x5; |
36 | 26f7227b | Stefan Hajnoczi | uint64_t x6; |
37 | 26f7227b | Stefan Hajnoczi | } TraceRecord; |
38 | 26f7227b | Stefan Hajnoczi | |
39 | 26f7227b | Stefan Hajnoczi | enum {
|
40 | 26f7227b | Stefan Hajnoczi | TRACE_BUF_LEN = 64 * 1024 / sizeof(TraceRecord), |
41 | 26f7227b | Stefan Hajnoczi | }; |
42 | 26f7227b | Stefan Hajnoczi | |
43 | 26f7227b | Stefan Hajnoczi | static TraceRecord trace_buf[TRACE_BUF_LEN];
|
44 | 26f7227b | Stefan Hajnoczi | static unsigned int trace_idx; |
45 | 26f7227b | Stefan Hajnoczi | static FILE *trace_fp;
|
46 | c5ceb523 | Stefan Hajnoczi | static char *trace_file_name = NULL; |
47 | c5ceb523 | Stefan Hajnoczi | static bool trace_file_enabled = false; |
48 | c5ceb523 | Stefan Hajnoczi | |
49 | c5ceb523 | Stefan Hajnoczi | void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) |
50 | c5ceb523 | Stefan Hajnoczi | { |
51 | c5ceb523 | Stefan Hajnoczi | stream_printf(stream, "Trace file \"%s\" %s.\n",
|
52 | c5ceb523 | Stefan Hajnoczi | trace_file_name, trace_file_enabled ? "on" : "off"); |
53 | c5ceb523 | Stefan Hajnoczi | } |
54 | 26f7227b | Stefan Hajnoczi | |
55 | 26f7227b | Stefan Hajnoczi | static bool write_header(FILE *fp) |
56 | 26f7227b | Stefan Hajnoczi | { |
57 | 26f7227b | Stefan Hajnoczi | static const TraceRecord header = { |
58 | 26f7227b | Stefan Hajnoczi | .event = HEADER_EVENT_ID, |
59 | 26f7227b | Stefan Hajnoczi | .timestamp_ns = HEADER_MAGIC, |
60 | 26f7227b | Stefan Hajnoczi | .x1 = HEADER_VERSION, |
61 | 26f7227b | Stefan Hajnoczi | }; |
62 | 26f7227b | Stefan Hajnoczi | |
63 | 26f7227b | Stefan Hajnoczi | return fwrite(&header, sizeof header, 1, fp) == 1; |
64 | 26f7227b | Stefan Hajnoczi | } |
65 | 26f7227b | Stefan Hajnoczi | |
66 | c5ceb523 | Stefan Hajnoczi | /**
|
67 | c5ceb523 | Stefan Hajnoczi | * set_trace_file : To set the name of a trace file.
|
68 | c5ceb523 | Stefan Hajnoczi | * @file : pointer to the name to be set.
|
69 | c5ceb523 | Stefan Hajnoczi | * If NULL, set to the default name-<pid> set at config time.
|
70 | c5ceb523 | Stefan Hajnoczi | */
|
71 | c5ceb523 | Stefan Hajnoczi | bool st_set_trace_file(const char *file) |
72 | 9410b56c | Prerna Saxena | { |
73 | c5ceb523 | Stefan Hajnoczi | st_set_trace_file_enabled(false);
|
74 | c5ceb523 | Stefan Hajnoczi | |
75 | c5ceb523 | Stefan Hajnoczi | free(trace_file_name); |
76 | c5ceb523 | Stefan Hajnoczi | |
77 | c5ceb523 | Stefan Hajnoczi | if (!file) {
|
78 | c5ceb523 | Stefan Hajnoczi | if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) { |
79 | c5ceb523 | Stefan Hajnoczi | trace_file_name = NULL;
|
80 | c5ceb523 | Stefan Hajnoczi | return false; |
81 | c5ceb523 | Stefan Hajnoczi | } |
82 | c5ceb523 | Stefan Hajnoczi | } else {
|
83 | c5ceb523 | Stefan Hajnoczi | if (asprintf(&trace_file_name, "%s", file) < 0) { |
84 | c5ceb523 | Stefan Hajnoczi | trace_file_name = NULL;
|
85 | c5ceb523 | Stefan Hajnoczi | return false; |
86 | c5ceb523 | Stefan Hajnoczi | } |
87 | 9410b56c | Prerna Saxena | } |
88 | 9410b56c | Prerna Saxena | |
89 | c5ceb523 | Stefan Hajnoczi | st_set_trace_file_enabled(true);
|
90 | c5ceb523 | Stefan Hajnoczi | return true; |
91 | 9410b56c | Prerna Saxena | } |
92 | 9410b56c | Prerna Saxena | |
93 | c5ceb523 | Stefan Hajnoczi | static void flush_trace_file(void) |
94 | 26f7227b | Stefan Hajnoczi | { |
95 | c5ceb523 | Stefan Hajnoczi | /* If the trace file is not open yet, open it now */
|
96 | 26f7227b | Stefan Hajnoczi | if (!trace_fp) {
|
97 | c5ceb523 | Stefan Hajnoczi | trace_fp = fopen(trace_file_name, "w");
|
98 | c5ceb523 | Stefan Hajnoczi | if (!trace_fp) {
|
99 | c5ceb523 | Stefan Hajnoczi | /* Avoid repeatedly trying to open file on failure */
|
100 | c5ceb523 | Stefan Hajnoczi | trace_file_enabled = false;
|
101 | c5ceb523 | Stefan Hajnoczi | return;
|
102 | c5ceb523 | Stefan Hajnoczi | } |
103 | c5ceb523 | Stefan Hajnoczi | write_header(trace_fp); |
104 | 26f7227b | Stefan Hajnoczi | } |
105 | c5ceb523 | Stefan Hajnoczi | |
106 | 26f7227b | Stefan Hajnoczi | if (trace_fp) {
|
107 | 26f7227b | Stefan Hajnoczi | size_t unused; /* for when fwrite(3) is declared warn_unused_result */
|
108 | 26f7227b | Stefan Hajnoczi | unused = fwrite(trace_buf, trace_idx * sizeof(trace_buf[0]), 1, trace_fp); |
109 | 26f7227b | Stefan Hajnoczi | } |
110 | c5ceb523 | Stefan Hajnoczi | } |
111 | c5ceb523 | Stefan Hajnoczi | |
112 | c5ceb523 | Stefan Hajnoczi | void st_flush_trace_buffer(void) |
113 | c5ceb523 | Stefan Hajnoczi | { |
114 | c5ceb523 | Stefan Hajnoczi | if (trace_file_enabled) {
|
115 | c5ceb523 | Stefan Hajnoczi | flush_trace_file(); |
116 | c5ceb523 | Stefan Hajnoczi | } |
117 | 26f7227b | Stefan Hajnoczi | |
118 | 26f7227b | Stefan Hajnoczi | /* Discard written trace records */
|
119 | 26f7227b | Stefan Hajnoczi | trace_idx = 0;
|
120 | 26f7227b | Stefan Hajnoczi | } |
121 | 26f7227b | Stefan Hajnoczi | |
122 | 26f7227b | Stefan Hajnoczi | void st_set_trace_file_enabled(bool enable) |
123 | 26f7227b | Stefan Hajnoczi | { |
124 | 26f7227b | Stefan Hajnoczi | if (enable == trace_file_enabled) {
|
125 | 26f7227b | Stefan Hajnoczi | return; /* no change */ |
126 | 26f7227b | Stefan Hajnoczi | } |
127 | 26f7227b | Stefan Hajnoczi | |
128 | 26f7227b | Stefan Hajnoczi | /* Flush/discard trace buffer */
|
129 | 26f7227b | Stefan Hajnoczi | st_flush_trace_buffer(); |
130 | 26f7227b | Stefan Hajnoczi | |
131 | 26f7227b | Stefan Hajnoczi | /* To disable, close trace file */
|
132 | 26f7227b | Stefan Hajnoczi | if (!enable) {
|
133 | 26f7227b | Stefan Hajnoczi | fclose(trace_fp); |
134 | 26f7227b | Stefan Hajnoczi | trace_fp = NULL;
|
135 | 26f7227b | Stefan Hajnoczi | } |
136 | 26f7227b | Stefan Hajnoczi | |
137 | 26f7227b | Stefan Hajnoczi | trace_file_enabled = enable; |
138 | 26f7227b | Stefan Hajnoczi | } |
139 | 26f7227b | Stefan Hajnoczi | |
140 | 26f7227b | Stefan Hajnoczi | static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, |
141 | 26f7227b | Stefan Hajnoczi | uint64_t x4, uint64_t x5, uint64_t x6) |
142 | 26f7227b | Stefan Hajnoczi | { |
143 | 26f7227b | Stefan Hajnoczi | TraceRecord *rec = &trace_buf[trace_idx]; |
144 | 26f7227b | Stefan Hajnoczi | |
145 | 22890ab5 | Prerna Saxena | if (!trace_list[event].state) {
|
146 | 22890ab5 | Prerna Saxena | return;
|
147 | 22890ab5 | Prerna Saxena | } |
148 | 22890ab5 | Prerna Saxena | |
149 | 26f7227b | Stefan Hajnoczi | rec->event = event; |
150 | c57c846a | Blue Swirl | rec->timestamp_ns = get_clock(); |
151 | 26f7227b | Stefan Hajnoczi | rec->x1 = x1; |
152 | 26f7227b | Stefan Hajnoczi | rec->x2 = x2; |
153 | 26f7227b | Stefan Hajnoczi | rec->x3 = x3; |
154 | 26f7227b | Stefan Hajnoczi | rec->x4 = x4; |
155 | 26f7227b | Stefan Hajnoczi | rec->x5 = x5; |
156 | 26f7227b | Stefan Hajnoczi | rec->x6 = x6; |
157 | 26f7227b | Stefan Hajnoczi | |
158 | 26f7227b | Stefan Hajnoczi | if (++trace_idx == TRACE_BUF_LEN) {
|
159 | c5ceb523 | Stefan Hajnoczi | st_flush_trace_buffer(); |
160 | 26f7227b | Stefan Hajnoczi | } |
161 | 26f7227b | Stefan Hajnoczi | } |
162 | 26f7227b | Stefan Hajnoczi | |
163 | 26f7227b | Stefan Hajnoczi | void trace0(TraceEventID event)
|
164 | 26f7227b | Stefan Hajnoczi | { |
165 | 26f7227b | Stefan Hajnoczi | trace(event, 0, 0, 0, 0, 0, 0); |
166 | 26f7227b | Stefan Hajnoczi | } |
167 | 26f7227b | Stefan Hajnoczi | |
168 | 26f7227b | Stefan Hajnoczi | void trace1(TraceEventID event, uint64_t x1)
|
169 | 26f7227b | Stefan Hajnoczi | { |
170 | 26f7227b | Stefan Hajnoczi | trace(event, x1, 0, 0, 0, 0, 0); |
171 | 26f7227b | Stefan Hajnoczi | } |
172 | 26f7227b | Stefan Hajnoczi | |
173 | 26f7227b | Stefan Hajnoczi | void trace2(TraceEventID event, uint64_t x1, uint64_t x2)
|
174 | 26f7227b | Stefan Hajnoczi | { |
175 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, 0, 0, 0, 0); |
176 | 26f7227b | Stefan Hajnoczi | } |
177 | 26f7227b | Stefan Hajnoczi | |
178 | 26f7227b | Stefan Hajnoczi | void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3)
|
179 | 26f7227b | Stefan Hajnoczi | { |
180 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, 0, 0, 0); |
181 | 26f7227b | Stefan Hajnoczi | } |
182 | 26f7227b | Stefan Hajnoczi | |
183 | 26f7227b | Stefan Hajnoczi | void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4)
|
184 | 26f7227b | Stefan Hajnoczi | { |
185 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, 0, 0); |
186 | 26f7227b | Stefan Hajnoczi | } |
187 | 26f7227b | Stefan Hajnoczi | |
188 | 26f7227b | Stefan Hajnoczi | void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5)
|
189 | 26f7227b | Stefan Hajnoczi | { |
190 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, x5, 0);
|
191 | 26f7227b | Stefan Hajnoczi | } |
192 | 26f7227b | Stefan Hajnoczi | |
193 | 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)
|
194 | 26f7227b | Stefan Hajnoczi | { |
195 | 26f7227b | Stefan Hajnoczi | trace(event, x1, x2, x3, x4, x5, x6); |
196 | 26f7227b | Stefan Hajnoczi | } |
197 | 26f7227b | Stefan Hajnoczi | |
198 | 26f7227b | Stefan Hajnoczi | /**
|
199 | 26f7227b | Stefan Hajnoczi | * Flush the trace buffer on exit
|
200 | 26f7227b | Stefan Hajnoczi | */
|
201 | 26f7227b | Stefan Hajnoczi | static void __attribute__((constructor)) st_init(void) |
202 | 26f7227b | Stefan Hajnoczi | { |
203 | 26f7227b | Stefan Hajnoczi | atexit(st_flush_trace_buffer); |
204 | 26f7227b | Stefan Hajnoczi | } |
205 | 22890ab5 | Prerna Saxena | |
206 | 22890ab5 | Prerna Saxena | void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) |
207 | 22890ab5 | Prerna Saxena | { |
208 | 22890ab5 | Prerna Saxena | unsigned int i; |
209 | 22890ab5 | Prerna Saxena | |
210 | 22890ab5 | Prerna Saxena | for (i = 0; i < trace_idx; i++) { |
211 | a12c668f | Blue Swirl | stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64 |
212 | a12c668f | Blue Swirl | " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n", |
213 | 22890ab5 | Prerna Saxena | trace_buf[i].event, trace_buf[i].x1, trace_buf[i].x2, |
214 | a12c668f | Blue Swirl | trace_buf[i].x3, trace_buf[i].x4, trace_buf[i].x5, |
215 | a12c668f | Blue Swirl | trace_buf[i].x6); |
216 | 22890ab5 | Prerna Saxena | } |
217 | 22890ab5 | Prerna Saxena | } |
218 | 22890ab5 | Prerna Saxena | |
219 | 22890ab5 | Prerna Saxena | void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) |
220 | 22890ab5 | Prerna Saxena | { |
221 | 22890ab5 | Prerna Saxena | unsigned int i; |
222 | 22890ab5 | Prerna Saxena | |
223 | 22890ab5 | Prerna Saxena | for (i = 0; i < NR_TRACE_EVENTS; i++) { |
224 | 22890ab5 | Prerna Saxena | stream_printf(stream, "%s [Event ID %u] : state %u\n",
|
225 | 22890ab5 | Prerna Saxena | trace_list[i].tp_name, i, trace_list[i].state); |
226 | 22890ab5 | Prerna Saxena | } |
227 | 22890ab5 | Prerna Saxena | } |
228 | 22890ab5 | Prerna Saxena | |
229 | 22890ab5 | Prerna Saxena | static TraceEvent* find_trace_event_by_name(const char *tname) |
230 | 22890ab5 | Prerna Saxena | { |
231 | 22890ab5 | Prerna Saxena | unsigned int i; |
232 | 22890ab5 | Prerna Saxena | |
233 | 22890ab5 | Prerna Saxena | if (!tname) {
|
234 | 22890ab5 | Prerna Saxena | return NULL; |
235 | 22890ab5 | Prerna Saxena | } |
236 | 22890ab5 | Prerna Saxena | |
237 | 22890ab5 | Prerna Saxena | for (i = 0; i < NR_TRACE_EVENTS; i++) { |
238 | 22890ab5 | Prerna Saxena | if (!strcmp(trace_list[i].tp_name, tname)) {
|
239 | 22890ab5 | Prerna Saxena | return &trace_list[i];
|
240 | 22890ab5 | Prerna Saxena | } |
241 | 22890ab5 | Prerna Saxena | } |
242 | 22890ab5 | Prerna Saxena | return NULL; /* indicates end of list reached without a match */ |
243 | 22890ab5 | Prerna Saxena | } |
244 | 22890ab5 | Prerna Saxena | |
245 | f871d689 | Blue Swirl | bool st_change_trace_event_state(const char *tname, bool tstate) |
246 | 22890ab5 | Prerna Saxena | { |
247 | 22890ab5 | Prerna Saxena | TraceEvent *tp; |
248 | 22890ab5 | Prerna Saxena | |
249 | 22890ab5 | Prerna Saxena | tp = find_trace_event_by_name(tname); |
250 | 22890ab5 | Prerna Saxena | if (tp) {
|
251 | 22890ab5 | Prerna Saxena | tp->state = tstate; |
252 | f871d689 | Blue Swirl | return true; |
253 | 22890ab5 | Prerna Saxena | } |
254 | f871d689 | Blue Swirl | return false; |
255 | 22890ab5 | Prerna Saxena | } |