X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Ftracepoint.c;h=00c471969b4394f16b9ec2e13bb520e10e78fe4b;hb=d6297168f9042cdc550507bb5e97cee7037c34d3;hp=7bb38fa9ec307f9b1eb85670c7b90a456e9bce3d;hpb=5e6df7eabfed640cc83d227ae8bed3de75a56694;p=lttng-ust.git diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c index 7bb38fa9..00c47196 100644 --- a/liblttng-ust/tracepoint.c +++ b/liblttng-ust/tracepoint.c @@ -95,6 +95,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]; }; @@ -295,6 +296,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; @@ -310,41 +312,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. */ @@ -393,6 +360,59 @@ static void disable_tracepoint(struct tracepoint *elem) 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. @@ -480,7 +500,7 @@ static void lib_register_callsites(struct tracepoint_lib *lib) if (!(*iter)->name) { continue; } - add_callsite(*iter); + add_callsite(lib, *iter); } } @@ -704,24 +724,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) { @@ -730,7 +732,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); @@ -779,13 +784,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);