Use iterator on tracepoint probes instead of tracepoints per se
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 3 Dec 2011 22:37:41 +0000 (17:37 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 3 Dec 2011 22:37:41 +0000 (17:37 -0500)
- Simplify iteration locking scheme by using a linked list to store all
  the tracepoints to be iterated on.
- Allow getting the loglevel in addition to the tracepoint name.

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

index 45358d422ec9c54d972c5e16c5379790b97d9855..0a03193920229cc6406f51b0752b4744309f587c 100644 (file)
@@ -206,9 +206,14 @@ struct lttng_probe_desc {
        struct cds_list_head head;              /* chain registered probes */
 };
 
-struct tp_loglevel_iter {
-       struct lttng_probe_desc *desc;
-       const struct tracepoint_loglevel_entry *loglevel;
+struct tp_list_entry {
+       struct lttng_ust_tracepoint_iter tp;
+       struct cds_list_head head;
+};
+
+struct lttng_ust_tracepoint_list {
+       struct tp_list_entry *iter;
+       struct cds_list_head head;
 };
 
 struct ust_pending_probe;
@@ -378,4 +383,9 @@ const struct lttng_ust_lib_ring_buffer_client_cb *lttng_client_callbacks_overwri
 
 struct ltt_transport *ltt_transport_find(const char *name);
 
+int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list);
+void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list);
+struct lttng_ust_tracepoint_iter *
+       lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list);
+
 #endif /* _LTTNG_UST_EVENTS_H */
index 5f55bfa898a62e1c2c4a795d30e7499944621890..957a9b59ba55afd64794e05294b833bad1b6f17a 100644 (file)
@@ -13,6 +13,7 @@
 #include <urcu/list.h>
 #include <lttng/ust-events.h>
 #include <assert.h>
+#include <helper.h>
 
 #include "ltt-tracer-core.h"
 
@@ -121,3 +122,79 @@ const struct lttng_event_desc *ltt_event_get(const char *name)
 void ltt_event_put(const struct lttng_event_desc *event)
 {
 }
+
+void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
+{
+       struct tp_list_entry *list_entry, *tmp;
+
+       cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) {
+               cds_list_del(&list_entry->head);
+               free(list_entry);
+       }
+}
+
+/*
+ * called with UST lock held.
+ */
+int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list)
+{
+       struct lttng_probe_desc *probe_desc;
+       int i;
+
+       CDS_INIT_LIST_HEAD(&list->head);
+       cds_list_for_each_entry(probe_desc, &probe_list, head) {
+               for (i = 0; i < probe_desc->nr_events; i++) {
+                       struct tp_list_entry *list_entry;
+
+                       list_entry = zmalloc(sizeof(*list_entry));
+                       if (!list_entry)
+                               goto err_nomem;
+                       cds_list_add(&list_entry->head, &list->head);
+                       strncpy(list_entry->tp.name,
+                               probe_desc->event_desc[i]->name,
+                               LTTNG_UST_SYM_NAME_LEN);
+                       list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+                       if (!probe_desc->event_desc[i]->loglevel) {
+                               list_entry->tp.loglevel[0] = '\0';
+                               list_entry->tp.loglevel_value = 0;
+                       } else {
+                               strncpy(list_entry->tp.loglevel,
+                                       (*probe_desc->event_desc[i]->loglevel)->identifier,
+                                       LTTNG_UST_SYM_NAME_LEN);
+                               list_entry->tp.loglevel[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+                               list_entry->tp.loglevel_value =
+                                       (*probe_desc->event_desc[i]->loglevel)->value;
+                       }
+               }
+       }
+       if (cds_list_empty(&list->head))
+               list->iter = NULL;
+       else
+               list->iter =
+                       cds_list_first_entry(&list->head, struct tp_list_entry, head);
+       return 0;
+
+err_nomem:
+       ltt_probes_prune_event_list(list);
+       return -ENOMEM;
+}
+
+/*
+ * Return current iteration position, advance internal iterator to next.
+ * Return NULL if end of list.
+ */
+struct lttng_ust_tracepoint_iter *
+       lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list)
+{
+       struct tp_list_entry *entry;
+
+       if (!list->iter)
+               return NULL;
+       entry = list->iter;
+       if (entry->head.next == &list->head)
+               list->iter = NULL;
+       else
+               list->iter = cds_list_entry(entry->head.next,
+                               struct tp_list_entry, head);
+       return &entry->tp;
+}
index d146e1023efda3c70ee21db5be17a61d63070dc5..900f7834e196bcefeb4a953ac39d041d1ebec895 100644 (file)
 #include "ltt-tracer.h"
 #include "tracepoint-internal.h"
 
