Introduce sync vs unsync enablers
[lttng-ust.git] / src / lib / lttng-ust / lttng-events.c
index 4bacbb951e7405cbd03ff849ba48614fb3d0c985..e618dce62c4f12ecc031a4322c7cb5c556ed3d80 100644 (file)
 #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,
@@ -2003,8 +2061,7 @@ void lttng_ust_context_set_session_provider(const char *name,
                        struct lttng_ust_ring_buffer_ctx *ctx,
                        struct lttng_ust_channel_buffer *chan),
                void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
-                       struct lttng_ust_ctx_value *value),
-               void *priv)
+                       struct lttng_ust_ctx_value *value))
 {
        struct lttng_ust_session_private *session_priv;
 
@@ -2014,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();
                }
@@ -2046,8 +2103,7 @@ void lttng_ust_context_set_event_notifier_group_provider(const char *name,
                        struct lttng_ust_ring_buffer_ctx *ctx,
                        struct lttng_ust_channel_buffer *chan),
                void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
-                       struct lttng_ust_ctx_value *value),
-               void *priv)
+                       struct lttng_ust_ctx_value *value))
 {
        struct lttng_event_notifier_group *event_notifier_group;
 
@@ -2056,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();
        }
This page took 0.029225 seconds and 4 git commands to generate.