X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-events.c;h=26601a671c976506587564fe556f7eabc16a7566;hb=60d8702955d702f95053b0355d156ae032ac2bc8;hp=00babd0ebd293807abc7d9d07df4030173978897;hpb=13b21cd60df2abab292653cead980ef27dbfab08;p=lttng-ust.git diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c index 00babd0e..26601a67 100644 --- a/liblttng-ust/lttng-events.c +++ b/liblttng-ust/lttng-events.c @@ -45,7 +45,7 @@ #include #include -#include +#include #include #include "error.h" #include "compat.h" @@ -78,7 +78,6 @@ void ust_unlock(void) static CDS_LIST_HEAD(sessions); static void _lttng_event_destroy(struct lttng_event *event); -static int _lttng_event_unregister(struct lttng_event *event); static void lttng_session_lazy_sync_enablers(struct lttng_session *session); @@ -170,17 +169,57 @@ void _lttng_channel_unmap(struct lttng_channel *lttng_chan) channel_destroy(chan, handle, 0); } +static +void register_event(struct lttng_event *event) +{ + int ret; + const struct lttng_event_desc *desc; + + assert(event->registered == 0); + desc = event->desc; + ret = __tracepoint_probe_register(desc->name, + desc->probe_callback, + event, desc->signature); + WARN_ON_ONCE(ret); + if (!ret) + event->registered = 1; +} + +static +void unregister_event(struct lttng_event *event) +{ + int ret; + const struct lttng_event_desc *desc; + + assert(event->registered == 1); + desc = event->desc; + ret = __tracepoint_probe_unregister(desc->name, + desc->probe_callback, + event); + WARN_ON_ONCE(ret); + if (!ret) + event->registered = 0; +} + +/* + * Only used internally at session destruction. + */ +static +void _lttng_event_unregister(struct lttng_event *event) +{ + if (event->registered) + unregister_event(event); +} + void lttng_session_destroy(struct lttng_session *session) { struct lttng_channel *chan, *tmpchan; struct lttng_event *event, *tmpevent; struct lttng_enabler *enabler, *tmpenabler; - int ret; CMM_ACCESS_ONCE(session->active) = 0; cds_list_for_each_entry(event, &session->events_head, node) { - ret = _lttng_event_unregister(event); - WARN_ON(ret); + _lttng_event_unregister(event); } synchronize_trace(); /* Wait for in-flight events to complete */ cds_list_for_each_entry_safe(enabler, tmpenabler, @@ -210,6 +249,8 @@ int lttng_session_enable(struct lttng_session *session) if (notify_socket < 0) return notify_socket; + /* Set transient enabler state to "enabled" */ + session->tstate = 1; /* We need to sync enablers with session before activation. */ lttng_session_sync_enablers(session); @@ -219,8 +260,9 @@ int lttng_session_enable(struct lttng_session *session) */ cds_list_for_each_entry(chan, &session->chan_head, node) { const struct lttng_ctx *ctx; - const struct lttng_event_field *fields = NULL; + const struct lttng_ctx_field *fields = NULL; size_t nr_fields = 0; + uint32_t chan_id; /* don't change it if session stop/restart */ if (chan->header_type) @@ -228,21 +270,27 @@ int lttng_session_enable(struct lttng_session *session) ctx = chan->ctx; if (ctx) { nr_fields = ctx->nr_fields; - fields = &ctx->fields->event_field; + fields = ctx->fields; } ret = ustcomm_register_channel(notify_socket, session->objd, chan->objd, nr_fields, fields, - &chan->id, + &chan_id, &chan->header_type); if (ret) { DBG("Error (%d) registering channel to sessiond", ret); return ret; } + if (chan_id != chan->id) { + DBG("Error: channel registration id (%u) does not match id assigned at creation (%u)", + chan_id, chan->id); + return -EINVAL; + } } + /* Set atomically the state to "active" */ CMM_ACCESS_ONCE(session->active) = 1; CMM_ACCESS_ONCE(session->been_active) = 1; end: @@ -257,29 +305,48 @@ int lttng_session_disable(struct lttng_session *session) ret = -EBUSY; goto end; } + /* Set atomically the state to "inactive" */ CMM_ACCESS_ONCE(session->active) = 0; + + /* Set transient enabler state to "disabled" */ + session->tstate = 0; + lttng_session_sync_enablers(session); end: return ret; } int lttng_channel_enable(struct lttng_channel *channel) { - int old; + int ret = 0; - old = uatomic_xchg(&channel->enabled, 1); - if (old) - return -EEXIST; - return 0; + if (channel->enabled) { + ret = -EBUSY; + goto end; + } + /* Set transient enabler state to "enabled" */ + channel->tstate = 1; + lttng_session_sync_enablers(channel->session); + /* Set atomically the state to "enabled" */ + CMM_ACCESS_ONCE(channel->enabled) = 1; +end: + return ret; } int lttng_channel_disable(struct lttng_channel *channel) { - int old; + int ret = 0; - old = uatomic_xchg(&channel->enabled, 0); - if (!old) - return -EEXIST; - return 0; + if (!channel->enabled) { + ret = -EBUSY; + goto end; + } + /* Set atomically the state to "disabled" */ + CMM_ACCESS_ONCE(channel->enabled) = 0; + /* Set transient enabler state to "enabled" */ + channel->tstate = 0; + lttng_session_sync_enablers(channel->session); +end: + return ret; } /* @@ -304,9 +371,9 @@ int lttng_event_create(const struct lttng_event_desc *desc, head = &chan->session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)]; cds_hlist_for_each_entry(event, node, head, hlist) { assert(event->desc); - if (!strncmp(event->desc->name, - desc->name, - LTTNG_UST_SYM_NAME_LEN - 1)) { + if (!strncmp(event->desc->name, desc->name, + LTTNG_UST_SYM_NAME_LEN - 1) + && chan == event->chan) { ret = -EEXIST; goto exist; } @@ -328,7 +395,9 @@ int lttng_event_create(const struct lttng_event_desc *desc, } event->chan = chan; - event->enabled = 1; + /* Event will be enabled by enabler sync. */ + event->enabled = 0; + event->registered = 0; CDS_INIT_LIST_HEAD(&event->bytecode_runtime_head); CDS_INIT_LIST_HEAD(&event->enablers_ref_head); event->desc = desc; @@ -360,17 +429,10 @@ int lttng_event_create(const struct lttng_event_desc *desc, /* Populate lttng_event structure before tracepoint registration. */ cmm_smp_wmb(); - ret = __tracepoint_probe_register(event_name, - desc->probe_callback, - event, desc->signature); - if (ret) - goto tracepoint_register_error; - cds_list_add(&event->node, &chan->session->events_head); cds_hlist_add_head(&event->hlist, head); return 0; -tracepoint_register_error: sessiond_register_error: free(event); cache_error: @@ -384,7 +446,7 @@ int lttng_desc_match_wildcard_enabler(const struct lttng_event_desc *desc, struct lttng_enabler *enabler) { int loglevel = 0; - unsigned int has_loglevel; + unsigned int has_loglevel = 0; assert(enabler->type == LTTNG_ENABLER_WILDCARD); /* Compare excluding final '*' */ @@ -443,7 +505,11 @@ static int lttng_event_match_enabler(struct lttng_event *event, struct lttng_enabler *enabler) { - return lttng_desc_match_enabler(event->desc, enabler); + if (lttng_desc_match_enabler(event->desc, enabler) + && event->chan == enabler->chan) + return 1; + else + return 0; } static @@ -501,7 +567,8 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler) hash = jhash(event_name, name_len, 0); head = &session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)]; cds_hlist_for_each_entry(event, node, head, hlist) { - if (event->desc == desc) + if (event->desc == desc + && event->chan == enabler->chan) found = 1; } if (found) @@ -568,12 +635,9 @@ int lttng_enabler_ref_events(struct lttng_enabler *enabler) /* * Called at library load: connect the probe on all enablers matching * this event. - * called with session mutex held. - * TODO: currently, for each desc added, we iterate on all event desc - * (inefficient). We should create specific code that only target the - * added desc. + * Called with session mutex held. */ -int lttng_fix_pending_event_desc(const struct lttng_event_desc *desc) +int lttng_fix_pending_events(void) { struct lttng_session *session; @@ -583,16 +647,6 @@ int lttng_fix_pending_event_desc(const struct lttng_event_desc *desc) return 0; } -/* - * Only used internally at session destruction. - */ -int _lttng_event_unregister(struct lttng_event *event) -{ - return __tracepoint_probe_unregister(event->desc->name, - event->desc->probe_callback, - event); -} - /* * Only used internally at session destruction. */ @@ -686,6 +740,8 @@ int lttng_attach_context(struct lttng_ust_context *context_param, return lttng_add_vpid_to_ctx(ctx); case LTTNG_UST_CONTEXT_PROCNAME: return lttng_add_procname_to_ctx(ctx); + case LTTNG_UST_CONTEXT_IP: + return lttng_add_ip_to_ctx(ctx); default: return -EINVAL; } @@ -739,7 +795,8 @@ void lttng_session_sync_enablers(struct lttng_session *session) lttng_enabler_ref_events(enabler); /* * For each event, if at least one of its enablers is enabled, - * we enable the event, else we disable it. + * and its channel and session transient states are enabled, we + * enable the event, else we disable it. */ cds_list_for_each_entry(event, &session->events_head, node) { struct lttng_enabler_ref *enabler_ref; @@ -754,7 +811,25 @@ void lttng_session_sync_enablers(struct lttng_session *session) break; } } - event->enabled = enabled; + /* + * Enabled state is based on union of enablers, with + * intesection of session and channel transient enable + * states. + */ + enabled = enabled && session->tstate && event->chan->tstate; + + CMM_STORE_SHARED(event->enabled, enabled); + /* + * Sync tracepoint registration with event enabled + * state. + */ + if (enabled) { + if (!event->registered) + register_event(event); + } else { + if (event->registered) + unregister_event(event); + } /* Check if has enablers without bytecode enabled */ cds_list_for_each_entry(enabler_ref,