X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Ftracepoint.c;h=3404acf2e2272e2bd13bb9fcb2750d4157d99b49;hb=refs%2Fheads%2Fstable-2.5;hp=013f9b2a6091a69e4e07f8d9365ac695c39cc84f;hpb=3469bbbe391e22739245dc35091d944b50429179;p=lttng-ust.git diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c index 013f9b2a..3404acf2 100644 --- a/liblttng-ust/tracepoint.c +++ b/liblttng-ust/tracepoint.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include /* for LTTNG_UST_SYM_NAME_LEN */ @@ -95,6 +96,7 @@ struct tracepoint_entry { struct cds_hlist_node hlist; struct tracepoint_probe *probes; int refcount; /* Number of times armed. 0 if disarmed. */ + int callsite_refcount; /* how many libs use this tracepoint */ const char *signature; char name[0]; }; @@ -122,6 +124,7 @@ struct callsite_entry { struct tracepoint *tp; }; +/* coverity[+alloc] */ static void *allocate_probes(int count) { struct tp_probes *p = zmalloc(count * sizeof(struct tracepoint_probe) @@ -129,6 +132,7 @@ static void *allocate_probes(int count) return p == NULL ? NULL : p->probes; } +/* coverity[+free : arg-0] */ static void release_probes(void *old) { if (old) { @@ -293,6 +297,7 @@ static struct tracepoint_entry *add_tracepoint(const char *name, e->name[name_len] = '\0'; e->probes = NULL; e->refcount = 0; + e->callsite_refcount = 0; e->signature = signature; cds_hlist_add_head(&e->hlist, head); return e; @@ -308,41 +313,6 @@ static void remove_tracepoint(struct tracepoint_entry *e) free(e); } -/* - * Add the callsite to the callsite hash table. Must be called with - * tracepoint mutex held. - */ -static void add_callsite(struct tracepoint *tp) -{ - struct cds_hlist_head *head; - struct callsite_entry *e; - const char *name = tp->name; - size_t name_len = strlen(name); - uint32_t hash; - - if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) { - WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1); - name_len = LTTNG_UST_SYM_NAME_LEN - 1; - } - hash = jhash(name, name_len, 0); - head = &callsite_table[hash & (CALLSITE_TABLE_SIZE - 1)]; - e = zmalloc(sizeof(struct callsite_entry)); - assert(e); - cds_hlist_add_head(&e->hlist, head); - e->tp = tp; -} - -/* - * Remove the callsite from the callsite hash table and from lib - * callsite list. Must be called with tracepoint mutex held. - */ -static void remove_callsite(struct callsite_entry *e) -{ - cds_hlist_del(&e->hlist); - cds_list_del(&e->node); - free(e); -} - /* * Sets the probe callback corresponding to one tracepoint. */ @@ -376,7 +346,7 @@ static void set_tracepoint(struct tracepoint_entry **entry, * is used. */ rcu_assign_pointer(elem->probes, (*entry)->probes); - elem->state = active; + CMM_STORE_SHARED(elem->state, active); } /* @@ -387,10 +357,63 @@ static void set_tracepoint(struct tracepoint_entry **entry, */ static void disable_tracepoint(struct tracepoint *elem) { - elem->state = 0; + CMM_STORE_SHARED(elem->state, 0); rcu_assign_pointer(elem->probes, NULL); } +/* + * Add the callsite to the callsite hash table. Must be called with + * tracepoint mutex held. + */ +static void add_callsite(struct tracepoint_lib * lib, struct tracepoint *tp) +{ + struct cds_hlist_head *head; + struct callsite_entry *e; + const char *name = tp->name; + size_t name_len = strlen(name); + uint32_t hash; + struct tracepoint_entry *tp_entry; + + if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) { + WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1); + name_len = LTTNG_UST_SYM_NAME_LEN - 1; + } + hash = jhash(name, name_len, 0); + head = &callsite_table[hash & (CALLSITE_TABLE_SIZE - 1)]; + e = zmalloc(sizeof(struct callsite_entry)); + if (!e) { + PERROR("Unable to add callsite for tracepoint \"%s\"", name); + return; + } + cds_hlist_add_head(&e->hlist, head); + e->tp = tp; + cds_list_add(&e->node, &lib->callsites); + + tp_entry = get_tracepoint(name); + if (!tp_entry) + return; + tp_entry->callsite_refcount++; +} + +/* + * Remove the callsite from the callsite hash table and from lib + * callsite list. Must be called with tracepoint mutex held. + */ +static void remove_callsite(struct callsite_entry *e) +{ + struct tracepoint_entry *tp_entry; + + tp_entry = get_tracepoint(e->tp->name); + if (tp_entry) { + tp_entry->callsite_refcount--; + if (tp_entry->callsite_refcount == 0) + disable_tracepoint(e->tp); + } + cds_hlist_del(&e->hlist); + cds_list_del(&e->node); + free(e); +} + /* * Enable/disable all callsites based on the state of a specific * tracepoint entry. @@ -478,7 +501,7 @@ static void lib_register_callsites(struct tracepoint_lib *lib) if (!(*iter)->name) { continue; } - add_callsite(*iter); + add_callsite(lib, *iter); } } @@ -702,24 +725,6 @@ static void new_tracepoints(struct tracepoint * const *start, struct tracepoint } } -static -void lib_disable_tracepoints(struct tracepoint_lib *lib) -{ - struct tracepoint * const *begin; - struct tracepoint * const *end; - struct tracepoint * const *iter; - - begin = lib->tracepoints_start; - end = lib->tracepoints_start + lib->tracepoints_count; - - for (iter = begin; iter < end; iter++) { - if (!*iter) - continue; /* skip dummy */ - disable_tracepoint(*iter); - } - -} - int tracepoint_register_lib(struct tracepoint * const *tracepoints_start, int tracepoints_count) { @@ -728,7 +733,10 @@ int tracepoint_register_lib(struct tracepoint * const *tracepoints_start, init_tracepoint(); pl = (struct tracepoint_lib *) zmalloc(sizeof(struct tracepoint_lib)); - + if (!pl) { + PERROR("Unable to register tracepoint lib"); + return -1; + } pl->tracepoints_start = tracepoints_start; pl->tracepoints_count = tracepoints_count; CDS_INIT_LIST_HEAD(&pl->callsites); @@ -777,13 +785,11 @@ int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start) cds_list_del(&lib->list); /* - * Force tracepoint disarm for all tracepoints of this lib. - * This takes care of destructor of library that would leave a - * LD_PRELOAD wrapper override function enabled for tracing, but - * the session teardown would not be able to reach the - * tracepoint anymore to disable it. + * Unregistering a callsite also decreases the + * callsite reference count of the corresponding + * tracepoint, and disables the tracepoint if + * the reference count drops to zero. */ - lib_disable_tracepoints(lib); lib_unregister_callsites(lib); DBG("just unregistered a tracepoints section from %p", lib->tracepoints_start);