diff options
author | Peter Maydell | 2016-10-12 12:05:21 +0200 |
---|---|---|
committer | Peter Maydell | 2016-10-12 12:05:21 +0200 |
commit | ae4b28ace9554385eec50e2e330526159836c33d (patch) | |
tree | 1c4a0ac151d4096f7a16be82bd6533a698d85808 /trace | |
parent | build: Work around SIZE_MAX bug in OSX headers (diff) | |
parent | trace: Add missing execution mode of guest events (diff) | |
download | qemu-ae4b28ace9554385eec50e2e330526159836c33d.tar.gz qemu-ae4b28ace9554385eec50e2e330526159836c33d.tar.xz qemu-ae4b28ace9554385eec50e2e330526159836c33d.zip |
Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
# gpg: Signature made Wed 12 Oct 2016 09:43:03 BST
# gpg: using RSA key 0x9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8
* remotes/stefanha/tags/tracing-pull-request:
trace: Add missing execution mode of guest events
trace: introduce a formal group name for trace events
trace: pass trace-events to tracetool as a positional param
trace: push reading of events up a level to tracetool main
trace: rename _read_events to read_events
trace: get rid of generated-events.h/generated-events.c
trace: dynamically allocate event IDs at runtime
trace: dynamically allocate trace_dstate in CPUState
trace: provide mechanism for registering trace events
trace: don't abort qemu if ftrace can't be initialized
trace: emit name <-> ID mapping in simpletrace header
trace: remove the TraceEventID and TraceEventVCPUID enums
trace: give each trace event a named TraceEvent struct
trace: break circular dependency in event-internal.h
trace: remove duplicate control.h includes in generated-tracers.h
trace: remove global 'uint16 dstate[]' array
trace: remove some now unused functions
trace: convert code to use event iterators
trace: add trace event iterator APIs
trace: move colo trace events to net/ sub-directory
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'trace')
-rw-r--r-- | trace/Makefile.objs | 46 | ||||
-rw-r--r-- | trace/control-internal.h | 48 | ||||
-rw-r--r-- | trace/control-target.c | 35 | ||||
-rw-r--r-- | trace/control.c | 123 | ||||
-rw-r--r-- | trace/control.h | 112 | ||||
-rw-r--r-- | trace/event-internal.h | 18 | ||||
-rw-r--r-- | trace/ftrace.c | 6 | ||||
-rw-r--r-- | trace/qmp.c | 16 | ||||
-rw-r--r-- | trace/simple.c | 41 | ||||
-rw-r--r-- | trace/simple.h | 6 |
10 files changed, 227 insertions, 224 deletions
diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 24d3b3758c..1e1ce7479d 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -22,7 +22,7 @@ $(obj)/generated-ust-provider.h-timestamp: $(BUILD_DIR)/trace-events-all $(trace $(call quiet-command,$(TRACETOOL) \ --format=ust-events-h \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak @cmp $< $@ >/dev/null 2>&1 || cp $< $@ @@ -30,34 +30,13 @@ $(obj)/generated-ust.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y) $(call quiet-command,$(TRACETOOL) \ --format=ust-events-c \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") -$(obj)/generated-events.h: $(obj)/generated-ust-provider.h -$(obj)/generated-events.c: $(obj)/generated-ust.c +$(obj)/generated-tracers.h: $(obj)/generated-ust-provider.h +$(obj)/generated-tracers.c: $(obj)/generated-ust.c endif -###################################################################### -# Auto-generated event descriptions - -$(obj)/generated-events.h: $(obj)/generated-events.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-events.h-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --format=events-h \ - --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - -$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-events.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --format=events-c \ - --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - -util-obj-y += generated-events.o - ###################################################################### # Auto-generated tracing routines @@ -71,7 +50,7 @@ $(obj)/generated-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=h \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") ############################## # non-DTrace @@ -82,7 +61,7 @@ $(obj)/generated-tracers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=c \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h @@ -100,7 +79,7 @@ $(obj)/generated-tracers-dtrace.dtrace-timestamp: $(BUILD_DIR)/trace-events-all $(call quiet-command,$(TRACETOOL) \ --format=d \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace $(call quiet-command,dtrace -o $@ -h -s $<,"GEN","$@") @@ -119,7 +98,7 @@ $(obj)/generated-helpers-wrappers.h-timestamp: $(BUILD_DIR)/trace-events-all $(B $(call quiet-command,$(TRACETOOL) \ --format=tcg-helper-wrapper-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp @cmp $< $@ >/dev/null 2>&1 || cp $< $@ @@ -127,7 +106,7 @@ $(obj)/generated-helpers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=tcg-helper-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp @cmp $< $@ >/dev/null 2>&1 || cp $< $@ @@ -135,7 +114,7 @@ $(obj)/generated-helpers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=tcg-helper-c \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-helpers.o: $(obj)/generated-helpers.c @@ -148,13 +127,14 @@ $(obj)/generated-tcg-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_ $(call quiet-command,$(TRACETOOL) \ --format=tcg-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") ###################################################################### # Backend code -util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o generated-tracers.o +util-obj-y += generated-tracers.o +util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o util-obj-$(CONFIG_TRACE_UST) += generated-ust.o util-obj-y += control.o diff --git a/trace/control-internal.h b/trace/control-internal.h index a4e5f4aa06..a9d395a587 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -15,42 +15,29 @@ #include "qom/cpu.h" -extern TraceEvent trace_events[]; -extern uint16_t trace_events_dstate[]; extern int trace_events_enabled_count; -static inline TraceEventID trace_event_count(void) -{ - return TRACE_EVENT_COUNT; -} - -static inline TraceEvent *trace_event_id(TraceEventID id) -{ - assert(id < trace_event_count()); - return &trace_events[id]; -} - static inline bool trace_event_is_pattern(const char *str) { assert(str != NULL); return strchr(str, '*') != NULL; } -static inline TraceEventID trace_event_get_id(TraceEvent *ev) +static inline uint32_t trace_event_get_id(TraceEvent *ev) { assert(ev != NULL); return ev->id; } -static inline TraceEventVCPUID trace_event_get_vcpu_id(TraceEvent *ev) +static inline uint32_t trace_event_get_vcpu_id(TraceEvent *ev) { return ev->vcpu_id; } static inline bool trace_event_is_vcpu(TraceEvent *ev) { - return ev->vcpu_id != TRACE_VCPU_EVENT_COUNT; + return ev->vcpu_id != TRACE_VCPU_EVENT_NONE; } static inline const char * trace_event_get_name(TraceEvent *ev) @@ -65,26 +52,22 @@ static inline bool trace_event_get_state_static(TraceEvent *ev) return ev->sstate; } -static inline bool trace_event_get_state_dynamic_by_id(TraceEventID id) -{ - /* it's on fast path, avoid consistency checks (asserts) */ - return unlikely(trace_events_enabled_count) && trace_events_dstate[id]; -} +/* it's on fast path, avoid consistency checks (asserts) */ +#define trace_event_get_state_dynamic_by_id(id) \ + (unlikely(trace_events_enabled_count) && _ ## id ## _DSTATE) static inline bool trace_event_get_state_dynamic(TraceEvent *ev) { - TraceEventID id; - assert(trace_event_get_state_static(ev)); - id = trace_event_get_id(ev); - return trace_event_get_state_dynamic_by_id(id); + return unlikely(trace_events_enabled_count) && *ev->dstate; } -static inline bool trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu, - TraceEventVCPUID id) +static inline bool +trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu, + uint32_t vcpu_id) { /* it's on fast path, avoid consistency checks (asserts) */ if (unlikely(trace_events_enabled_count)) { - return test_bit(id, vcpu->trace_dstate); + return test_bit(vcpu_id, vcpu->trace_dstate); } else { return false; } @@ -93,10 +76,13 @@ static inline bool trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu, static inline bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev) { - TraceEventVCPUID id; + uint32_t vcpu_id; assert(trace_event_is_vcpu(ev)); - id = trace_event_get_vcpu_id(ev); - return trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, id); + vcpu_id = trace_event_get_vcpu_id(ev); + return trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, vcpu_id); } + +void trace_event_register_group(TraceEvent **events); + #endif /* TRACE__CONTROL_INTERNAL_H */ diff --git a/trace/control-target.c b/trace/control-target.c index 52fcce5a00..7ebf6e0bcb 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -16,21 +16,20 @@ void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state) { - TraceEventID id = trace_event_get_id(ev); bool state_pre; assert(trace_event_get_state_static(ev)); /* * We ignore the "vcpu" property here, since no vCPUs have been created * yet. Then dstate can only be 1 or 0. */ - state_pre = trace_events_dstate[id]; + state_pre = *ev->dstate; if (state_pre != state) { if (state) { trace_events_enabled_count++; - trace_events_dstate[id] = 1; + *ev->dstate = 1; } else { trace_events_enabled_count--; - trace_events_dstate[id] = 0; + *ev->dstate = 0; } } } @@ -45,15 +44,14 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state) } } else { /* Without the "vcpu" property, dstate can only be 1 or 0 */ - TraceEventID id = trace_event_get_id(ev); - bool state_pre = trace_events_dstate[id]; + bool state_pre = *ev->dstate; if (state_pre != state) { if (state) { trace_events_enabled_count++; - trace_events_dstate[id] = 1; + *ev->dstate = 1; } else { trace_events_enabled_count--; - trace_events_dstate[id] = 0; + *ev->dstate = 0; } } } @@ -62,23 +60,21 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state) void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev, bool state) { - TraceEventID id; - TraceEventVCPUID vcpu_id; + uint32_t vcpu_id; bool state_pre; assert(trace_event_get_state_static(ev)); assert(trace_event_is_vcpu(ev)); - id = trace_event_get_id(ev); vcpu_id = trace_event_get_vcpu_id(ev); state_pre = test_bit(vcpu_id, vcpu->trace_dstate); if (state_pre != state) { if (state) { trace_events_enabled_count++; set_bit(vcpu_id, vcpu->trace_dstate); - trace_events_dstate[id]++; + (*ev->dstate)++; } else { trace_events_enabled_count--; clear_bit(vcpu_id, vcpu->trace_dstate); - trace_events_dstate[id]--; + (*ev->dstate)--; } } } @@ -98,18 +94,18 @@ static bool adding_first_cpu(void) void trace_init_vcpu(CPUState *vcpu) { - TraceEvent *ev = NULL; - - while ((ev = trace_event_pattern("*", ev)) != NULL) { + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (trace_event_is_vcpu(ev) && trace_event_get_state_static(ev) && trace_event_get_state_dynamic(ev)) { - TraceEventID id = trace_event_get_id(ev); if (adding_first_cpu()) { /* check preconditions */ - assert(trace_events_dstate[id] == 1); + assert(*ev->dstate == 1); /* disable early-init state ... */ - trace_events_dstate[id] = 0; + *ev->dstate = 0; trace_events_enabled_count--; /* ... and properly re-enable */ trace_event_set_vcpu_state_dynamic(vcpu, ev, true); @@ -118,6 +114,5 @@ void trace_init_vcpu(CPUState *vcpu) } } } - trace_guest_cpu_enter(vcpu); } diff --git a/trace/control.c b/trace/control.c index 10b3e9baba..1a7bee6ddc 100644 --- a/trace/control.c +++ b/trace/control.c @@ -28,12 +28,15 @@ #include "monitor/monitor.h" int trace_events_enabled_count; -/* - * Interpretation depends on wether the event has the 'vcpu' property: - * - false: Boolean value indicating whether the event is active. - * - true : Integral counting the number of vCPUs that have this event enabled. - */ -uint16_t trace_events_dstate[TRACE_EVENT_COUNT]; + +typedef struct TraceEventGroup { + TraceEvent **events; +} TraceEventGroup; + +static TraceEventGroup *event_groups; +static size_t nevent_groups; +static uint32_t next_id; +static uint32_t next_vcpu_id; QemuOptsList qemu_trace_opts = { .name = "trace", @@ -56,13 +59,29 @@ QemuOptsList qemu_trace_opts = { }; +void trace_event_register_group(TraceEvent **events) +{ + size_t i; + for (i = 0; events[i] != NULL; i++) { + events[i]->id = next_id++; + if (events[i]->vcpu_id != TRACE_VCPU_EVENT_NONE) { + events[i]->vcpu_id = next_vcpu_id++; + } + } + event_groups = g_renew(TraceEventGroup, event_groups, nevent_groups + 1); + event_groups[nevent_groups].events = events; + nevent_groups++; +} + + TraceEvent *trace_event_name(const char *name) { assert(name != NULL); - TraceEventID i; - for (i = 0; i < trace_event_count(); i++) { - TraceEvent *ev = trace_event_id(i); + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (strcmp(trace_event_get_name(ev), name) == 0) { return ev; } @@ -101,25 +120,29 @@ static bool pattern_glob(const char *pat, const char *ev) } } -TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) -{ - assert(pat != NULL); - TraceEventID i; - - if (ev == NULL) { - i = -1; - } else { - i = trace_event_get_id(ev); - } - i++; +void trace_event_iter_init(TraceEventIter *iter, const char *pattern) +{ + iter->event = 0; + iter->group = 0; + iter->pattern = pattern; +} - while (i < trace_event_count()) { - TraceEvent *res = trace_event_id(i); - if (pattern_glob(pat, trace_event_get_name(res))) { - return res; +TraceEvent *trace_event_iter_next(TraceEventIter *iter) +{ + while (iter->group < nevent_groups && + event_groups[iter->group].events[iter->event] != NULL) { + TraceEvent *ev = event_groups[iter->group].events[iter->event]; + iter->event++; + if (event_groups[iter->group].events[iter->event] == NULL) { + iter->event = 0; + iter->group++; + } + if (!iter->pattern || + pattern_glob(iter->pattern, + trace_event_get_name(ev))) { + return ev; } - i++; } return NULL; @@ -127,10 +150,11 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) void trace_list_events(void) { - int i; - for (i = 0; i < trace_event_count(); i++) { - TraceEvent *res = trace_event_id(i); - fprintf(stderr, "%s\n", trace_event_get_name(res)); + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + fprintf(stderr, "%s\n", trace_event_get_name(ev)); } } @@ -138,26 +162,32 @@ static void do_trace_enable_events(const char *line_buf) { const bool enable = ('-' != line_buf[0]); const char *line_ptr = enable ? line_buf : line_buf + 1; + TraceEventIter iter; + TraceEvent *ev; + bool is_pattern = trace_event_is_pattern(line_ptr); - if (trace_event_is_pattern(line_ptr)) { - TraceEvent *ev = NULL; - while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { - if (trace_event_get_state_static(ev)) { - trace_event_set_state_dynamic_init(ev, enable); + trace_event_iter_init(&iter, line_ptr); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + if (!trace_event_get_state_static(ev)) { + if (!is_pattern) { + error_report("WARNING: trace event '%s' is not traceable", + line_ptr); + return; } + continue; } - } else { - TraceEvent *ev = trace_event_name(line_ptr); - if (ev == NULL) { - error_report("WARNING: trace event '%s' does not exist", - line_ptr); - } else if (!trace_event_get_state_static(ev)) { - error_report("WARNING: trace event '%s' is not traceable", - line_ptr); - } else { - trace_event_set_state_dynamic_init(ev, enable); + + /* start tracing */ + trace_event_set_state_dynamic(ev, enable); + if (!is_pattern) { + return; } } + + if (!is_pattern) { + error_report("WARNING: trace event '%s' does not exist", + line_ptr); + } } void trace_enable_events(const char *line_buf) @@ -269,3 +299,8 @@ char *trace_opt_parse(const char *optarg) return trace_file; } + +uint32_t trace_get_vcpu_event_count(void) +{ + return next_vcpu_id; +} diff --git a/trace/control.h b/trace/control.h index a22d11242e..ccaeac8552 100644 --- a/trace/control.h +++ b/trace/control.h @@ -11,35 +11,37 @@ #define TRACE__CONTROL_H #include "qemu-common.h" -#include "trace/generated-events.h" +#include "event-internal.h" + +typedef struct TraceEventIter { + size_t event; + size_t group; + const char *pattern; +} TraceEventIter; /** - * TraceEventID: - * - * Unique tracing event identifier. - * - * These are named as 'TRACE_${EVENT_NAME}'. + * trace_event_iter_init: + * @iter: the event iterator struct + * @pattern: optional pattern to filter events on name * - * See also: "trace/generated-events.h" + * Initialize the event iterator struct @iter, + * optionally using @pattern to filter out events + * with non-matching names. */ -enum TraceEventID; +void trace_event_iter_init(TraceEventIter *iter, const char *pattern); /** - * trace_event_id: - * @id: Event identifier. - * - * Get an event by its identifier. + * trace_event_iter_next: + * @iter: the event iterator struct * - * This routine has a constant cost, as opposed to trace_event_name and - * trace_event_pattern. - * - * Pre-conditions: The identifier is valid. - * - * Returns: pointer to #TraceEvent. + * Get the next event, if any. When this returns NULL, + * the iterator should no longer be used. * + * Returns: the next event, or NULL if no more events exist */ -static TraceEvent *trace_event_id(TraceEventID id); +TraceEvent *trace_event_iter_next(TraceEventIter *iter); + /** * trace_event_name: @@ -52,48 +54,29 @@ static TraceEvent *trace_event_id(TraceEventID id); TraceEvent *trace_event_name(const char *name); /** - * trace_event_pattern: - * @pat: Event name pattern. - * @ev: Event to start searching from (not included). - * - * Get all events with a given name pattern. - * - * Returns: pointer to #TraceEvent or NULL if not found. - */ -TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev); - -/** * trace_event_is_pattern: * * Whether the given string is an event name pattern. */ static bool trace_event_is_pattern(const char *str); -/** - * trace_event_count: - * - * Return the number of events. - */ -static TraceEventID trace_event_count(void); - - /** * trace_event_get_id: * * Get the identifier of an event. */ -static TraceEventID trace_event_get_id(TraceEvent *ev); +static uint32_t trace_event_get_id(TraceEvent *ev); /** * trace_event_get_vcpu_id: * * Get the per-vCPU identifier of an event. * - * Special value #TRACE_VCPU_EVENT_COUNT means the event is not vCPU-specific + * Special value #TRACE_VCPU_EVENT_NONE means the event is not vCPU-specific * (does not have the "vcpu" property). */ -static TraceEventVCPUID trace_event_get_vcpu_id(TraceEvent *ev); +static uint32_t trace_event_get_vcpu_id(TraceEvent *ev); /** * trace_event_is_vcpu: @@ -111,14 +94,12 @@ static const char * trace_event_get_name(TraceEvent *ev); /** * trace_event_get_state: - * @id: Event identifier. + * @id: Event identifier name. * * Get the tracing state of an event (both static and dynamic). * * If the event has the disabled property, the check will have no performance * impact. - * - * As a down side, you must always use an immediate #TraceEventID value. */ #define trace_event_get_state(id) \ ((id ##_ENABLED) && trace_event_get_state_dynamic_by_id(id)) @@ -126,19 +107,18 @@ static const char * trace_event_get_name(TraceEvent *ev); /** * trace_event_get_vcpu_state: * @vcpu: Target vCPU. - * @id: Event identifier (TraceEventID). - * @vcpu_id: Per-vCPU event identifier (TraceEventVCPUID). + * @id: Event identifier name. * * Get the tracing state of an event (both static and dynamic) for the given * vCPU. * * If the event has the disabled property, the check will have no performance * impact. - * - * As a down side, you must always use an immediate #TraceEventID value. */ -#define trace_event_get_vcpu_state(vcpu, id, vcpu_id) \ - ((id ##_ENABLED) && trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, vcpu_id)) +#define trace_event_get_vcpu_state(vcpu, id) \ + ((id ##_ENABLED) && \ + trace_event_get_vcpu_state_dynamic_by_vcpu_id( \ + vcpu, _ ## id ## _EVENT.vcpu_id)) /** * trace_event_get_state_static: @@ -167,31 +147,6 @@ static bool trace_event_get_state_dynamic(TraceEvent *ev); */ static bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev); -/** - * trace_event_set_state: - * - * Set the tracing state of an event (only if possible). - */ -#define trace_event_set_state(id, state) \ - do { \ - if ((id ##_ENABLED)) { \ - TraceEvent *_e = trace_event_id(id); \ - trace_event_set_state_dynamic(_e, state); \ - } \ - } while (0) - -/** - * trace_event_set_vcpu_state: - * - * Set the tracing state of an event for the given vCPU (only if not disabled). - */ -#define trace_event_set_vcpu_state(vcpu, id, state) \ - do { \ - if ((id ##_ENABLED)) { \ - TraceEvent *_e = trace_event_id(id); \ - trace_event_set_vcpu_state_dynamic(vcpu, _e, state); \ - } \ - } while (0) /** * trace_event_set_state_dynamic: @@ -277,6 +232,13 @@ extern QemuOptsList qemu_trace_opts; */ char *trace_opt_parse(const char *optarg); +/** + * trace_get_vcpu_event_count: + * + * Return the number of known vcpu-specific events + */ +uint32_t trace_get_vcpu_event_count(void); + #include "trace/control-internal.h" diff --git a/trace/event-internal.h b/trace/event-internal.h index 074faf6862..f63500b37e 100644 --- a/trace/event-internal.h +++ b/trace/event-internal.h @@ -10,8 +10,11 @@ #ifndef TRACE__EVENT_INTERNAL_H #define TRACE__EVENT_INTERNAL_H -#include "trace/generated-events.h" - +/* + * Special value for TraceEvent.vcpu_id field to indicate + * that the event is not VCPU specific + */ +#define TRACE_VCPU_EVENT_NONE ((uint32_t)-1) /** * TraceEvent: @@ -19,14 +22,21 @@ * @vcpu_id: Unique per-vCPU event identifier. * @name: Event name. * @sstate: Static tracing state. + * @dstate: Dynamic tracing state + * + * Interpretation of @dstate depends on whether the event has the 'vcpu' + * property: + * - false: Boolean value indicating whether the event is active. + * - true : Integral counting the number of vCPUs that have this event enabled. * * Opaque generic description of a tracing event. */ typedef struct TraceEvent { - TraceEventID id; - TraceEventVCPUID vcpu_id; + uint32_t id; + uint32_t vcpu_id; const char * name; const bool sstate; + uint16_t *dstate; } TraceEvent; void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state); diff --git a/trace/ftrace.c b/trace/ftrace.c index e953922f5b..3588bb0eb4 100644 --- a/trace/ftrace.c +++ b/trace/ftrace.c @@ -51,6 +51,12 @@ bool ftrace_init(void) snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs); trace_fd = open(path, O_WRONLY); if (trace_fd < 0) { + if (errno == EACCES) { + trace_marker_fd = open("/dev/null", O_WRONLY); + if (trace_marker_fd != -1) { + return true; + } + } perror("Could not open ftrace 'tracing_on' file"); return false; } else { diff --git a/trace/qmp.c b/trace/qmp.c index 11d2564e7b..ac777d154f 100644 --- a/trace/qmp.c +++ b/trace/qmp.c @@ -52,8 +52,10 @@ static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern return true; } else { /* error for unavailable events */ - TraceEvent *ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (!ignore_unavailable && !trace_event_get_state_static(ev)) { error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); return false; @@ -69,6 +71,7 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name, { Error *err = NULL; TraceEventInfoList *events = NULL; + TraceEventIter iter; TraceEvent *ev; bool is_pattern = trace_event_is_pattern(name); CPUState *cpu; @@ -86,8 +89,8 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name, } /* Get states (all errors checked above) */ - ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + trace_event_iter_init(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { TraceEventInfoList *elem; bool is_vcpu = trace_event_is_vcpu(ev); if (has_vcpu && !is_vcpu) { @@ -132,6 +135,7 @@ void qmp_trace_event_set_state(const char *name, bool enable, Error **errp) { Error *err = NULL; + TraceEventIter iter; TraceEvent *ev; bool is_pattern = trace_event_is_pattern(name); CPUState *cpu; @@ -150,8 +154,8 @@ void qmp_trace_event_set_state(const char *name, bool enable, } /* Apply changes (all errors checked above) */ - ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + trace_event_iter_init(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (!trace_event_get_state_static(ev) || (has_vcpu && !trace_event_is_vcpu(ev))) { continue; diff --git a/trace/simple.c b/trace/simple.c index 2f09dafcbc..b263622fa9 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -17,14 +17,14 @@ #include "trace/control.h" #include "trace/simple.h" -/** Trace file header event ID */ -#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ +/** Trace file header event ID, picked to avoid conflict with real event IDs */ +#define HEADER_EVENT_ID (~(uint64_t)0) /** Trace file magic number */ #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL /** Trace file version number, bump if format changes */ -#define HEADER_VERSION 3 +#define HEADER_VERSION 4 /** Records were dropped event ID */ #define DROPPED_EVENT_ID (~(uint64_t)0 - 1) @@ -56,9 +56,12 @@ static uint32_t trace_pid; static FILE *trace_fp; static char *trace_file_name; +#define TRACE_RECORD_TYPE_MAPPING 0 +#define TRACE_RECORD_TYPE_EVENT 1 + /* * Trace buffer entry */ typedef struct { - uint64_t event; /* TraceEventID */ + uint64_t event; /* event ID value */ uint64_t timestamp_ns; uint32_t length; /* in bytes */ uint32_t pid; @@ -160,6 +163,7 @@ static gpointer writeout_thread(gpointer opaque) unsigned int idx = 0; int dropped_count; size_t unused __attribute__ ((unused)); + uint64_t type = TRACE_RECORD_TYPE_EVENT; for (;;) { wait_for_trace_records_available(); @@ -174,10 +178,12 @@ static gpointer writeout_thread(gpointer opaque) } while (!g_atomic_int_compare_and_exchange(&dropped_events, dropped_count, 0)); dropped.rec.arguments[0] = dropped_count; + unused = fwrite(&type, sizeof(type), 1, trace_fp); unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp); } while (get_trace_record(idx, &recordptr)) { + unused = fwrite(&type, sizeof(type), 1, trace_fp); unused = fwrite(recordptr, recordptr->length, 1, trace_fp); writeout_idx += recordptr->length; free(recordptr); /* don't use g_free, can deadlock when traced */ @@ -202,7 +208,7 @@ void trace_record_write_str(TraceBufferRecord *rec, const char *s, uint32_t slen rec->rec_off = write_to_buffer(rec->rec_off, (void*)s, slen); } -int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasize) +int trace_record_start(TraceBufferRecord *rec, uint32_t event, size_t datasize) { unsigned int idx, rec_off, old_idx, new_idx; uint32_t rec_len = sizeof(TraceRecord) + datasize; @@ -273,6 +279,28 @@ void trace_record_finish(TraceBufferRecord *rec) } } +static int st_write_event_mapping(void) +{ + uint64_t type = TRACE_RECORD_TYPE_MAPPING; + TraceEventIter iter; + TraceEvent *ev; + + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + uint64_t id = trace_event_get_id(ev); + const char *name = trace_event_get_name(ev); + uint32_t len = strlen(name); + if (fwrite(&type, sizeof(type), 1, trace_fp) != 1 || + fwrite(&id, sizeof(id), 1, trace_fp) != 1 || + fwrite(&len, sizeof(len), 1, trace_fp) != 1 || + fwrite(name, len, 1, trace_fp) != 1) { + return -1; + } + } + + return 0; +} + void st_set_trace_file_enabled(bool enable) { if (enable == !!trace_fp) { @@ -297,7 +325,8 @@ void st_set_trace_file_enabled(bool enable) return; } - if (fwrite(&header, sizeof header, 1, trace_fp) != 1) { + if (fwrite(&header, sizeof header, 1, trace_fp) != 1 || + st_write_event_mapping() < 0) { fclose(trace_fp); trace_fp = NULL; return; diff --git a/trace/simple.h b/trace/simple.h index 1e7de45575..9931808c05 100644 --- a/trace/simple.h +++ b/trace/simple.h @@ -11,10 +11,6 @@ #ifndef TRACE_SIMPLE_H #define TRACE_SIMPLE_H - -#include "trace/generated-events.h" - - void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); void st_set_trace_file_enabled(bool enable); void st_set_trace_file(const char *file); @@ -33,7 +29,7 @@ typedef struct { * * @arglen number of bytes required for arguments */ -int trace_record_start(TraceBufferRecord *rec, TraceEventID id, size_t arglen); +int trace_record_start(TraceBufferRecord *rec, uint32_t id, size_t arglen); /** * Append a 64-bit argument to a trace record |