From c8fcf224e283ed7679c84cbcccf70ac65ca7e41d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 3 Dec 2011 17:37:41 -0500 Subject: [PATCH] Use iterator on tracepoint probes instead of tracepoints per se - 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 --- include/lttng/ust-events.h | 16 ++++- liblttng-ust/ltt-probes.c | 77 +++++++++++++++++++++++ liblttng-ust/lttng-ust-abi.c | 74 ++++++---------------- liblttng-ust/tracepoint-internal.h | 12 ---- liblttng-ust/tracepoint.c | 99 ------------------------------ 5 files changed, 110 insertions(+), 168 deletions(-) diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 45358d42..0a031939 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -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 */ diff --git a/liblttng-ust/ltt-probes.c b/liblttng-ust/ltt-probes.c index 5f55bfa8..957a9b59 100644 --- a/liblttng-ust/ltt-probes.c +++ b/liblttng-ust/ltt-probes.c @@ -13,6 +13,7 @@ #include #include #include +#include #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; +} diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index d146e102..900f7834 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -34,11 +34,6 @@ #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, <tng_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 { diff --git a/liblttng-ust/tracepoint-internal.h b/liblttng-ust/tracepoint-internal.h index 01d8c8bf..8ac6487f 100644 --- a/liblttng-ust/tracepoint-internal.h +++ b/liblttng-ust/tracepoint-internal.h @@ -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. diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c index 1e252ce3..e8241e8a 100644 --- a/liblttng-ust/tracepoint.c +++ b/liblttng-ust/tracepoint.c @@ -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; -- 2.34.1