Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
[qemu.git] / trace / control.c
1 /*
2 * Interface for configuring and controlling the state of tracing events.
3 *
4 * Copyright (C) 2011-2012 LluĂ­s Vilanova <vilanova@ac.upc.edu>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9
10 #include "trace/control.h"
11
12
13 TraceEvent *trace_event_name(const char *name)
14 {
15 assert(name != NULL);
16
17 TraceEventID i;
18 for (i = 0; i < trace_event_count(); i++) {
19 TraceEvent *ev = trace_event_id(i);
20 if (strcmp(trace_event_get_name(ev), name) == 0) {
21 return ev;
22 }
23 }
24 return NULL;
25 }
26
27 static bool pattern_glob(const char *pat, const char *ev)
28 {
29 while (*pat != '\0' && *ev != '\0') {
30 if (*pat == *ev) {
31 pat++;
32 ev++;
33 }
34 else if (*pat == '*') {
35 if (pattern_glob(pat, ev+1)) {
36 return true;
37 } else if (pattern_glob(pat+1, ev)) {
38 return true;
39 } else {
40 return false;
41 }
42 } else {
43 return false;
44 }
45 }
46
47 while (*pat == '*') {
48 pat++;
49 }
50
51 if (*pat == '\0' && *ev == '\0') {
52 return true;
53 } else {
54 return false;
55 }
56 }
57
58 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
59 {
60 assert(pat != NULL);
61
62 TraceEventID i;
63
64 if (ev == NULL) {
65 i = -1;
66 } else {
67 i = trace_event_get_id(ev);
68 }
69 i++;
70
71 while (i < trace_event_count()) {
72 TraceEvent *res = trace_event_id(i);
73 if (pattern_glob(pat, trace_event_get_name(res))) {
74 return res;
75 }
76 i++;
77 }
78
79 return NULL;
80 }
81
82 void trace_backend_init_events(const char *fname)
83 {
84 if (fname == NULL) {
85 return;
86 }
87
88 FILE *fp = fopen(fname, "r");
89 if (!fp) {
90 fprintf(stderr, "error: could not open trace events file '%s': %s\n",
91 fname, strerror(errno));
92 exit(1);
93 }
94 char line_buf[1024];
95 while (fgets(line_buf, sizeof(line_buf), fp)) {
96 size_t len = strlen(line_buf);
97 if (len > 1) { /* skip empty lines */
98 line_buf[len - 1] = '\0';
99 if ('#' == line_buf[0]) { /* skip commented lines */
100 continue;
101 }
102 const bool enable = ('-' != line_buf[0]);
103 char *line_ptr = enable ? line_buf : line_buf + 1;
104 if (trace_event_is_pattern(line_ptr)) {
105 TraceEvent *ev = NULL;
106 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
107 if (trace_event_get_state_static(ev)) {
108 trace_event_set_state_dynamic(ev, enable);
109 }
110 }
111 } else {
112 TraceEvent *ev = trace_event_name(line_ptr);
113 if (ev == NULL) {
114 fprintf(stderr,
115 "error: trace event '%s' does not exist\n", line_ptr);
116 exit(1);
117 }
118 if (!trace_event_get_state_static(ev)) {
119 fprintf(stderr,
120 "error: trace event '%s' is not traceable\n", line_ptr);
121 exit(1);
122 }
123 trace_event_set_state_dynamic(ev, enable);
124 }
125 }
126 }
127 if (fclose(fp) != 0) {
128 fprintf(stderr, "error: closing file '%s': %s\n",
129 fname, strerror(errno));
130 exit(1);
131 }
132 }