From: Nils Carlson Date: Wed, 8 Sep 2010 13:17:22 +0000 (+0200) Subject: Add trace_event structs X-Git-Tag: v0.8~23 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=0c0686eefbf60682c54bc4b3c0bc593250deedc1;p=ust.git Add trace_event structs Add trace_event structs, registration functions and trace_event iterator and locking functions. --- diff --git a/include/ust/tracepoint.h b/include/ust/tracepoint.h index 9c7c091..1c4a384 100644 --- a/include/ust/tracepoint.h +++ b/include/ust/tracepoint.h @@ -337,6 +337,63 @@ extern int tracepoint_unregister_lib(struct tracepoint *tracepoints_start); * TRACE_EVENT_FN to perform any (un)registration work. */ +struct trace_event { + const char *name; + int (*regfunc)(void *data); + int (*unregfunc)(void *data); +} __attribute__((aligned(32))); + +struct trace_event_lib { + struct trace_event *trace_events_start; + int trace_events_count; + struct list_head list; +}; + +struct trace_event_iter { + struct trace_event_lib *lib; + struct trace_event *trace_event; +}; + +extern void lock_trace_events(void); +extern void unlock_trace_events(void); + +extern void trace_event_iter_start(struct trace_event_iter *iter); +extern void trace_event_iter_next(struct trace_event_iter *iter); +extern void trace_event_iter_reset(struct trace_event_iter *iter); + +extern int trace_event_get_iter_range(struct trace_event **trace_event, + struct trace_event *begin, + struct trace_event *end); + +extern void trace_event_update_process(void); +extern int is_trace_event_enabled(const char *channel, const char *name); + +extern int trace_event_register_lib(struct trace_event *start_trace_events, + int trace_event_count); + +extern int trace_event_unregister_lib(struct trace_event *start_trace_events); + +#define TRACE_EVENT_LIB \ + extern struct trace_event __start___trace_events[] \ + __attribute__((weak, visibility("hidden"))); \ + extern struct trace_event __stop___trace_events[] \ + __attribute__((weak, visibility("hidden"))); \ + static void __attribute__((constructor)) \ + __trace_events__init(void) \ + { \ + long trace_event_count =((long)__stop___trace_events- \ + (long)__start___trace_events) \ + /sizeof(struct trace_event); \ + trace_event_register_lib(__start___trace_events, \ + trace_event_count); \ + } \ + \ + static void __attribute__((destructor)) \ + __trace_event__destroy(void) \ + { \ + trace_event_unregister_lib(__start___trace_events); \ + } + #define DECLARE_TRACE_EVENT_CLASS(name, proto, args, tstruct, assign, print) #define DEFINE_TRACE_EVENT(template, name, proto, args) \ DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) diff --git a/include/ust/ust_trace.h b/include/ust/ust_trace.h index e1b0257..01c241d 100644 --- a/include/ust/ust_trace.h +++ b/include/ust/ust_trace.h @@ -23,6 +23,8 @@ * to a printf */ +#include + /* * Stage 1. Create a struct and a printf calling function * that is connected to the tracepoint at load time. @@ -66,6 +68,20 @@ \ printf(print); \ } \ + static inline int register_event_##name(void *data) \ + { \ + return register_trace_##name(trace_printf_##name, data); \ + } \ + static inline int unregister_event_##name(void *data) \ + { \ + return unregister_trace_##name(trace_printf_##name, data); \ + } \ + struct trace_event __event_##name \ + __attribute__((section("__trace_events"), aligned(32))) = { \ + __tpstrtab_##name, \ + register_event_##name, \ + unregister_event_##name \ + }; \ static void __attribute__((constructor)) init_##name() \ { \ void *dummy; \ diff --git a/libust/Makefile.am b/libust/Makefile.am index a6051a8..697b469 100644 --- a/libust/Makefile.am +++ b/libust/Makefile.am @@ -6,6 +6,7 @@ lib_LTLIBRARIES = libust.la libust_la_SOURCES = \ marker.c \ tracepoint.c \ + trace_event.c \ channels.c \ channels.h \ marker-control.c \ diff --git a/libust/trace_event.c b/libust/trace_event.c new file mode 100644 index 0000000..af1e3fb --- /dev/null +++ b/libust/trace_event.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2010 Nils Carlson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include "usterr.h" + +#define _LGPL_SOURCE +#include + +/* libraries that contain trace_events (struct trace_event_lib) */ +static LIST_HEAD(libs); + +static DEFINE_MUTEX(trace_events_mutex); + +void lock_trace_events(void) +{ + pthread_mutex_lock(&trace_events_mutex); +} + +void unlock_trace_events(void) +{ + pthread_mutex_unlock(&trace_events_mutex); +} + + +int lib_get_iter_trace_events(struct trace_event_iter *iter) +{ + struct trace_event_lib *iter_lib; + int found = 0; + + list_for_each_entry(iter_lib, &libs, list) { + if (iter_lib < iter->lib) + continue; + else if (iter_lib > iter->lib) + iter->trace_event = NULL; + found = trace_event_get_iter_range(&iter->trace_event, + iter_lib->trace_events_start, + iter_lib->trace_events_start + iter_lib->trace_events_count); + if (found) { + iter->lib = iter_lib; + break; + } + } + return found; +} + +/** + * trace_event_get_iter_range - Get a next trace_event iterator given a range. + * @trace_event: current trace_events (in), next trace_event (out) + * @begin: beginning of the range + * @end: end of the range + * + * Returns whether a next trace_event has been found (1) or not (0). + * Will return the first trace_event in the range if the input trace_event is NULL. + */ +int trace_event_get_iter_range(struct trace_event **trace_event, struct trace_event *begin, + struct trace_event *end) +{ + if (!*trace_event && begin != end) { + *trace_event = begin; + return 1; + } + if (*trace_event >= begin && *trace_event < end) + return 1; + return 0; +} + +static void trace_event_get_iter(struct trace_event_iter *iter) +{ + int found = 0; + + found = lib_get_iter_trace_events(iter); +end: + if (!found) + trace_event_iter_reset(iter); +} + +void trace_event_iter_start(struct trace_event_iter *iter) +{ + trace_event_get_iter(iter); +} + +void trace_event_iter_next(struct trace_event_iter *iter) +{ + iter->trace_event++; + /* + * iter->trace_event may be invalid because we blindly incremented it. + * Make sure it is valid by marshalling on the trace_events, getting the + * trace_events from following modules if necessary. + */ + trace_event_get_iter(iter); +} + +void trace_event_iter_reset(struct trace_event_iter *iter) +{ + iter->lib = NULL; + iter->trace_event = NULL; +} + +int trace_event_register_lib(struct trace_event *trace_events_start, + int trace_events_count) +{ + struct trace_event_lib *pl; + + pl = (struct trace_event_lib *) malloc(sizeof(struct trace_event_lib)); + + pl->trace_events_start = trace_events_start; + pl->trace_events_count = trace_events_count; + + /* FIXME: maybe protect this with its own mutex? */ + pthread_mutex_lock(&trace_events_mutex); + list_add(&pl->list, &libs); + pthread_mutex_unlock(&trace_events_mutex); + + DBG("just registered a trace_events section from %p and having %d trace_events", trace_events_start, trace_events_count); + + return 0; +} + +int trace_event_unregister_lib(struct trace_event *trace_events_start) +{ + struct trace_event_lib *lib; + + pthread_mutex_lock(&trace_events_mutex); + + list_for_each_entry(lib, &libs, list) { + if(lib->trace_events_start == trace_events_start) { + struct trace_event_lib *lib2free = lib; + list_del(&lib->list); + free(lib2free); + break; + } + } + + pthread_mutex_unlock(&trace_events_mutex); + + return 0; +}