doc: remove duplicate LTTNG_UST_BLOCKING_RETRY_TIMEOUT man page entry
[lttng-ust.git] / liblttng-ust / tracepoint.c
index a594d73ddd7bc6a3c893acd3d645635d23bc6c73..14b8231f879fca9d3aa8e3bde5a6a661cbb6b4c2 100644 (file)
 #include "error.h"
 
 /* Test compiler support for weak symbols with hidden visibility. */
-char __tracepoint_test_symbol[9] __attribute__((weak, visibility("hidden")));
+int __tracepoint_test_symbol1 __attribute__((weak, visibility("hidden")));
+void *__tracepoint_test_symbol2 __attribute__((weak, visibility("hidden")));
+struct {
+       char a[24];
+} __tracepoint_test_symbol3 __attribute__((weak, visibility("hidden")));
 
 /* Set to 1 to enable tracepoint debug output */
 static const int tracepoint_debug;
@@ -89,6 +93,9 @@ static struct cds_hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
 static CDS_LIST_HEAD(old_probes);
 static int need_update;
 
+static CDS_LIST_HEAD(release_queue);
+static int release_queue_need_update;
+
 /*
  * Note about RCU :
  * It is used to to delay the free of multiple probes array until a quiescent
@@ -549,6 +556,16 @@ tracepoint_add_probe(const char *name, void (*probe)(void), void *data,
        return old;
 }
 
+static void tracepoint_release_queue_add_old_probes(void *old)
+{
+       release_queue_need_update = 1;
+       if (old) {
+               struct tp_probes *tp_probes = caa_container_of(old,
+                       struct tp_probes, probes[0]);
+               cds_list_add(&tp_probes->u.list, &release_queue);
+       }
+}
+
 /**
  * __tracepoint_probe_register -  Connect a probe to a tracepoint
  * @name: tracepoint name
@@ -580,6 +597,33 @@ end:
        return ret;
 }
 
+/*
+ * Caller needs to invoke __tracepoint_probe_release_queue() after
+ * calling __tracepoint_probe_register_queue_release() one or multiple
+ * times to ensure it does not leak memory.
+ */
+int __tracepoint_probe_register_queue_release(const char *name,
+               void (*probe)(void), void *data, const char *signature)
+{
+       void *old;
+       int ret = 0;
+
+       DBG("Registering probe to tracepoint %s. Queuing release.", name);
+
+       pthread_mutex_lock(&tracepoint_mutex);
+       old = tracepoint_add_probe(name, probe, data, signature);
+       if (IS_ERR(old)) {
+               ret = PTR_ERR(old);
+               goto end;
+       }
+
+       tracepoint_sync_callsites(name);
+       tracepoint_release_queue_add_old_probes(old);
+end:
+       pthread_mutex_unlock(&tracepoint_mutex);
+       return ret;
+}
+
 static void *tracepoint_remove_probe(const char *name, void (*probe)(void),
                void *data)
 {
@@ -624,6 +668,57 @@ end:
        return ret;
 }
 
+/*
+ * Caller needs to invoke __tracepoint_probe_release_queue() after
+ * calling __tracepoint_probe_unregister_queue_release() one or multiple
+ * times to ensure it does not leak memory.
+ */
+int __tracepoint_probe_unregister_queue_release(const char *name,
+               void (*probe)(void), void *data)
+{
+       void *old;
+       int ret = 0;
+
+       DBG("Un-registering probe from tracepoint %s. Queuing release.", name);
+
+       pthread_mutex_lock(&tracepoint_mutex);
+       old = tracepoint_remove_probe(name, probe, data);
+       if (IS_ERR(old)) {
+               ret = PTR_ERR(old);
+               goto end;
+       }
+       tracepoint_sync_callsites(name);
+       tracepoint_release_queue_add_old_probes(old);
+end:
+       pthread_mutex_unlock(&tracepoint_mutex);
+       return ret;
+}
+
+void __tracepoint_probe_prune_release_queue(void)
+{
+       CDS_LIST_HEAD(release_probes);
+       struct tp_probes *pos, *next;
+
+       DBG("Release queue of unregistered tracepoint probes.");
+
+       pthread_mutex_lock(&tracepoint_mutex);
+       if (!release_queue_need_update)
+               goto end;
+       if (!cds_list_empty(&release_queue))
+               cds_list_replace_init(&release_queue, &release_probes);
+       release_queue_need_update = 0;
+
+       /* Wait for grace period between all sync_callsites and free. */
+       synchronize_rcu();
+
+       cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
+               cds_list_del(&pos->u.list);
+               free(pos);
+       }
+end:
+       pthread_mutex_unlock(&tracepoint_mutex);
+}
+
 static void tracepoint_add_old_probes(void *old)
 {
        need_update = 1;
@@ -704,9 +799,10 @@ void tracepoint_probe_update_all(void)
        need_update = 0;
 
        tracepoint_update_probes();
+       /* Wait for grace period between update_probes and free. */
+       synchronize_rcu();
        cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
                cds_list_del(&pos->u.list);
-               synchronize_rcu();
                free(pos);
        }
 end:
@@ -814,10 +910,18 @@ int tracepoint_unregister_lib(struct lttng_ust_tracepoint * const *tracepoints_s
  */
 static void check_weak_hidden(void)
 {
-       DBG("Your compiler support for weak symbols with hidden visibility is %s",
-               __tracepoint_test_symbol == lttng_ust_tp_check_weak_hidden() ?
-                       "OK" :
-                       "BROKEN. Please upgrade or fix your compiler to use LTTng-UST tracepoints.");
+       DBG("Your compiler treats weak symbols with hidden visibility for integer objects as %s between compile units part of the same module.",
+               &__tracepoint_test_symbol1 == lttng_ust_tp_check_weak_hidden1() ?
+                       "SAME address" :
+                       "DIFFERENT addresses");
+       DBG("Your compiler treats weak symbols with hidden visibility for pointer objects as %s between compile units part of the same module.",
+               &__tracepoint_test_symbol2 == lttng_ust_tp_check_weak_hidden2() ?
+                       "SAME address" :
+                       "DIFFERENT addresses");
+       DBG("Your compiler treats weak symbols with hidden visibility for 24-byte structure objects as %s between compile units part of the same module.",
+               &__tracepoint_test_symbol3 == lttng_ust_tp_check_weak_hidden3() ?
+                       "SAME address" :
+                       "DIFFERENT addresses");
 }
 
 void init_tracepoint(void)
This page took 0.024623 seconds and 4 git commands to generate.