From 6a1b0f3aea09142cb8989ccffb3b74bb8808a00f Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:42 +0100 Subject: trace: add trace event iterator APIs Currently methods which want to iterate over trace events, do so using the trace_event_count() and trace_event_id() methods. This leaks the concept of a single ID enum to the callers. There is an alternative trace_event_pattern() method which can be used in an iteration context, but its design is stateless, so is not easy to expand it in the future. This defines a formal iterator API will provide a future- proof way of iterating over events. The iterator is also able to apply a pattern match filter to events, further removing the need for the pattern Reviewed-by: Stefan Hajnoczi Reviewed-by: Lluís Vilanova Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-4-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- trace/control.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'trace/control.h') diff --git a/trace/control.h b/trace/control.h index a22d11242e..36d7cd23ed 100644 --- a/trace/control.h +++ b/trace/control.h @@ -13,6 +13,10 @@ #include "qemu-common.h" #include "trace/generated-events.h" +typedef struct TraceEventIter { + size_t event; + const char *pattern; +} TraceEventIter; /** * TraceEventID: @@ -25,6 +29,29 @@ */ enum TraceEventID; + +/** + * trace_event_iter_init: + * @iter: the event iterator struct + * @pattern: optional pattern to filter events on name + * + * Initialize the event iterator struct @iter, + * optionally using @pattern to filter out events + * with non-matching names. + */ +void trace_event_iter_init(TraceEventIter *iter, const char *pattern); + +/** + * trace_event_iter_next: + * @iter: the event iterator struct + * + * 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 + */ +TraceEvent *trace_event_iter_next(TraceEventIter *iter); + /** * trace_event_id: * @id: Event identifier. -- cgit v1.2.3-55-g7522 From 599ab2f241ee6693ea0a2700210718327b346f7f Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:44 +0100 Subject: trace: remove some now unused functions The trace_event_count, trace_event_id and trace_event_pattern methods are no longer required now that everything is using the iterator APIs The trace_event_set_state and trace_event_set_vcpu_state macros were also unused. Reviewed-by: Stefan Hajnoczi Reviewed-by: Lluís Vilanova Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-6-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- trace/control-internal.h | 11 --------- trace/control.c | 20 ---------------- trace/control.h | 59 ------------------------------------------------ 3 files changed, 90 deletions(-) (limited to 'trace/control.h') diff --git a/trace/control-internal.h b/trace/control-internal.h index a4e5f4aa06..7f31e39059 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -20,17 +20,6 @@ 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); diff --git a/trace/control.c b/trace/control.c index a107cc370f..a423f32eb0 100644 --- a/trace/control.c +++ b/trace/control.c @@ -102,26 +102,6 @@ static bool pattern_glob(const char *pat, const char *ev) } } -TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) -{ - assert(pat != NULL); - - bool matched = ev ? false : true; - TraceEventIter iter; - TraceEvent *thisev; - trace_event_iter_init(&iter, pat); - while ((thisev = trace_event_iter_next(&iter)) != NULL) { - if (matched) { - return thisev; - } else { - if (ev == thisev) { - matched = true; - } - } - } - - return NULL; -} void trace_event_iter_init(TraceEventIter *iter, const char *pattern) { diff --git a/trace/control.h b/trace/control.h index 36d7cd23ed..10d4aba78c 100644 --- a/trace/control.h +++ b/trace/control.h @@ -52,21 +52,6 @@ void trace_event_iter_init(TraceEventIter *iter, const char *pattern); */ TraceEvent *trace_event_iter_next(TraceEventIter *iter); -/** - * trace_event_id: - * @id: Event identifier. - * - * Get an event by its identifier. - * - * 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. - * - */ -static TraceEvent *trace_event_id(TraceEventID id); /** * trace_event_name: @@ -78,17 +63,6 @@ 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: * @@ -96,14 +70,6 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev); */ 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: @@ -194,31 +160,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: -- cgit v1.2.3-55-g7522 From ef4c9fc8542e06b1d567172c04b0c0377c7ab0c5 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:49 +0100 Subject: trace: remove the TraceEventID and TraceEventVCPUID enums The TraceEventID and TraceEventVCPUID enums constants are no longer actually used for anything critical. The TRACE_EVENT_COUNT limit is used to determine the size of the TraceEvents array, and can be removed if we just NULL terminate the array instead. The TRACE_VCPU_EVENT_COUNT limit is used as a magic value for marking non-vCPU events, and also for declaring the size of the trace dstate mask in the CPUState struct. The former usage can be replaced by a dedicated constant TRACE_EVENT_VCPU_NONE, defined as (uint32_t)-1. For the latter usage, we can simply define a constant for the number of VCPUs, avoiding the need for the full enum. The only other usages of the enum values can be replaced by accesing the id/vcpu_id fields via the named TraceEvent structs. Reviewed-by: Lluís Vilanova Reviewed-by: Stefan Hajnoczi Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-11-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- scripts/tracetool/backend/simple.py | 4 ++-- scripts/tracetool/format/events_c.py | 16 +++++++++++----- scripts/tracetool/format/events_h.py | 19 ++----------------- scripts/tracetool/format/h.py | 3 +-- trace/control-internal.h | 19 ++++++++++--------- trace/control-target.c | 2 +- trace/control.c | 2 +- trace/control.h | 32 +++++++++----------------------- trace/event-internal.h | 6 ++++++ trace/simple.c | 8 ++++---- trace/simple.h | 2 +- 11 files changed, 48 insertions(+), 65 deletions(-) (limited to 'trace/control.h') diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py index 1bccada63d..1114e3550b 100644 --- a/scripts/tracetool/backend/simple.py +++ b/scripts/tracetool/backend/simple.py @@ -80,11 +80,11 @@ def generate_c(event): ' return;', ' }', '', - ' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {', + ' if (trace_record_start(&rec, %(event_obj)s.id, %(size_str)s)) {', ' return; /* Trace Buffer Full, Event Dropped ! */', ' }', cond=cond, - event_id=event_id, + event_obj=event.api(event.QEMU_EVENT), size_str=sizestr) if len(event.args) > 0: diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py index a97054fd58..40ae39568e 100644 --- a/scripts/tracetool/format/events_c.py +++ b/scripts/tracetool/format/events_c.py @@ -28,11 +28,16 @@ def generate(events, backend): for e in events: out('uint16_t %s;' % e.api(e.QEMU_DSTATE)) + next_id = 0 + next_vcpu_id = 0 for e in events: + id = next_id + next_id += 1 if "vcpu" in e.properties: - vcpu_id = "TRACE_VCPU_" + e.name.upper() + vcpu_id = next_vcpu_id + next_vcpu_id += 1 else: - vcpu_id = "TRACE_VCPU_EVENT_COUNT" + vcpu_id = "TRACE_VCPU_EVENT_NONE" out('TraceEvent %(event)s = {', ' .id = %(id)s,', ' .vcpu_id = %(vcpu_id)s,', @@ -41,16 +46,17 @@ def generate(events, backend): ' .dstate = &%(dstate)s ', '};', event = e.api(e.QEMU_EVENT), - id = "TRACE_" + e.name.upper(), + id = id, vcpu_id = vcpu_id, name = e.name, sstate = "TRACE_%s_ENABLED" % e.name.upper(), dstate = e.api(e.QEMU_DSTATE)) - out('TraceEvent *trace_events[TRACE_EVENT_COUNT] = {') + out('TraceEvent *trace_events[] = {') for e in events: out(' &%(event)s,', event = e.api(e.QEMU_EVENT)) - out('};', + out(' NULL,', + '};', '') diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py index 80a66c57d5..ca6d730519 100644 --- a/scripts/tracetool/format/events_h.py +++ b/scripts/tracetool/format/events_h.py @@ -29,27 +29,12 @@ def generate(events, backend): out('extern TraceEvent %(event)s;', event = e.api(e.QEMU_EVENT)) - # event identifiers - out('typedef enum {') - - for e in events: - out(' TRACE_%s,' % e.name.upper()) - - out(' TRACE_EVENT_COUNT', - '} TraceEventID;') - for e in events: out('extern uint16_t %s;' % e.api(e.QEMU_DSTATE)) - # per-vCPU event identifiers - out('typedef enum {') - - for e in events: - if "vcpu" in e.properties: - out(' TRACE_VCPU_%s,' % e.name.upper()) + numvcpu = len([e for e in events if "vcpu" in e.properties]) - out(' TRACE_VCPU_EVENT_COUNT', - '} TraceEventVCPUID;') + out("#define TRACE_VCPU_EVENT_COUNT %d" % numvcpu) # static state for e in events: diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index 3763e9aecb..64a6680fdc 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -32,8 +32,7 @@ def generate(events, backend): if "vcpu" in e.properties: trace_cpu = next(iter(e.args))[1] cond = "trace_event_get_vcpu_state(%(cpu)s,"\ - " TRACE_%(id)s,"\ - " TRACE_VCPU_%(id)s)"\ + " TRACE_%(id)s)"\ % dict( cpu=trace_cpu, id=e.name.upper()) diff --git a/trace/control-internal.h b/trace/control-internal.h index 808f85dc06..9abbc96bcb 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -25,20 +25,20 @@ static inline bool trace_event_is_pattern(const char *str) 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) @@ -62,12 +62,13 @@ static inline bool trace_event_get_state_dynamic(TraceEvent *ev) 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; } @@ -76,10 +77,10 @@ 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); } #endif /* TRACE__CONTROL_INTERNAL_H */ diff --git a/trace/control-target.c b/trace/control-target.c index 3b55941414..7ebf6e0bcb 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -60,7 +60,7 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state) void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev, bool state) { - TraceEventVCPUID vcpu_id; + uint32_t vcpu_id; bool state_pre; assert(trace_event_get_state_static(ev)); assert(trace_event_is_vcpu(ev)); diff --git a/trace/control.c b/trace/control.c index 9035846b26..6b32511d60 100644 --- a/trace/control.c +++ b/trace/control.c @@ -105,7 +105,7 @@ void trace_event_iter_init(TraceEventIter *iter, const char *pattern) TraceEvent *trace_event_iter_next(TraceEventIter *iter) { - while (iter->event < TRACE_EVENT_COUNT) { + while (trace_events[iter->event] != NULL) { TraceEvent *ev = trace_events[iter->event]; iter->event++; if (!iter->pattern || diff --git a/trace/control.h b/trace/control.h index 10d4aba78c..cccd2a295e 100644 --- a/trace/control.h +++ b/trace/control.h @@ -18,17 +18,6 @@ typedef struct TraceEventIter { const char *pattern; } TraceEventIter; -/** - * TraceEventID: - * - * Unique tracing event identifier. - * - * These are named as 'TRACE_${EVENT_NAME}'. - * - * See also: "trace/generated-events.h" - */ -enum TraceEventID; - /** * trace_event_iter_init: @@ -76,17 +65,17 @@ static bool trace_event_is_pattern(const char *str); * * 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: @@ -104,14 +93,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)) @@ -119,19 +106,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: diff --git a/trace/event-internal.h b/trace/event-internal.h index 58f0551745..f63500b37e 100644 --- a/trace/event-internal.h +++ b/trace/event-internal.h @@ -10,6 +10,12 @@ #ifndef TRACE__EVENT_INTERNAL_H #define TRACE__EVENT_INTERNAL_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: * @id: Unique event identifier. diff --git a/trace/simple.c b/trace/simple.c index 2f09dafcbc..2ec32e159c 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -17,8 +17,8 @@ #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 @@ -58,7 +58,7 @@ static char *trace_file_name; /* * 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; @@ -202,7 +202,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; diff --git a/trace/simple.h b/trace/simple.h index 1e7de45575..17ce47260f 100644 --- a/trace/simple.h +++ b/trace/simple.h @@ -33,7 +33,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 -- cgit v1.2.3-55-g7522 From fe4db84d49545e669806d0cce12b3aa384e04ac3 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:52 +0100 Subject: trace: provide mechanism for registering trace events Remove the notion of there being a single global array of trace events, by introducing a method for registering groups of events. The module_call_init() needs to be invoked at the start of any program that wants to make use of the trace support. Currently this covers system emulators qemu-nbd, qemu-img and qemu-io. [Squashed the following fix from Daniel P. Berrange : linux-user/bsd-user: initialize trace events subsystem The bsd-user/linux-user programs make use of the CPU emulation code and this now requires that the trace events subsystem is enabled, otherwise it'll crash trying to allocate an empty trace events bitmap for the CPU object. --Stefan] Reviewed-by: Stefan Hajnoczi Reviewed-by: Lluís Vilanova Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-14-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- bsd-user/main.c | 1 + include/qemu/module.h | 2 ++ linux-user/main.c | 1 + qemu-img.c | 1 + qemu-io.c | 1 + qemu-nbd.c | 1 + scripts/tracetool/format/events_c.py | 6 ++++++ trace/control-internal.h | 4 +++- trace/control.c | 25 +++++++++++++++++++++++-- trace/control.h | 1 + vl.c | 2 ++ 11 files changed, 42 insertions(+), 3 deletions(-) (limited to 'trace/control.h') diff --git a/bsd-user/main.c b/bsd-user/main.c index d8367bda46..4fd7b6396d 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -740,6 +740,7 @@ int main(int argc, char **argv) if (argc <= 1) usage(); + module_call_init(MODULE_INIT_TRACE); qemu_init_cpu_list(); module_call_init(MODULE_INIT_QOM); diff --git a/include/qemu/module.h b/include/qemu/module.h index dc2c9d4c4e..877cca7d7b 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -44,6 +44,7 @@ typedef enum { MODULE_INIT_OPTS, MODULE_INIT_QAPI, MODULE_INIT_QOM, + MODULE_INIT_TRACE, MODULE_INIT_MAX } module_init_type; @@ -51,6 +52,7 @@ typedef enum { #define opts_init(function) module_init(function, MODULE_INIT_OPTS) #define qapi_init(function) module_init(function, MODULE_INIT_QAPI) #define type_init(function) module_init(function, MODULE_INIT_QOM) +#define trace_init(function) module_init(function, MODULE_INIT_TRACE) #define block_module_load_one(lib) module_load_one("block-", lib) diff --git a/linux-user/main.c b/linux-user/main.c index 9e4b430d66..0e31dad684 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4158,6 +4158,7 @@ int main(int argc, char **argv, char **envp) int ret; int execfd; + module_call_init(MODULE_INIT_TRACE); qemu_init_cpu_list(); module_call_init(MODULE_INIT_QOM); diff --git a/qemu-img.c b/qemu-img.c index ceffefeacb..02c07b913d 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -4165,6 +4165,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); #endif + module_call_init(MODULE_INIT_TRACE); error_set_progname(argv[0]); qemu_init_exec_dir(argv[0]); diff --git a/qemu-io.c b/qemu-io.c index db129eac5f..23a229f880 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -467,6 +467,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); #endif + module_call_init(MODULE_INIT_TRACE); progname = basename(argv[0]); qemu_init_exec_dir(argv[0]); diff --git a/qemu-nbd.c b/qemu-nbd.c index 705b95ec29..cca4a983b7 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -533,6 +533,7 @@ int main(int argc, char **argv) sa_sigterm.sa_handler = termsig_handler; sigaction(SIGTERM, &sa_sigterm, NULL); + module_call_init(MODULE_INIT_TRACE); qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py index 40ae39568e..88175559de 100644 --- a/scripts/tracetool/format/events_c.py +++ b/scripts/tracetool/format/events_c.py @@ -60,3 +60,9 @@ def generate(events, backend): out(' NULL,', '};', '') + + out('static void trace_register_events(void)', + '{', + ' trace_event_register_group(trace_events);', + '}', + 'trace_init(trace_register_events)') diff --git a/trace/control-internal.h b/trace/control-internal.h index 9abbc96bcb..a9d395a587 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -15,7 +15,6 @@ #include "qom/cpu.h" -extern TraceEvent *trace_events[]; extern int trace_events_enabled_count; @@ -83,4 +82,7 @@ static inline bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu, 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.c b/trace/control.c index 6b32511d60..a2313273d8 100644 --- a/trace/control.c +++ b/trace/control.c @@ -29,6 +29,13 @@ int trace_events_enabled_count; +typedef struct TraceEventGroup { + TraceEvent **events; +} TraceEventGroup; + +static TraceEventGroup *event_groups; +static size_t nevent_groups; + QemuOptsList qemu_trace_opts = { .name = "trace", .implied_opt_name = "enable", @@ -50,6 +57,14 @@ QemuOptsList qemu_trace_opts = { }; +void trace_event_register_group(TraceEvent **events) +{ + 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); @@ -100,14 +115,20 @@ static bool pattern_glob(const char *pat, const char *ev) void trace_event_iter_init(TraceEventIter *iter, const char *pattern) { iter->event = 0; + iter->group = 0; iter->pattern = pattern; } TraceEvent *trace_event_iter_next(TraceEventIter *iter) { - while (trace_events[iter->event] != NULL) { - TraceEvent *ev = trace_events[iter->event]; + 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))) { diff --git a/trace/control.h b/trace/control.h index cccd2a295e..3f30a0c2b7 100644 --- a/trace/control.h +++ b/trace/control.h @@ -15,6 +15,7 @@ typedef struct TraceEventIter { size_t event; + size_t group; const char *pattern; } TraceEventIter; diff --git a/vl.c b/vl.c index eb3c5ee348..c657acdd3c 100644 --- a/vl.c +++ b/vl.c @@ -3024,6 +3024,8 @@ int main(int argc, char **argv, char **envp) Error *err = NULL; bool list_data_dirs = false; + module_call_init(MODULE_INIT_TRACE); + qemu_init_cpu_list(); qemu_init_cpu_loop(); qemu_mutex_lock_iothread(); -- cgit v1.2.3-55-g7522 From b7d48952c375842bd669460fd8384d90cc12286c Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:53 +0100 Subject: trace: dynamically allocate trace_dstate in CPUState The CPUState struct has a bitmap tracking which VCPU events are currently active. This is indexed based on the event ID values, and sized according the maximum TraceEventVCPUID enum value. When we start dynamically assigning IDs at runtime, we can't statically declare a bitmap without making an assumption about the max event count. This problem can be solved by dynamically allocating the per-CPU dstate bitmap. Reviewed-by: Stefan Hajnoczi Reviewed-by: Lluís Vilanova Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-15-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- include/qom/cpu.h | 9 ++++++--- qom/cpu.c | 7 +++++-- trace/control.c | 5 +++++ trace/control.h | 7 +++++++ 4 files changed, 23 insertions(+), 5 deletions(-) (limited to 'trace/control.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 22b54d6d93..6d481a1dc0 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -27,7 +27,6 @@ #include "qemu/bitmap.h" #include "qemu/queue.h" #include "qemu/thread.h" -#include "trace/generated-events.h" typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -345,8 +344,12 @@ struct CPUState { struct KVMState *kvm_state; struct kvm_run *kvm_run; - /* Used for events with 'vcpu' and *without* the 'disabled' properties */ - DECLARE_BITMAP(trace_dstate, TRACE_VCPU_EVENT_COUNT); + /* + * Used for events with 'vcpu' and *without* the 'disabled' properties. + * Dynamically allocated based on bitmap requried to hold up to + * trace_get_vcpu_event_count() entries. + */ + unsigned long *trace_dstate; /* TODO Move common fields from CPUArchState here. */ int cpu_index; /* used by alpha TCG */ diff --git a/qom/cpu.c b/qom/cpu.c index e765bc0caf..c40f774a0c 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -360,12 +360,15 @@ static void cpu_common_initfn(Object *obj) qemu_mutex_init(&cpu->work_mutex); QTAILQ_INIT(&cpu->breakpoints); QTAILQ_INIT(&cpu->watchpoints); - bitmap_zero(cpu->trace_dstate, TRACE_VCPU_EVENT_COUNT); + + cpu->trace_dstate = bitmap_new(trace_get_vcpu_event_count()); } static void cpu_common_finalize(Object *obj) { - cpu_exec_exit(CPU(obj)); + CPUState *cpu = CPU(obj); + cpu_exec_exit(cpu); + g_free(cpu->trace_dstate); } static int64_t cpu_common_get_arch_id(CPUState *cpu) diff --git a/trace/control.c b/trace/control.c index a2313273d8..5f10e2d96e 100644 --- a/trace/control.c +++ b/trace/control.c @@ -290,3 +290,8 @@ char *trace_opt_parse(const char *optarg) return trace_file; } + +uint32_t trace_get_vcpu_event_count(void) +{ + return TRACE_VCPU_EVENT_COUNT; +} diff --git a/trace/control.h b/trace/control.h index 3f30a0c2b7..69635bfb8b 100644 --- a/trace/control.h +++ b/trace/control.h @@ -232,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" -- cgit v1.2.3-55-g7522 From 347701879ceaa9a03093364bc519042b248b4967 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Tue, 4 Oct 2016 14:35:55 +0100 Subject: trace: get rid of generated-events.h/generated-events.c Currently the generated-events.[ch] files contain the event dstates, constants and TraceEvent structs, while the generated-tracers.[ch] files contain the actual trace probe logic. With the removal of usage of the event enums from the API there is no longer any compelling reason for the separation between these files. The generated-events.h content is only ever needed from the generated-tracers.[ch] files. The enums/constants/structs from generated-events.[ch] are thus moved into the generated-tracers.[ch], so that there is one less file to be generated. Reviewed-by: Stefan Hajnoczi Reviewed-by: Lluís Vilanova Signed-off-by: Daniel P. Berrange Message-id: 1475588159-30598-17-git-send-email-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- Makefile | 3 -- include/trace-tcg.h | 1 - include/trace.h | 1 - scripts/tracetool/format/c.py | 50 ++++++++++++++++++++++++++--- scripts/tracetool/format/events_c.py | 62 ------------------------------------ scripts/tracetool/format/events_h.py | 49 ---------------------------- scripts/tracetool/format/h.py | 20 ++++++++++++ trace/Makefile.objs | 28 +++------------- trace/control.h | 2 +- trace/simple.h | 4 --- 10 files changed, 70 insertions(+), 150 deletions(-) delete mode 100644 scripts/tracetool/format/events_c.py delete mode 100644 scripts/tracetool/format/events_h.py (limited to 'trace/control.h') diff --git a/Makefile b/Makefile index 5f6acaed3b..3bcb0565b6 100644 --- a/Makefile +++ b/Makefile @@ -56,9 +56,6 @@ GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c GENERATED_HEADERS += qmp-introspect.h GENERATED_SOURCES += qmp-introspect.c -GENERATED_HEADERS += trace/generated-events.h -GENERATED_SOURCES += trace/generated-events.c - GENERATED_HEADERS += trace/generated-tracers.h ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace) GENERATED_HEADERS += trace/generated-tracers-dtrace.h diff --git a/include/trace-tcg.h b/include/trace-tcg.h index edab4b159c..da68608c85 100644 --- a/include/trace-tcg.h +++ b/include/trace-tcg.h @@ -2,6 +2,5 @@ #define TRACE_TCG_H #include "trace/generated-tcg-tracers.h" -#include "trace/generated-events.h" #endif /* TRACE_TCG_H */ diff --git a/include/trace.h b/include/trace.h index 9a01e4454b..ac9ff3dddd 100644 --- a/include/trace.h +++ b/include/trace.h @@ -2,6 +2,5 @@ #define TRACE_H #include "trace/generated-tracers.h" -#include "trace/generated-events.h" #endif /* TRACE_H */ diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py index 699598fb02..7ac6d4c508 100644 --- a/scripts/tracetool/format/c.py +++ b/scripts/tracetool/format/c.py @@ -17,12 +17,52 @@ from tracetool import out def generate(events, backend): - events = [e for e in events - if "disable" not in e.properties] + active_events = [e for e in events + if "disable" not in e.properties] out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#include "qemu/osdep.h"', + '#include "trace.h"', '') - backend.generate_begin(events) - for event in events: + + for e in events: + out('uint16_t %s;' % e.api(e.QEMU_DSTATE)) + + for e in events: + if "vcpu" in e.properties: + vcpu_id = 0 + else: + vcpu_id = "TRACE_VCPU_EVENT_NONE" + out('TraceEvent %(event)s = {', + ' .id = 0,', + ' .vcpu_id = %(vcpu_id)s,', + ' .name = \"%(name)s\",', + ' .sstate = %(sstate)s,', + ' .dstate = &%(dstate)s ', + '};', + event = e.api(e.QEMU_EVENT), + vcpu_id = vcpu_id, + name = e.name, + sstate = "TRACE_%s_ENABLED" % e.name.upper(), + dstate = e.api(e.QEMU_DSTATE)) + + out('TraceEvent *trace_events[] = {') + + for e in events: + out(' &%(event)s,', event = e.api(e.QEMU_EVENT)) + + out(' NULL,', + '};', + '') + + out('static void trace_register_events(void)', + '{', + ' trace_event_register_group(trace_events);', + '}', + 'trace_init(trace_register_events)') + + backend.generate_begin(active_events) + for event in active_events: backend.generate(event) - backend.generate_end(events) + backend.generate_end(active_events) diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py deleted file mode 100644 index a976c22c8b..0000000000 --- a/scripts/tracetool/format/events_c.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -trace/generated-events.c -""" - -__author__ = "Lluís Vilanova " -__copyright__ = "Copyright 2012-2016, Lluís Vilanova " -__license__ = "GPL version 2 or (at your option) any later version" - -__maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" - - -from tracetool import out - - -def generate(events, backend): - out('/* This file is autogenerated by tracetool, do not edit. */', - '', - '#include "qemu/osdep.h"', - '#include "trace.h"', - '#include "trace/generated-events.h"', - '#include "trace/control.h"', - '') - - for e in events: - out('uint16_t %s;' % e.api(e.QEMU_DSTATE)) - - for e in events: - if "vcpu" in e.properties: - vcpu_id = 0 - else: - vcpu_id = "TRACE_VCPU_EVENT_NONE" - out('TraceEvent %(event)s = {', - ' .id = 0,', - ' .vcpu_id = %(vcpu_id)s,', - ' .name = \"%(name)s\",', - ' .sstate = %(sstate)s,', - ' .dstate = &%(dstate)s ', - '};', - event = e.api(e.QEMU_EVENT), - vcpu_id = vcpu_id, - name = e.name, - sstate = "TRACE_%s_ENABLED" % e.name.upper(), - dstate = e.api(e.QEMU_DSTATE)) - - out('TraceEvent *trace_events[] = {') - - for e in events: - out(' &%(event)s,', event = e.api(e.QEMU_EVENT)) - - out(' NULL,', - '};', - '') - - out('static void trace_register_events(void)', - '{', - ' trace_event_register_group(trace_events);', - '}', - 'trace_init(trace_register_events)') diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py deleted file mode 100644 index 1cb332befc..0000000000 --- a/scripts/tracetool/format/events_h.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -trace/generated-events.h -""" - -__author__ = "Lluís Vilanova " -__copyright__ = "Copyright 2012-2016, Lluís Vilanova " -__license__ = "GPL version 2 or (at your option) any later version" - -__maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" - - -from tracetool import out - - -def generate(events, backend): - out('/* This file is autogenerated by tracetool, do not edit. */', - '', - '#ifndef TRACE__GENERATED_EVENTS_H', - '#define TRACE__GENERATED_EVENTS_H', - '', - '#include "trace/event-internal.h"', - ) - - for e in events: - out('extern TraceEvent %(event)s;', - event = e.api(e.QEMU_EVENT)) - - for e in events: - out('extern uint16_t %s;' % e.api(e.QEMU_DSTATE)) - - # static state - for e in events: - if 'disable' in e.properties: - enabled = 0 - else: - enabled = 1 - if "tcg-exec" in e.properties: - # a single define for the two "sub-events" - out('#define TRACE_%(name)s_ENABLED %(enabled)d', - name=e.original.name.upper(), - enabled=enabled) - out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled)) - - out('', - '#endif /* TRACE__GENERATED_EVENTS_H */') diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index 64a6680fdc..f4748c301f 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -26,6 +26,26 @@ def generate(events, backend): '#include "trace/control.h"', '') + for e in events: + out('extern TraceEvent %(event)s;', + event = e.api(e.QEMU_EVENT)) + + for e in events: + out('extern uint16_t %s;' % e.api(e.QEMU_DSTATE)) + + # static state + for e in events: + if 'disable' in e.properties: + enabled = 0 + else: + enabled = 1 + if "tcg-exec" in e.properties: + # a single define for the two "sub-events" + out('#define TRACE_%(name)s_ENABLED %(enabled)d', + name=e.original.name.upper(), + enabled=enabled) + out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled)) + backend.generate_begin(events) for e in events: diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 24d3b3758c..abac333094 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -32,32 +32,11 @@ $(obj)/generated-ust.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y) --backends=$(TRACE_BACKENDS) \ < $< > $@,"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 @@ -154,7 +133,8 @@ $(obj)/generated-tcg-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_ ###################################################################### # 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.h b/trace/control.h index 69635bfb8b..ccaeac8552 100644 --- a/trace/control.h +++ b/trace/control.h @@ -11,7 +11,7 @@ #define TRACE__CONTROL_H #include "qemu-common.h" -#include "trace/generated-events.h" +#include "event-internal.h" typedef struct TraceEventIter { size_t event; diff --git a/trace/simple.h b/trace/simple.h index 17ce47260f..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); -- cgit v1.2.3-55-g7522