X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Fltt-probes.c;h=15c83873f6ad25ab038b638b5ff2ec8243f2f793;hb=7a673d9947d11a37d08be89a5c157afdfd377f9f;hp=fda35bf994104f9dc2d6b27b24d4a86f15375ce4;hpb=a3bb4b278286aaa20867ba68bd5b5a5853974126;p=lttng-ust.git diff --git a/liblttng-ust/ltt-probes.c b/liblttng-ust/ltt-probes.c index fda35bf9..15c83873 100644 --- a/liblttng-ust/ltt-probes.c +++ b/liblttng-ust/ltt-probes.c @@ -1,27 +1,57 @@ /* * ltt-probes.c * - * Copyright 2010 (c) - Mathieu Desnoyers - * * Holds LTTng probes registry. * - * Dual LGPL v2.1/GPL v2 license. + * Copyright 2010-2012 (c) - Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include -#include +#include #include +#include +#include "tracepoint-internal.h" #include +#include +#include #include "ltt-tracer-core.h" +#include "jhash.h" +#include "error.h" /* * probe list is protected by ust_lock()/ust_unlock(). */ static CDS_LIST_HEAD(probe_list); +static +const struct lttng_probe_desc *find_provider(const char *provider) +{ + struct lttng_probe_desc *iter; + + cds_list_for_each_entry(iter, &probe_list, head) { + if (!strcmp(iter->provider, provider)) + return iter; + } + return NULL; +} + static const struct lttng_event_desc *find_event(const char *name) { @@ -30,8 +60,9 @@ const struct lttng_event_desc *find_event(const char *name) cds_list_for_each_entry(probe_desc, &probe_list, head) { for (i = 0; i < probe_desc->nr_events; i++) { - if (!strcmp(probe_desc->event_desc[i].name, name)) - return &probe_desc->event_desc[i]; + if (!strncmp(probe_desc->event_desc[i]->name, name, + LTTNG_UST_SYM_NAME_LEN - 1)) + return probe_desc->event_desc[i]; } } return NULL; @@ -39,27 +70,53 @@ const struct lttng_event_desc *find_event(const char *name) int ltt_probe_register(struct lttng_probe_desc *desc) { + struct lttng_probe_desc *iter; int ret = 0; int i; ust_lock(); + 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. */ for (i = 0; i < desc->nr_events; i++) { - if (find_event(desc->event_desc[i].name)) { + if (find_event(desc->event_desc[i]->name)) { ret = -EEXIST; goto end; } } - cds_list_add(&desc->head, &probe_list); + /* + * We sort the providers by struct lttng_probe_desc pointer + * address. + */ + cds_list_for_each_entry_reverse(iter, &probe_list, head) { + BUG_ON(iter == desc); /* Should never be in the list twice */ + if (iter < desc) { + /* We belong to the location right after iter. */ + cds_list_add(&desc->head, &iter->head); + goto desc_added; + } + } + /* We should be added at the head of the list */ + cds_list_add(&desc->head, &probe_list); +desc_added: + DBG("just registered probe %s containing %u events", + desc->provider, desc->nr_events); /* * fix the events awaiting probe load. */ for (i = 0; i < desc->nr_events; i++) { - ret = pending_probe_fix_events(&desc->event_desc[i]); + const struct lttng_event_desc *ed; + + ed = desc->event_desc[i]; + DBG("Registered event probe \"%s\" with signature \"%s\"", + ed->name, ed->signature); + ret = pending_probe_fix_events(ed); assert(!ret); } end: @@ -71,6 +128,7 @@ void ltt_probe_unregister(struct lttng_probe_desc *desc) { ust_lock(); cds_list_del(&desc->head); + DBG("just unregistered probe %s", desc->provider); ust_unlock(); } @@ -91,80 +149,127 @@ void ltt_event_put(const struct lttng_event_desc *event) { } -#if 0 -static -void *tp_list_start(struct seq_file *m, loff_t *pos) +void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list) { - struct lttng_probe_desc *probe_desc; - int iter = 0, i; + struct tp_list_entry *list_entry, *tmp; - pthread_mutex_lock(&probe_mutex); - cds_list_for_each_entry(probe_desc, &probe_list, head) { - for (i = 0; i < probe_desc->nr_events; i++) { - if (iter++ >= *pos) - return (void *) &probe_desc->event_desc[i]; - } + cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) { + cds_list_del(&list_entry->head); + free(list_entry); } - /* End of list */ - return NULL; } -static -void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos) +/* + * called with UST lock held. + */ +int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list) { struct lttng_probe_desc *probe_desc; - int iter = 0, i; + int i; - (*ppos)++; + 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++) { - if (iter++ >= *ppos) - return (void *) &probe_desc->event_desc[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 = TRACE_DEFAULT; + } else { + list_entry->tp.loglevel = *(*probe_desc->event_desc[i]->loglevel); + } } } - /* End of list */ - return NULL; + 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; } -static -void tp_list_stop(struct seq_file *m, void *p) +/* + * 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) { - pthread_mutex_unlock(&probe_mutex); + 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; } -static -int tp_list_show(struct seq_file *m, void *p) +/* + * marshall all probes/all events and create those that fit the + * wildcard. Add them to the events list as created. + */ +void ltt_probes_create_wildcard_events(struct wildcard_entry *entry, + struct session_wildcard *wildcard) { - const struct lttng_event_desc *probe_desc = p; + struct lttng_probe_desc *probe_desc; + struct lttng_ust_event event_param; + int i; - /* - * Don't export lttng internal events (metadata). - */ - if (!strncmp(probe_desc->name, "lttng_", sizeof("lttng_") - 1)) - return 0; - seq_printf(m, "event { name = %s; };\n", - probe_desc->name); - return 0; -} + cds_list_for_each_entry(probe_desc, &probe_list, head) { + for (i = 0; i < probe_desc->nr_events; i++) { + const struct lttng_event_desc *event_desc; + int match = 0; -static -const struct seq_operations lttng_tracepoint_list_seq_ops = { - .start = tp_list_start, - .next = tp_list_next, - .stop = tp_list_stop, - .show = tp_list_show, -}; + event_desc = probe_desc->event_desc[i]; + /* compare excluding final '*' */ + assert(strlen(entry->name) > 0); + if (strcmp(event_desc->name, "lttng_ust:metadata") + && (strlen(entry->name) == 1 + || !strncmp(event_desc->name, entry->name, + strlen(entry->name) - 1))) { + if (ltt_loglevel_match(event_desc, + entry->loglevel_type, + entry->loglevel)) { + match = 1; + } + } + if (match) { + struct ltt_event *ev; + int ret; -static -int lttng_tracepoint_list_open(struct inode *inode, struct file *file) -{ - return seq_open(file, <tng_tracepoint_list_seq_ops); + memcpy(&event_param, &wildcard->event_param, + sizeof(event_param)); + strncpy(event_param.name, + event_desc->name, + sizeof(event_param.name)); + event_param.name[sizeof(event_param.name) - 1] = '\0'; + /* create event */ + ret = ltt_event_create(wildcard->chan, + &event_param, NULL, + &ev); + if (ret) { + DBG("Error creating event"); + continue; + } + cds_list_add(&ev->wildcard_list, + &wildcard->events); + } + } + } } -const struct file_operations lttng_tracepoint_list_fops = { - .open = lttng_tracepoint_list_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; -#endif //0