LTTng-UST probe registration is O(n^2). I actually left a comment that
describes this, also implying that we can improve this if it becomes an
issue.
I've had a report from Yang Wang, who works on instrumenting the J9 VM,
that O(n^2) does not agree well with 16000 probes and tracepoints.
It appears that lttng_probe_register() is being too paranoid for its own
good. There are now many things that are guaranteed by the way probe
providers are being built.
We actually need to keep a check that no provider with the same name has
been registered (O(n) on the number of registered providers, could be
improved with a hash table if it ever becomes necessary).
Use an assert to check that each event name starts with its own provider
name (it would be an internal error within the provider if it's not the
case). (O(n) on the number of events within a provider)
The rest is just useless, so remove this O(n^2) check.
While we are there, remove the now unused
lttng_event_get()/lttng_event_put() functions.
Reported-by: Yang Wang <yangw.wang5@unb.ca>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
int lttng_probe_register(struct lttng_probe_desc *desc);
void lttng_probe_unregister(struct lttng_probe_desc *desc);
int lttng_fix_pending_event_desc(const struct lttng_event_desc *desc);
int lttng_probe_register(struct lttng_probe_desc *desc);
void lttng_probe_unregister(struct lttng_probe_desc *desc);
int lttng_fix_pending_event_desc(const struct lttng_event_desc *desc);
-const struct lttng_event_desc *lttng_event_get(const char *name);
-void lttng_event_put(const struct lttng_event_desc *desc);
int lttng_probes_init(void);
void lttng_probes_exit(void);
int lttng_find_context(struct lttng_ctx *ctx, const char *name);
int lttng_probes_init(void);
void lttng_probes_exit(void);
int lttng_find_context(struct lttng_ctx *ctx, const char *name);
WARN_ON_ONCE(__tracepoint_probe_unregister(event_name,
desc->probe_callback,
event));
WARN_ON_ONCE(__tracepoint_probe_unregister(event_name,
desc->probe_callback,
event));
- lttng_event_put(event->desc);
register_error:
free(event);
cache_error:
register_error:
free(event);
cache_error:
{
struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
{
struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
- lttng_event_put(event->desc);
cds_list_del(&event->node);
lttng_destroy_context(event->ctx);
lttng_free_event_filter_runtime(event);
cds_list_del(&event->node);
lttng_destroy_context(event->ctx);
lttng_free_event_filter_runtime(event);
-const struct lttng_event_desc *find_event(const char *name)
+int check_event_provider(struct lttng_probe_desc *desc)
- struct lttng_probe_desc *probe_desc;
+ size_t provider_name_len;
- cds_list_for_each_entry(probe_desc, &probe_list, head) {
- for (i = 0; i < probe_desc->nr_events; i++) {
- if (!strncmp(probe_desc->event_desc[i]->name, name,
- LTTNG_UST_SYM_NAME_LEN - 1))
- return probe_desc->event_desc[i];
- }
+ provider_name_len = strnlen(desc->provider,
+ LTTNG_UST_SYM_NAME_LEN - 1);
+ for (i = 0; i < desc->nr_events; i++) {
+ if (strncmp(desc->event_desc[i]->name,
+ desc->provider,
+ provider_name_len))
+ return 0; /* provider mismatch */
}
int lttng_probe_register(struct lttng_probe_desc *desc)
}
int lttng_probe_register(struct lttng_probe_desc *desc)
+
+ /*
+ * Check if the provider has already been registered.
+ */
if (find_provider(desc->provider)) {
ret = -EEXIST;
goto end;
}
if (find_provider(desc->provider)) {
ret = -EEXIST;
goto end;
}
- * TODO: This is O(N^2). Turn into a hash table when probe registration
- * overhead becomes an issue.
+ * Each provider enforce that every event name begins with the
+ * provider name. Check this in an assertion for extra
+ * carefulness. This ensures we cannot have duplicate event
+ * names across providers.
+ */
+ assert(check_event_provider(desc));
+
+ /*
+ * The provider ensures there are no duplicate event names.
+ * Duplicated TRACEPOINT_EVENT event names would generate a
+ * compile-time error due to duplicated symbol names.
- for (i = 0; i < desc->nr_events; i++) {
- if (find_event(desc->event_desc[i]->name)) {
- ret = -EEXIST;
- goto end;
- }
- }
/*
* We sort the providers by struct lttng_probe_desc pointer
/*
* We sort the providers by struct lttng_probe_desc pointer
lttng_probe_unregister(desc);
}
lttng_probe_unregister(desc);
}
-/*
- * called with UST lock held.
- */
-const struct lttng_event_desc *lttng_event_get(const char *name)
-{
- const struct lttng_event_desc *event;
-
- event = find_event(name);
- if (!event)
- return NULL;
- return event;
-}
-
-void lttng_event_put(const struct lttng_event_desc *event)
-{
-}
-
void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
{
struct tp_list_entry *list_entry, *tmp;
void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
{
struct tp_list_entry *list_entry, *tmp;