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
<berrange@redhat.com>:

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 <stefanha@redhat.com>
Reviewed-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-id: 1475588159-30598-14-git-send-email-berrange@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Daniel P. Berrange 2016-10-04 14:35:52 +01:00 committed by Stefan Hajnoczi
parent 8ed5372874
commit fe4db84d49
11 changed files with 42 additions and 3 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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]);

View File

@ -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]);

View File

@ -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);

View File

@ -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)')

View File

@ -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 */

View File

@ -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))) {

View File

@ -15,6 +15,7 @@
typedef struct TraceEventIter {
size_t event;
size_t group;
const char *pattern;
} TraceEventIter;

2
vl.c
View File

@ -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();