-struct ltt_tracepoint_list {
-       struct tracepoint_iter iter;
-       int got_first;
-};
-
 static int lttng_ust_abi_close_in_progress;
 
 static
@@ -502,62 +497,26 @@ static const struct lttng_ust_objd_ops lttng_session_ops = {
        .cmd = lttng_session_cmd,
 };
 
-/*
- * beware: we don't keep the mutex over the send, but we must walk the
- * whole list each time we are called again. So sending one tracepoint
- * at a time means this is O(n^2). TODO: do as in the kernel and send
- * multiple tracepoints for each call to amortize this cost.
- */
-static
-void ltt_tracepoint_list_get(struct ltt_tracepoint_list *list,
-               struct lttng_ust_tracepoint_iter *tracepoint)
-{
-next:
-       if (!list->got_first) {
-               tracepoint_iter_start(&list->iter);
-               list->got_first = 1;
-               goto copy;
-       }
-       tracepoint_iter_next(&list->iter);
-copy:
-       if (!list->iter.tracepoint) {
-               tracepoint->name[0] = '\0';     /* end of list */
-       } else {
-               if (!strcmp((*list->iter.tracepoint)->name,
-                               "lttng_ust:metadata"))
-                       goto next;
-               memcpy(tracepoint->name, (*list->iter.tracepoint)->name,
-                       LTTNG_UST_SYM_NAME_LEN);
-#if 0
-               if ((*list->iter.tracepoint)->loglevel) {
-                       memcpy(tracepoint->loglevel,
-                               (*list->iter.tracepoint)->loglevel->identifier,
-                               LTTNG_UST_SYM_NAME_LEN);
-                       tracepoint->loglevel_value =
-                               (*list->iter.tracepoint)->loglevel->value;
-               } else {
-#endif
-                       tracepoint->loglevel[0] = '\0';
-                       tracepoint->loglevel_value = 0;
-#if 0
-               }
-#endif
-       }
-}
-
 static
 long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg)
 {
-       struct ltt_tracepoint_list *list = objd_private(objd);
+       struct lttng_ust_tracepoint_list *list = objd_private(objd);
        struct lttng_ust_tracepoint_iter *tp =
                (struct lttng_ust_tracepoint_iter *) arg;
+       struct lttng_ust_tracepoint_iter *iter;
 
        switch (cmd) {
        case LTTNG_UST_TRACEPOINT_LIST_GET:
-               ltt_tracepoint_list_get(list, tp);
-               if (tp->name[0] == '\0')
+       {
+       retry:
+               iter = lttng_ust_tracepoint_list_get_iter_next(list);
+               if (!iter)
                        return -ENOENT;
+               if (!strcmp(iter->name, "lttng_ust:metadata"))
+                       goto retry;
+               memcpy(tp, iter, sizeof(*tp));
                return 0;
+       }
        default:
                return -EINVAL;
        }
@@ -567,7 +526,7 @@ static
 int lttng_abi_tracepoint_list(void)
 {
        int list_objd, ret;
-       struct ltt_tracepoint_list *list;
+       struct lttng_ust_tracepoint_list *list;
 
        list_objd = objd_alloc(NULL, &lttng_tracepoint_list_ops);
        if (list_objd < 0) {
@@ -581,8 +540,15 @@ int lttng_abi_tracepoint_list(void)
        }
        objd_set_private(list_objd, list);
 
+       /* populate list by walking on all registered probes. */
+       ret = ltt_probes_get_event_list(list);
+       if (ret) {
+               goto list_error;
+       }
        return list_objd;
 
+list_error:
+       free(list);
 alloc_error:
        {
                int err;
@@ -597,10 +563,10 @@ objd_error:
 static
 int lttng_release_tracepoint_list(int objd)
 {
-       struct ltt_tracepoint_list *list = objd_private(objd);
+       struct lttng_ust_tracepoint_list *list = objd_private(objd);
 
        if (list) {
-               tracepoint_iter_stop(&list->iter);
+               ltt_probes_prune_event_list(list);
                free(list);
                return 0;
        } else {
index 01d8c8bfdfc3dc9dae05429153d76c745581678f..8ac6487f7b00078db5fa12496991b6d72decde5c 100644 (file)
@@ -29,22 +29,10 @@ struct tracepoint_lib {
        int tracepoints_count;
 };
 
-struct tracepoint_iter {
-       struct tracepoint_lib *lib;
-       struct tracepoint * const *tracepoint;
-};
-
 extern int tracepoint_probe_register_noupdate(const char *name, void *callback, void *priv);
 extern int tracepoint_probe_unregister_noupdate(const char *name, void *callback, void *priv);
 extern void tracepoint_probe_update_all(void);
 
-extern void tracepoint_iter_start(struct tracepoint_iter *iter);
-extern void tracepoint_iter_next(struct tracepoint_iter *iter);
-extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
-extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
-extern int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
-       struct tracepoint * const *begin, struct tracepoint * const *end);
-
 /*
  * call after disconnection of last probe implemented within a
  * shared object before unmapping the library that contains the probe.
index 1e252ce39d859fc10cc1766757db9ace908da7fe..e8241e8abd3cd29dfb0931f0edc2abbf17a43fe3 100644 (file)
@@ -491,105 +491,6 @@ void tracepoint_probe_update_all(void)
        }
 }
 
-/*
- * Returns 0 if current not found.
- * Returns 1 if current found.
- *
- * Called with UST lock held
- */
-int lib_get_iter_tracepoints(struct tracepoint_iter *iter)
-{
-       struct tracepoint_lib *iter_lib;
-       int found = 0;
-
-       cds_list_for_each_entry(iter_lib, &libs, list) {
-               if (iter_lib < iter->lib)
-                       continue;
-               else if (iter_lib > iter->lib)
-                       iter->tracepoint = NULL;
-               found = tracepoint_get_iter_range(&iter->tracepoint,
-                       iter_lib->tracepoints_start,
-                       iter_lib->tracepoints_start + iter_lib->tracepoints_count);
-               if (found) {
-                       iter->lib = iter_lib;
-                       break;
-               }
-       }
-       return found;
-}
-
-/**
- * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
- * @tracepoint: current tracepoints (in), next tracepoint (out)
- * @begin: beginning of the range
- * @end: end of the range
- *
- * Returns whether a next tracepoint has been found (1) or not (0).
- * Will return the first tracepoint in the range if the input tracepoint is
- * NULL.
- * Called with UST lock held.
- */
-int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
-       struct tracepoint * const *begin, struct tracepoint * const *end)
-{
-       if (!*tracepoint && begin != end)
-               *tracepoint = begin;
-       while (*tracepoint >= begin && *tracepoint < end) {
-               if (!**tracepoint)
-                       (*tracepoint)++;        /* skip dummy */
-               else
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * Called with UST lock held.
- */
-static void tracepoint_get_iter(struct tracepoint_iter *iter)
-{
-       int found = 0;
-
-       /* tracepoints in libs. */
-       found = lib_get_iter_tracepoints(iter);
-       if (!found)
-               tracepoint_iter_reset(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_start(struct tracepoint_iter *iter)
-{
-       tracepoint_get_iter(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_next(struct tracepoint_iter *iter)
-{
-       iter->tracepoint++;
-       /*
-        * iter->tracepoint may be invalid because we blindly incremented it.
-        * Make sure it is valid by marshalling on the tracepoints, getting the
-        * tracepoints from following library if necessary.
-        */
-       tracepoint_get_iter(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_stop(struct tracepoint_iter *iter)
-{
-}
-
-void tracepoint_iter_reset(struct tracepoint_iter *iter)
-{
-       iter->tracepoint = NULL;
-}
-
 void tracepoint_set_new_tracepoint_cb(void (*cb)(struct tracepoint *))
 {
        new_tracepoint_cb = cb;
This page took 0.030816 seconds and 4 git commands to generate.