X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ust%2Flttng-events.c;h=e618dce62c4f12ecc031a4322c7cb5c556ed3d80;hb=8a5c7efa50f9dce0360611b16323462c77f07321;hp=386106136bf4ca08c15ada7913c6c32179d5576b;hpb=612e9ce4e5cc3a1292522a563789f6aab6c421b1;p=lttng-ust.git diff --git a/src/lib/lttng-ust/lttng-events.c b/src/lib/lttng-ust/lttng-events.c index 38610613..e618dce6 100644 --- a/src/lib/lttng-ust/lttng-events.c +++ b/src/lib/lttng-ust/lttng-events.c @@ -39,12 +39,11 @@ #include "common/ust-fd.h" #include "common/dynamic-type.h" #include "common/ust-context-provider.h" -#include "lttng-ust-uuid.h" #include "common/tracepoint.h" #include "common/strutils.h" #include "lttng-bytecode.h" -#include "lttng-tracer.h" +#include "common/tracer.h" #include "lttng-tracer-core.h" #include "lttng-ust-statedump.h" #include "context-internal.h" @@ -99,6 +98,36 @@ void lttng_ust_format_event_name(const struct lttng_ust_event_desc *desc, strcat(name, desc->event_name); } +static +void lttng_event_enabler_unsync(struct lttng_event_enabler *event_enabler) +{ + cds_list_move(&event_enabler->node, + &event_enabler->chan->parent->session->priv->unsync_enablers_head); +} + +static +void lttng_session_unsync_enablers(struct lttng_ust_session *session) +{ + cds_list_splice(&session->priv->sync_enablers_head, + &session->priv->unsync_enablers_head); + CDS_INIT_LIST_HEAD(&session->priv->sync_enablers_head); +} + +static +void lttng_event_notifier_enabler_unsync(struct lttng_event_notifier_enabler *event_notifier_enabler) +{ + cds_list_move(&event_notifier_enabler->node, + &event_notifier_enabler->group->unsync_enablers_head); +} + +static +void lttng_event_notifier_group_unsync_enablers(struct lttng_event_notifier_group *event_notifier_group) +{ + cds_list_splice(&event_notifier_group->sync_enablers_head, + &event_notifier_group->unsync_enablers_head); + CDS_INIT_LIST_HEAD(&event_notifier_group->sync_enablers_head); +} + /* * Called with ust lock held. */ @@ -168,7 +197,8 @@ struct lttng_ust_session *lttng_session_create(void) CDS_INIT_LIST_HEAD(&session->priv->chan_head); CDS_INIT_LIST_HEAD(&session->priv->events_head); CDS_INIT_LIST_HEAD(&session->priv->enums_head); - CDS_INIT_LIST_HEAD(&session->priv->enablers_head); + CDS_INIT_LIST_HEAD(&session->priv->unsync_enablers_head); + CDS_INIT_LIST_HEAD(&session->priv->sync_enablers_head); for (i = 0; i < LTTNG_UST_EVENT_HT_SIZE; i++) CDS_INIT_HLIST_HEAD(&session->priv->events_ht.table[i]); for (i = 0; i < LTTNG_UST_ENUM_HT_SIZE; i++) @@ -232,7 +262,8 @@ struct lttng_event_notifier_group *lttng_event_notifier_group_create(void) return NULL; } - CDS_INIT_LIST_HEAD(&event_notifier_group->enablers_head); + CDS_INIT_LIST_HEAD(&event_notifier_group->sync_enablers_head); + CDS_INIT_LIST_HEAD(&event_notifier_group->unsync_enablers_head); CDS_INIT_LIST_HEAD(&event_notifier_group->event_notifiers_head); for (i = 0; i < LTTNG_UST_EVENT_NOTIFIER_HT_SIZE; i++) CDS_INIT_HLIST_HEAD(&event_notifier_group->event_notifiers_ht.table[i]); @@ -271,8 +302,8 @@ void register_event(struct lttng_ust_event_common *event) desc = event->priv->desc; ret = lttng_ust_tp_probe_register_queue_release(desc->probe_desc->provider_name, desc->event_name, - desc->probe_callback, - event, desc->signature); + desc->tp_class->probe_callback, + event, desc->tp_class->signature); WARN_ON_ONCE(ret); if (!ret) event->priv->registered = 1; @@ -288,7 +319,7 @@ void unregister_event(struct lttng_ust_event_common *event) desc = event->priv->desc; ret = lttng_ust_tp_probe_unregister_queue_release(desc->probe_desc->provider_name, desc->event_name, - desc->probe_callback, + desc->tp_class->probe_callback, event); WARN_ON_ONCE(ret); if (!ret) @@ -316,7 +347,10 @@ void lttng_session_destroy(struct lttng_ust_session *session) lttng_ust_urcu_synchronize_rcu(); /* Wait for in-flight events to complete */ lttng_ust_tp_probe_prune_release_queue(); cds_list_for_each_entry_safe(event_enabler, event_tmpenabler, - &session->priv->enablers_head, node) + &session->priv->unsync_enablers_head, node) + lttng_event_enabler_destroy(event_enabler); + cds_list_for_each_entry_safe(event_enabler, event_tmpenabler, + &session->priv->sync_enablers_head, node) lttng_event_enabler_destroy(event_enabler); cds_list_for_each_entry_safe(event_recorder_priv, tmpevent_recorder_priv, &session->priv->events_head, node) @@ -350,7 +384,10 @@ void lttng_event_notifier_group_destroy( lttng_ust_urcu_synchronize_rcu(); cds_list_for_each_entry_safe(notifier_enabler, tmpnotifier_enabler, - &event_notifier_group->enablers_head, node) + &event_notifier_group->sync_enablers_head, node) + lttng_event_notifier_enabler_destroy(notifier_enabler); + cds_list_for_each_entry_safe(notifier_enabler, tmpnotifier_enabler, + &event_notifier_group->unsync_enablers_head, node) lttng_event_notifier_enabler_destroy(notifier_enabler); cds_list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv, @@ -730,7 +767,7 @@ int lttng_event_recorder_create(const struct lttng_ust_event_desc *desc, goto socket_error; } - ret = lttng_create_all_event_enums(desc->nr_fields, desc->fields, + ret = lttng_create_all_event_enums(desc->tp_class->nr_fields, desc->tp_class->fields, session); if (ret < 0) { DBG("Error (%d) adding enum to session", ret); @@ -794,9 +831,9 @@ int lttng_event_recorder_create(const struct lttng_ust_event_desc *desc, chan->priv->parent.objd, name, loglevel, - desc->signature, - desc->nr_fields, - desc->fields, + desc->tp_class->signature, + desc->tp_class->nr_fields, + desc->tp_class->fields, uri, &event_recorder->priv->id); if (ret < 0) { @@ -1174,12 +1211,12 @@ void _event_enum_destroy(struct lttng_ust_event_common *event) unsigned int i; /* Destroy enums of the current event. */ - for (i = 0; i < event_recorder->parent->priv->desc->nr_fields; i++) { + for (i = 0; i < event_recorder->parent->priv->desc->tp_class->nr_fields; i++) { const struct lttng_ust_enum_desc *enum_desc; const struct lttng_ust_event_field *field; struct lttng_enum *curr_enum; - field = event_recorder->parent->priv->desc->fields[i]; + field = event_recorder->parent->priv->desc->tp_class->fields[i]; switch (field->type->type) { case lttng_ust_type_enum: enum_desc = lttng_ust_get_type_enum(field->type)->desc; @@ -1293,6 +1330,11 @@ int lttng_fix_pending_events(void) struct lttng_ust_session_private *session_priv; cds_list_for_each_entry(session_priv, &sessions, node) { + /* + * New probes have appeared, we need to re-sync all + * enablers. + */ + lttng_session_unsync_enablers(session_priv->pub); lttng_session_lazy_sync_event_enablers(session_priv->pub); } return 0; @@ -1303,6 +1345,11 @@ int lttng_fix_pending_event_notifiers(void) struct lttng_event_notifier_group *event_notifier_group; cds_list_for_each_entry(event_notifier_group, &event_notifier_groups, node) { + /* + * New probes have appeared, we need to re-sync all + * enablers. + */ + lttng_event_notifier_group_unsync_enablers(event_notifier_group); lttng_event_notifier_group_sync_enablers(event_notifier_group); } return 0; @@ -1419,7 +1466,7 @@ struct lttng_event_enabler *lttng_event_enabler_create( event_enabler->chan = chan; /* ctx left NULL */ event_enabler->base.enabled = 0; - cds_list_add(&event_enabler->node, &event_enabler->chan->parent->session->priv->enablers_head); + cds_list_add(&event_enabler->node, &event_enabler->chan->parent->session->priv->unsync_enablers_head); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); return event_enabler; @@ -1458,7 +1505,7 @@ struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create( event_notifier_enabler->group = event_notifier_group; cds_list_add(&event_notifier_enabler->node, - &event_notifier_group->enablers_head); + &event_notifier_group->unsync_enablers_head); lttng_event_notifier_group_sync_enablers(event_notifier_group); @@ -1468,6 +1515,7 @@ struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create( int lttng_event_enabler_enable(struct lttng_event_enabler *event_enabler) { lttng_event_enabler_as_enabler(event_enabler)->enabled = 1; + lttng_event_enabler_unsync(event_enabler); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); return 0; @@ -1476,6 +1524,7 @@ int lttng_event_enabler_enable(struct lttng_event_enabler *event_enabler) int lttng_event_enabler_disable(struct lttng_event_enabler *event_enabler) { lttng_event_enabler_as_enabler(event_enabler)->enabled = 0; + lttng_event_enabler_unsync(event_enabler); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); return 0; @@ -1496,7 +1545,7 @@ int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler *event { _lttng_enabler_attach_filter_bytecode( lttng_event_enabler_as_enabler(event_enabler), bytecode); - + lttng_event_enabler_unsync(event_enabler); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); return 0; } @@ -1516,7 +1565,7 @@ int lttng_event_enabler_attach_exclusion(struct lttng_event_enabler *event_enabl { _lttng_enabler_attach_exclusion( lttng_event_enabler_as_enabler(event_enabler), excluder); - + lttng_event_enabler_unsync(event_enabler); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); return 0; } @@ -1525,6 +1574,7 @@ int lttng_event_notifier_enabler_enable( struct lttng_event_notifier_enabler *event_notifier_enabler) { lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)->enabled = 1; + lttng_event_notifier_enabler_unsync(event_notifier_enabler); lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); return 0; @@ -1534,6 +1584,7 @@ int lttng_event_notifier_enabler_disable( struct lttng_event_notifier_enabler *event_notifier_enabler) { lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)->enabled = 0; + lttng_event_notifier_enabler_unsync(event_notifier_enabler); lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); return 0; @@ -1546,7 +1597,7 @@ int lttng_event_notifier_enabler_attach_filter_bytecode( _lttng_enabler_attach_filter_bytecode( lttng_event_notifier_enabler_as_enabler(event_notifier_enabler), bytecode); - + lttng_event_notifier_enabler_unsync(event_notifier_enabler); lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); return 0; } @@ -1562,7 +1613,7 @@ int lttng_event_notifier_enabler_attach_capture_bytecode( /* Take ownership of bytecode */ *bytecode = NULL; event_notifier_enabler->num_captures++; - + lttng_event_notifier_enabler_unsync(event_notifier_enabler); lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); return 0; } @@ -1574,7 +1625,7 @@ int lttng_event_notifier_enabler_attach_exclusion( _lttng_enabler_attach_exclusion( lttng_event_notifier_enabler_as_enabler(event_notifier_enabler), excluder); - + lttng_event_notifier_enabler_unsync(event_notifier_enabler); lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); return 0; } @@ -1680,9 +1731,22 @@ void lttng_session_sync_event_enablers(struct lttng_ust_session *session) { struct lttng_event_enabler *event_enabler; struct lttng_ust_event_recorder_private *event_recorder_priv; + struct cds_list_head iter_list; + + /* + * lttng_event_enabler_ref_event_recorders can cause lazy probes + * to add items to the unsync_enablers_head list. Iterate on a + * local copy of that list until it is stable (empty). + */ + do { + CDS_INIT_LIST_HEAD(&iter_list); + cds_list_splice(&session->priv->unsync_enablers_head, &iter_list); + CDS_INIT_LIST_HEAD(&session->priv->unsync_enablers_head); + cds_list_for_each_entry(event_enabler, &iter_list, node) + lttng_event_enabler_ref_event_recorders(event_enabler); + cds_list_splice(&iter_list, &session->priv->sync_enablers_head); + } while (!cds_list_empty(&session->priv->unsync_enablers_head)); - cds_list_for_each_entry(event_enabler, &session->priv->enablers_head, node) - lttng_event_enabler_ref_event_recorders(event_enabler); /* * For each event, if at least one of its enablers is enabled, * and its channel and session transient states are enabled, we @@ -1746,13 +1810,6 @@ void lttng_session_sync_event_enablers(struct lttng_ust_session *session) lttng_ust_tp_probe_prune_release_queue(); } -/* Support for event notifier is introduced by probe provider major version 2. */ -static -bool lttng_ust_probe_supports_event_notifier(const struct lttng_ust_probe_desc *probe_desc) -{ - return probe_desc->major >= 2; -} - static void lttng_create_event_notifier_if_missing( struct lttng_event_notifier_enabler *event_notifier_enabler) @@ -1806,18 +1863,6 @@ void lttng_create_event_notifier_if_missing( if (found) continue; - /* Check that the probe supports event notifiers, else report the error. */ - if (!lttng_ust_probe_supports_event_notifier(probe_desc)) { - ERR("Probe \"%s\" contains event \"%s:%s\" which matches an enabled event notifier, " - "but its version (%u.%u) is too old and does not implement event notifiers. " - "It needs to be recompiled against a newer version of LTTng-UST, otherwise " - "this event will not generate any notification.", - probe_desc->provider_name, - probe_desc->provider_name, desc->event_name, - probe_desc->major, - probe_desc->minor); - continue; - } /* * We need to create a event_notifier for this event probe. */ @@ -1905,9 +1950,22 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group { struct lttng_event_notifier_enabler *event_notifier_enabler; struct lttng_ust_event_notifier_private *event_notifier_priv; + struct cds_list_head iter_list; - cds_list_for_each_entry(event_notifier_enabler, &event_notifier_group->enablers_head, node) - lttng_event_notifier_enabler_ref_event_notifiers(event_notifier_enabler); + /* + * lttng_event_notifier_enabler_ref_event_notifiers can cause + * lazy probes to add items to the unsync_enablers_head list. + * Iterate on a local copy of that list until it is stable + * (empty). + */ + do { + CDS_INIT_LIST_HEAD(&iter_list); + cds_list_splice(&event_notifier_group->unsync_enablers_head, &iter_list); + CDS_INIT_LIST_HEAD(&event_notifier_group->unsync_enablers_head); + cds_list_for_each_entry(event_notifier_enabler, &iter_list, node) + lttng_event_notifier_enabler_ref_event_notifiers(event_notifier_enabler); + cds_list_splice(&iter_list, &event_notifier_group->sync_enablers_head); + } while (!cds_list_empty(&event_notifier_group->unsync_enablers_head)); /* * For each event_notifier, if at least one of its enablers is enabled, @@ -1997,11 +2055,13 @@ void lttng_session_lazy_sync_event_enablers(struct lttng_ust_session *session) * context (either app context callbacks, or dummy callbacks). */ void lttng_ust_context_set_session_provider(const char *name, - size_t (*get_size)(void *priv, size_t offset), - void (*record)(void *priv, struct lttng_ust_ring_buffer_ctx *ctx, + size_t (*get_size)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + size_t offset), + void (*record)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + struct lttng_ust_ring_buffer_ctx *ctx, struct lttng_ust_channel_buffer *chan), - void (*get_value)(void *priv, struct lttng_ust_ctx_value *value), - void *priv) + void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + struct lttng_ust_ctx_value *value)) { struct lttng_ust_session_private *session_priv; @@ -2011,18 +2071,18 @@ void lttng_ust_context_set_session_provider(const char *name, int ret; ret = lttng_ust_context_set_provider_rcu(&session_priv->ctx, - name, get_size, record, get_value, priv); + name, get_size, record, get_value); if (ret) abort(); cds_list_for_each_entry(chan, &session_priv->chan_head, node) { ret = lttng_ust_context_set_provider_rcu(&chan->ctx, - name, get_size, record, get_value, priv); + name, get_size, record, get_value); if (ret) abort(); } cds_list_for_each_entry(event_recorder_priv, &session_priv->events_head, node) { ret = lttng_ust_context_set_provider_rcu(&event_recorder_priv->ctx, - name, get_size, record, get_value, priv); + name, get_size, record, get_value); if (ret) abort(); } @@ -2037,11 +2097,13 @@ void lttng_ust_context_set_session_provider(const char *name, * context (either app context callbacks, or dummy callbacks). */ void lttng_ust_context_set_event_notifier_group_provider(const char *name, - size_t (*get_size)(void *priv, size_t offset), - void (*record)(void *priv, struct lttng_ust_ring_buffer_ctx *ctx, + size_t (*get_size)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + size_t offset), + void (*record)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + struct lttng_ust_ring_buffer_ctx *ctx, struct lttng_ust_channel_buffer *chan), - void (*get_value)(void *priv, struct lttng_ust_ctx_value *value), - void *priv) + void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx, + struct lttng_ust_ctx_value *value)) { struct lttng_event_notifier_group *event_notifier_group; @@ -2050,7 +2112,7 @@ void lttng_ust_context_set_event_notifier_group_provider(const char *name, ret = lttng_ust_context_set_provider_rcu( &event_notifier_group->ctx, - name, get_size, record, get_value, priv); + name, get_size, record, get_value); if (ret) abort(); }