X-Git-Url: https://git.liburcu.org/?p=ust.git;a=blobdiff_plain;f=libust%2Ftrace_event.c;h=854a7676b3586d10b84ece785eb97cb65f2aec3d;hp=d0d9ec455e36c132f8b3eed065517940f63583b3;hb=HEAD;hpb=fc1caebc8a71283c7766549ebed47300d1b52945 diff --git a/libust/trace_event.c b/libust/trace_event.c index d0d9ec4..854a767 100644 --- a/libust/trace_event.c +++ b/libust/trace_event.c @@ -3,8 +3,8 @@ * * 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. + * License as published by the Free Software Foundation; + * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,31 +17,45 @@ * */ +#define _LGPL_SOURCE #include #include +#include #include #include -#include "usterr.h" - -#define _LGPL_SOURCE #include +#include "usterr_signal_safe.h" + /* libraries that contain trace_events (struct trace_event_lib) */ static CDS_LIST_HEAD(libs); - +/* + * Nested mutex is not required here, but provide the same guaranteed + * for start/stop iteration vs nested ops as markers and tracepoints. + */ +static __thread int nested_mutex; static DEFINE_MUTEX(trace_events_mutex); +static +int trace_event_get_iter_range(struct trace_event * const **trace_event, + struct trace_event * const *begin, + struct trace_event * const *end); + +static void lock_trace_events(void) { - pthread_mutex_lock(&trace_events_mutex); + if (!(nested_mutex++)) + pthread_mutex_lock(&trace_events_mutex); } +static void unlock_trace_events(void) { - pthread_mutex_unlock(&trace_events_mutex); + if (!(--nested_mutex)) + pthread_mutex_unlock(&trace_events_mutex); } - +static int lib_get_iter_trace_events(struct trace_event_iter *iter) { struct trace_event_lib *iter_lib; @@ -71,17 +85,21 @@ int lib_get_iter_trace_events(struct trace_event_iter *iter) * * 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. + * Called with trace event mutex held. */ +static int trace_event_get_iter_range(struct trace_event * const **trace_event, struct trace_event * const *begin, struct trace_event * const *end) { - if (!*trace_event && begin != end) { + if (!*trace_event && begin != end) *trace_event = begin; - return 1; + while (*trace_event >= begin && *trace_event < end) { + if (!**trace_event) + (*trace_event)++; /* skip dummy */ + else + return 1; } - if (*trace_event >= begin && *trace_event < end) - return 1; return 0; } @@ -97,9 +115,13 @@ static void trace_event_get_iter(struct trace_event_iter *iter) void trace_event_iter_start(struct trace_event_iter *iter) { + lock_trace_events(); trace_event_get_iter(iter); } +/* + * Called with trace event mutex held. + */ void trace_event_iter_next(struct trace_event_iter *iter) { iter->trace_event++; @@ -111,6 +133,11 @@ void trace_event_iter_next(struct trace_event_iter *iter) trace_event_get_iter(iter); } +void trace_event_iter_stop(struct trace_event_iter *iter) +{ + unlock_trace_events(); +} + void trace_event_iter_reset(struct trace_event_iter *iter) { iter->lib = NULL; @@ -120,19 +147,32 @@ void trace_event_iter_reset(struct trace_event_iter *iter) int trace_event_register_lib(struct trace_event * const *trace_events_start, int trace_events_count) { - struct trace_event_lib *pl; + struct trace_event_lib *pl, *iter; 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); + lock_trace_events(); + /* + * We sort the libs by struct lib pointer address. + */ + cds_list_for_each_entry_reverse(iter, &libs, list) { + BUG_ON(iter == pl); /* Should never be in the list twice */ + if (iter < pl) { + /* We belong to the location right after iter. */ + cds_list_add(&pl->list, &iter->list); + goto lib_added; + } + } + /* We should be added at the head of the list */ cds_list_add(&pl->list, &libs); - pthread_mutex_unlock(&trace_events_mutex); +lib_added: + unlock_trace_events(); - DBG("just registered a trace_events section from %p and having %d trace_events", trace_events_start, trace_events_count); + /* trace_events_count - 1: skip dummy */ + DBG("just registered a trace_events section from %p and having %d trace_events (minus dummy trace_event)", trace_events_start, trace_events_count); return 0; } @@ -141,8 +181,7 @@ int trace_event_unregister_lib(struct trace_event * const *trace_events_start) { struct trace_event_lib *lib; - pthread_mutex_lock(&trace_events_mutex); - + unlock_trace_events(); cds_list_for_each_entry(lib, &libs, list) { if(lib->trace_events_start == trace_events_start) { struct trace_event_lib *lib2free = lib; @@ -151,8 +190,7 @@ int trace_event_unregister_lib(struct trace_event * const *trace_events_start) break; } } - - pthread_mutex_unlock(&trace_events_mutex); + unlock_trace_events(); return 0; }