Lazy provider registration
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 19 Feb 2013 15:43:10 +0000 (10:43 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 19 Feb 2013 15:43:10 +0000 (10:43 -0500)
Register probe providers lazily, so process startup time is not impacted
by the number of events (especially for large number of events) as long
as no UST tracing session is active.

Refs #446

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-events.h
liblttng-ust/lttng-events.c
liblttng-ust/lttng-probes.c

index e755e0c67a8aa45ce879856bce18f13782e08de6..c87a82c00a87277ec0b1144c31104ed385c96835 100644 (file)
@@ -241,12 +241,14 @@ struct lttng_event_desc {
        } u;
 };
 
-#define LTTNG_UST_PROBE_DESC_PADDING   40
+#define LTTNG_UST_PROBE_DESC_PADDING   20
 struct lttng_probe_desc {
        const char *provider;
        const struct lttng_event_desc **event_desc;
        unsigned int nr_events;
        struct cds_list_head head;              /* chain registered probes */
+       struct cds_list_head lazy_init_head;
+       int lazy;                               /* lazy registration */
        char padding[LTTNG_UST_PROBE_DESC_PADDING];
 };
 
@@ -544,5 +546,6 @@ void lttng_free_event_filter_runtime(struct lttng_event *event);
 void lttng_filter_sync_state(struct lttng_bytecode_runtime *runtime);
 
 struct cds_list_head *lttng_get_probe_list_head(void);
+int lttng_session_active(void);
 
 #endif /* _LTTNG_UST_EVENTS_H */
index 90b2307818e8375bae31054321d2e8207c60e7e6..3bf1ede3a6a30836d50e35f48fd837da79815c89 100644 (file)
@@ -91,6 +91,20 @@ void lttng_session_sync_enablers(struct lttng_session *session);
 static
 void lttng_enabler_destroy(struct lttng_enabler *enabler);
 
+/*
+ * Called with ust lock held.
+ */
+int lttng_session_active(void)
+{
+       struct lttng_session *iter;
+
+       cds_list_for_each_entry(iter, &sessions, node) {
+               if (iter->active)
+                       return 1;
+       }
+       return 0;
+}
+
 static
 int lttng_loglevel_match(int loglevel,
                unsigned int has_loglevel,
index ecf28646e26e768c6f7182d8b42c26ae842ef79a..b1d5fe28558433209f70460119125ca81b433793 100644 (file)
  */
 static CDS_LIST_HEAD(_probe_list);
 
-struct cds_list_head *lttng_get_probe_list_head(void)
-{
-       return &_probe_list;
-}
-
-static
-const struct lttng_probe_desc *find_provider(const char *provider)
-{
-       struct lttng_probe_desc *iter;
-       struct cds_list_head *probe_list;
+/*
+ * List of probes registered by not yet processed.
+ */
+static CDS_LIST_HEAD(lazy_probe_init);
 
-       probe_list = lttng_get_probe_list_head();
-       cds_list_for_each_entry(iter, probe_list, head) {
-               if (!strcmp(iter->provider, provider))
-                       return iter;
-       }
-       return NULL;
-}
+/*
+ * lazy_nesting counter ensures we don't trigger lazy probe registration
+ * fixup while we are performing the fixup. It is protected by the ust
+ * mutex.
+ */
+static int lazy_nesting;
 
+/*
+ * Called under ust lock.
+ */
 static
 int check_event_provider(struct lttng_probe_desc *desc)
 {
@@ -76,22 +72,15 @@ int check_event_provider(struct lttng_probe_desc *desc)
        return 1;
 }
 
-int lttng_probe_register(struct lttng_probe_desc *desc)
+/*
+ * Called under ust lock.
+ */
+static
+void lttng_lazy_probe_register(struct lttng_probe_desc *desc)
 {
        struct lttng_probe_desc *iter;
-       int ret = 0;
-       int i;
        struct cds_list_head *probe_list;
-
-       ust_lock();
-
-       /*
-        * Check if the provider has already been registered.
-        */
-       if (find_provider(desc->provider)) {
-               ret = -EEXIST;
-               goto end;
-       }
+       int i;
 
        /*
         * Each provider enforce that every event name begins with the
@@ -111,7 +100,7 @@ int lttng_probe_register(struct lttng_probe_desc *desc)
         * We sort the providers by struct lttng_probe_desc pointer
         * address.
         */
-       probe_list = lttng_get_probe_list_head();
+       probe_list = &_probe_list;
        cds_list_for_each_entry_reverse(iter, probe_list, head) {
                BUG_ON(iter == desc); /* Should never be in the list twice */
                if (iter < desc) {
@@ -130,6 +119,7 @@ desc_added:
         */
        for (i = 0; i < desc->nr_events; i++) {
                const struct lttng_event_desc *ed;
+               int ret;
 
                ed = desc->event_desc[i];
                DBG("Registered event probe \"%s\" with signature \"%s\"",
@@ -137,6 +127,74 @@ desc_added:
                ret = lttng_fix_pending_event_desc(ed);
                assert(!ret);
        }
+}
+
+/*
+ * Called under ust lock.
+ */
+static
+void fixup_lazy_probes(void)
+{
+       struct lttng_probe_desc *iter, *tmp;
+
+       lazy_nesting++;
+       cds_list_for_each_entry_safe(iter, tmp,
+                       &lazy_probe_init, lazy_init_head) {
+               lttng_lazy_probe_register(iter);
+               iter->lazy = 0;
+               cds_list_del(&iter->lazy_init_head);
+       }
+       lazy_nesting--;
+}
+
+/*
+ * Called under ust lock.
+ */
+struct cds_list_head *lttng_get_probe_list_head(void)
+{
+       if (!lazy_nesting && !cds_list_empty(&lazy_probe_init))
+               fixup_lazy_probes();
+       return &_probe_list;
+}
+
+static
+const struct lttng_probe_desc *find_provider(const char *provider)
+{
+       struct lttng_probe_desc *iter;
+       struct cds_list_head *probe_list;
+
+       probe_list = lttng_get_probe_list_head();
+       cds_list_for_each_entry(iter, probe_list, head) {
+               if (!strcmp(iter->provider, provider))
+                       return iter;
+       }
+       return NULL;
+}
+
+int lttng_probe_register(struct lttng_probe_desc *desc)
+{
+       int ret = 0;
+
+       ust_lock();
+
+       /*
+        * Check if the provider has already been registered.
+        */
+       if (find_provider(desc->provider)) {
+               ret = -EEXIST;
+               goto end;
+       }
+       cds_list_add(&desc->lazy_init_head, &lazy_probe_init);
+       desc->lazy = 1;
+       DBG("adding probe %s containing %u events to lazy registration list",
+               desc->provider, desc->nr_events);
+       /*
+        * If there is at least one active session, we need to register
+        * the probe immediately, since we cannot delay event
+        * registration because they are needed ASAP.
+        */
+       if (lttng_session_active())
+               fixup_lazy_probes();
 end:
        ust_unlock();
        return ret;
@@ -151,7 +209,10 @@ int ltt_probe_register(struct lttng_probe_desc *desc)
 void lttng_probe_unregister(struct lttng_probe_desc *desc)
 {
        ust_lock();
-       cds_list_del(&desc->head);
+       if (!desc->lazy)
+               cds_list_del(&desc->head);
+       else
+               cds_list_del(&desc->lazy_init_head);
        DBG("just unregistered probe %s", desc->provider);
        ust_unlock();
 }
This page took 0.028738 seconds and 4 git commands to generate.