X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-events.c;h=d5597ca6d787ac4470538231e4a355649ac7e564;hb=6ca18e666d018ec79d517485a310c542cf735fa9;hp=46ba11d5f12e74935871efcb847c1160d020da96;hpb=c73a6ee1ee516abd1278d1720220fdf99bd8fd39;p=lttng-ust.git diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c index 46ba11d5..d5597ca6 100644 --- a/liblttng-ust/lttng-events.c +++ b/liblttng-ust/lttng-events.c @@ -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); @@ -221,6 +262,7 @@ int lttng_session_enable(struct lttng_session *session) const struct lttng_ctx *ctx; const struct lttng_event_field *fields = NULL; size_t nr_fields = 0; + uint32_t chan_id; /* don't change it if session stop/restart */ if (chan->header_type) @@ -235,12 +277,20 @@ int lttng_session_enable(struct lttng_session *session) chan->objd, nr_fields, fields, - &chan->id, + &chan_id, &chan->header_type); - if (ret) + 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: @@ -255,57 +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; - if (channel == channel->session->metadata) - return -EPERM; - 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; - - if (channel == channel->session->metadata) - return -EPERM; - old = uatomic_xchg(&channel->enabled, 0); - if (!old) - return -EEXIST; - return 0; -} - -int lttng_event_enable(struct lttng_event *event) -{ - int old; - - if (event->chan == event->chan->session->metadata) - return -EPERM; - old = uatomic_xchg(&event->enabled, 1); - if (old) - return -EEXIST; - return 0; -} - -int lttng_event_disable(struct lttng_event *event) -{ - int old; + int ret = 0; - if (event->chan == event->chan->session->metadata) - return -EPERM; - old = uatomic_xchg(&event->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; } /* @@ -354,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; @@ -368,39 +411,28 @@ int lttng_event_create(const struct lttng_event_desc *desc, else uri = NULL; - /* Don't register metadata events */ - if (session->metadata == chan) { - event->id = -1U; - } else { - /* Fetch event ID from sessiond */ - ret = ustcomm_register_event(notify_socket, - session->objd, - chan->objd, - event_name, - loglevel, - desc->signature, - desc->nr_fields, - desc->fields, - uri, - &event->id); - if (ret < 0) { - goto sessiond_register_error; - } + /* Fetch event ID from sessiond */ + ret = ustcomm_register_event(notify_socket, + session->objd, + chan->objd, + event_name, + loglevel, + desc->signature, + desc->nr_fields, + desc->fields, + uri, + &event->id); + if (ret < 0) { + DBG("Error (%d) registering event to sessiond", ret); + goto sessiond_register_error; } /* 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: @@ -414,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 '*' */ @@ -613,16 +645,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. */ @@ -682,8 +704,6 @@ int lttng_enabler_enable(struct lttng_enabler *enabler) int lttng_enabler_disable(struct lttng_enabler *enabler) { - if (enabler->chan == enabler->chan->session->metadata) - return -EPERM; enabler->enabled = 0; lttng_session_lazy_sync_enablers(enabler->chan->session); return 0; @@ -771,7 +791,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; @@ -786,7 +807,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,