X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=libust%2Ftracepoint.c;h=1a18463667d3bdac31c67855a99c28b79c0c3ccd;hb=5810472cfda38ae6108e577d163d63158b960519;hp=67619a85d8e36933af87d57035fb3671452fe406;hpb=5e96a46756a5dcd6e348afd84078b9e26438245d;p=lttng-ust.git diff --git a/libust/tracepoint.c b/libust/tracepoint.c index 67619a85..1a184636 100644 --- a/libust/tracepoint.c +++ b/libust/tracepoint.c @@ -27,16 +27,10 @@ #include #include #include +#include -#include "usterr_signal_safe.h" - -extern struct tracepoint * const __start___tracepoints_ptrs[] - __attribute__((visibility("hidden"))); -extern struct tracepoint * const __stop___tracepoints_ptrs[] - __attribute__((visibility("hidden"))); - -static struct tracepoint * __tracepoint_ptr_dummy - __attribute__((used, section("__tracepoints_ptrs"))); +#include +#include "ltt-tracer-core.h" /* Set to 1 to enable tracepoint debug output */ static const int tracepoint_debug; @@ -47,29 +41,12 @@ static void (*new_tracepoint_cb)(struct tracepoint *); static CDS_LIST_HEAD(libs); /* - * Allow nested mutex for mutex listing and nested enable. - */ -static __thread int nested_mutex; - -/* - * Tracepoints mutex protects the library tracepoints, the hash table, - * and the library list. + * The UST lock protects the library tracepoints, the hash table, and + * the library list. + * All calls to the tracepoint API must be protected by the UST lock, + * excepts calls to tracepoint_register_lib and + * tracepoint_unregister_lib, which take the UST lock themselves. */ -static pthread_mutex_t tracepoints_mutex; - -static -void lock_tracepoints(void) -{ - if (!(nested_mutex++)) - pthread_mutex_lock(&tracepoints_mutex); -} - -static -void unlock_tracepoints(void) -{ - if (!(--nested_mutex)) - pthread_mutex_unlock(&tracepoints_mutex); -} /* * Tracepoint hash table, containing the active tracepoints. @@ -264,7 +241,7 @@ static struct tracepoint_entry *add_tracepoint(const char *name) /* * Remove the tracepoint from the tracepoint hash table. Must be called with - * mutex_lock held. + * ust_lock held. */ static inline void remove_tracepoint(struct tracepoint_entry *e) { @@ -338,12 +315,10 @@ static void lib_update_tracepoints(void) { struct tracepoint_lib *lib; - lock_tracepoints(); cds_list_for_each_entry(lib, &libs, list) { tracepoint_update_probe_range(lib->tracepoints_start, lib->tracepoints_start + lib->tracepoints_count); } - unlock_tracepoints(); } /* @@ -380,14 +355,13 @@ tracepoint_add_probe(const char *name, void *probe, void *data) * * Returns 0 if ok, error value on error. * The probe address must at least be aligned on the architecture pointer size. + * Called with the UST lock held. */ int __tracepoint_probe_register(const char *name, void *probe, void *data) { void *old; - lock_tracepoints(); old = tracepoint_add_probe(name, probe, data); - unlock_tracepoints(); if (IS_ERR(old)) return PTR_ERR(old); @@ -418,18 +392,13 @@ static void *tracepoint_remove_probe(const char *name, void *probe, void *data) * @probe: probe function pointer * @probe: probe data pointer * - * We do not need to call a synchronize_sched to make sure the probes have - * finished running before doing a module unload, because the module unload - * itself uses stop_machine(), which insures that every preempt disabled section - * have finished. + * Called with the UST lock held. */ int __tracepoint_probe_unregister(const char *name, void *probe, void *data) { void *old; - lock_tracepoints(); old = tracepoint_remove_probe(name, probe, data); - unlock_tracepoints(); if (IS_ERR(old)) return PTR_ERR(old); @@ -454,20 +423,18 @@ static void tracepoint_add_old_probes(void *old) * @probe: probe handler * * caller must call tracepoint_probe_update_all() + * Called with the UST lock held. */ int tracepoint_probe_register_noupdate(const char *name, void *probe, void *data) { void *old; - lock_tracepoints(); old = tracepoint_add_probe(name, probe, data); if (IS_ERR(old)) { - unlock_tracepoints(); return PTR_ERR(old); } tracepoint_add_old_probes(old); - unlock_tracepoints(); return 0; } @@ -477,40 +444,36 @@ int tracepoint_probe_register_noupdate(const char *name, void *probe, * @probe: probe function pointer * * caller must call tracepoint_probe_update_all() + * Called with the UST lock held. */ int tracepoint_probe_unregister_noupdate(const char *name, void *probe, void *data) { void *old; - lock_tracepoints(); old = tracepoint_remove_probe(name, probe, data); if (IS_ERR(old)) { - unlock_tracepoints(); return PTR_ERR(old); } tracepoint_add_old_probes(old); - unlock_tracepoints(); return 0; } /** * tracepoint_probe_update_all - update tracepoints + * Called with the UST lock held. */ void tracepoint_probe_update_all(void) { CDS_LIST_HEAD(release_probes); struct tp_probes *pos, *next; - lock_tracepoints(); if (!need_update) { - unlock_tracepoints(); return; } if (!cds_list_empty(&old_probes)) cds_list_replace_init(&old_probes, &release_probes); need_update = 0; - unlock_tracepoints(); tracepoint_update_probes(); cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) { @@ -585,14 +548,16 @@ static void tracepoint_get_iter(struct tracepoint_iter *iter) tracepoint_iter_reset(iter); } +/* + * Called with UST lock held. + */ void tracepoint_iter_start(struct tracepoint_iter *iter) { - lock_tracepoints(); tracepoint_get_iter(iter); } /* - * Called with tracepoint mutex held. + * Called with UST lock held. */ void tracepoint_iter_next(struct tracepoint_iter *iter) { @@ -605,9 +570,11 @@ void tracepoint_iter_next(struct tracepoint_iter *iter) tracepoint_get_iter(iter); } +/* + * Called with UST lock held. + */ void tracepoint_iter_stop(struct tracepoint_iter *iter) { - unlock_tracepoints(); } void tracepoint_iter_reset(struct tracepoint_iter *iter) @@ -637,12 +604,14 @@ int tracepoint_register_lib(struct tracepoint * const *tracepoints_start, { struct tracepoint_lib *pl, *iter; + init_tracepoint(); + pl = (struct tracepoint_lib *) zmalloc(sizeof(struct tracepoint_lib)); pl->tracepoints_start = tracepoints_start; pl->tracepoints_count = tracepoints_count; - lock_tracepoints(); + ust_lock(); /* * We sort the libs by struct lib pointer address. */ @@ -657,15 +626,14 @@ int tracepoint_register_lib(struct tracepoint * const *tracepoints_start, /* We should be added at the head of the list */ cds_list_add(&pl->list, &libs); lib_added: - unlock_tracepoints(); - new_tracepoints(tracepoints_start, tracepoints_start + tracepoints_count); /* TODO: update just the loaded lib */ lib_update_tracepoints(); + ust_unlock(); - /* tracepoints_count - 1: skip dummy */ - DBG("just registered a tracepoints section from %p and having %d tracepoints (minus dummy tracepoints)", tracepoints_start, tracepoints_count); + DBG("just registered a tracepoints section from %p and having %d tracepoints", + tracepoints_start, tracepoints_count); return 0; } @@ -674,7 +642,7 @@ int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start) { struct tracepoint_lib *lib; - lock_tracepoints(); + ust_lock(); cds_list_for_each_entry(lib, &libs, list) { if (lib->tracepoints_start == tracepoints_start) { struct tracepoint_lib *lib2free = lib; @@ -683,23 +651,19 @@ int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start) break; } } - unlock_tracepoints(); + ust_unlock(); return 0; } -void __attribute__((constructor)) init_tracepoint(void) +void init_tracepoint(void) { + if (uatomic_xchg(&initialized, 1) == 1) + return; init_usterr(); - if (!initialized) { - tracepoint_register_lib(__start___tracepoints_ptrs, - __stop___tracepoints_ptrs - - __start___tracepoints_ptrs); - initialized = 1; - } } -void __attribute__((destructor)) destroy_tracepoint(void) +void exit_tracepoint(void) { - tracepoint_unregister_lib(__start___tracepoints_ptrs); + initialized = 0; }