X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Fltt-events.c;h=7882f6d2a63b84fdc0a2659b69d3e6e6d99027c0;hb=48740cab6057816414ac66a16c17275a7713ba16;hp=c97727348cb18834fb4a38e3b763f30e7fab3eae;hpb=23c8854a5fa1120df5cfdfbf08f00e00976f95fa;p=lttng-ust.git diff --git a/liblttng-ust/ltt-events.c b/liblttng-ust/ltt-events.c index c9772734..7882f6d2 100644 --- a/liblttng-ust/ltt-events.c +++ b/liblttng-ust/ltt-events.c @@ -14,31 +14,37 @@ #include #include #include -#include -#include -#include #include -#include #include #include #include +#include +#include + +#include +#include +#include +#include + +#include #include -#include -#include "lttng/core.h" + +#include +#include +#include "error.h" + #include "ltt-tracer.h" #include "ltt-tracer-core.h" #include "wait.h" #include "../libringbuffer/shm.h" -#include -#include -#include +#include "jhash.h" /* * The sessions mutex is the centralized mutex across UST tracing * control and probe registration. All operations within this file are * called by the communication thread, under ust_lock protection. */ -static DEFINE_MUTEX(sessions_mutex); +static pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER; void ust_lock(void) { @@ -68,6 +74,7 @@ struct ust_pending_probe { }; static void _ltt_event_destroy(struct ltt_event *event); +static void _ltt_loglevel_destroy(struct session_loglevel *sl); static void _ltt_channel_destroy(struct ltt_channel *chan); static int _ltt_event_unregister(struct ltt_event *event); static @@ -128,6 +135,46 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc) size_t name_len = strlen(name) + 1; uint32_t hash = jhash(name, name_len - 1, 0); int ret = 0; + struct lttng_ust_event event_param; + + /* + * For this event, we need to lookup the loglevel. If active (in + * the active loglevels hash table), we must create the event. + */ + if (desc->loglevel) { + const struct tracepoint_loglevel_entry *ev_ll; + struct loglevel_entry *loglevel; + + ev_ll = *desc->loglevel; + loglevel = get_loglevel(ev_ll->identifier); + if (!loglevel) + loglevel = get_loglevel_value(ev_ll->value); + if (loglevel) { + struct session_loglevel *sl; + + cds_list_for_each_entry(sl, &loglevel->session_list, + session_list) { + struct ltt_event *ev; + int ret; + + memcpy(&event_param, &sl->event_param, + sizeof(event_param)); + memcpy(event_param.name, + desc->name, + sizeof(event_param.name)); + /* create event */ + ret = ltt_event_create(sl->chan, + &event_param, NULL, + &ev); + if (ret) { + DBG("Error creating event"); + continue; + } + cds_list_add(&ev->loglevel_list, + &sl->events); + } + } + } head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)]; cds_hlist_for_each_entry_safe(e, node, p, head, node) { @@ -168,6 +215,7 @@ struct ltt_session *ltt_session_create(void) return NULL; CDS_INIT_LIST_HEAD(&session->chan); CDS_INIT_LIST_HEAD(&session->events); + CDS_INIT_LIST_HEAD(&session->loglevels); uuid_generate(session->uuid); cds_list_add(&session->list, &sessions); return session; @@ -177,6 +225,7 @@ void ltt_session_destroy(struct ltt_session *session) { struct ltt_channel *chan, *tmpchan; struct ltt_event *event, *tmpevent; + struct session_loglevel *loglevel, *tmploglevel; int ret; CMM_ACCESS_ONCE(session->active) = 0; @@ -185,6 +234,8 @@ void ltt_session_destroy(struct ltt_session *session) WARN_ON(ret); } synchronize_trace(); /* Wait for in-flight events to complete */ + cds_list_for_each_entry_safe(loglevel, tmploglevel, &session->loglevels, list) + _ltt_loglevel_destroy(loglevel); cds_list_for_each_entry_safe(event, tmpevent, &session->events, list) _ltt_event_destroy(event); cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list) @@ -342,28 +393,56 @@ void _ltt_channel_destroy(struct ltt_channel *chan) chan->ops->channel_destroy(chan); } +int ltt_loglevel_create(struct ltt_channel *chan, + struct lttng_ust_event *event_param, + struct session_loglevel **_sl) +{ + struct session_loglevel *sl; + + sl = add_loglevel(event_param->name, chan, event_param); + if (!sl || IS_ERR(sl)) { + return PTR_ERR(sl); + } + *_sl = sl; + return 0; +} + +static +void _ltt_loglevel_destroy(struct session_loglevel *sl) +{ + _remove_loglevel(sl); +} + /* * Supports event creation while tracing session is active. */ -struct ltt_event *ltt_event_create(struct ltt_channel *chan, - struct lttng_ust_event *event_param, - void *filter) +int ltt_event_create(struct ltt_channel *chan, + struct lttng_ust_event *event_param, + void *filter, + struct ltt_event **_event) { struct ltt_event *event; - int ret; + int ret = 0; - if (chan->used_event_id == -1UL) + if (chan->used_event_id == -1UL) { + ret = -ENOMEM; goto full; + } /* * This is O(n^2) (for each event, the loop is called at event * creation). Might require a hash if we have lots of events. */ - cds_list_for_each_entry(event, &chan->session->events, list) - if (event->desc && !strcmp(event->desc->name, event_param->name)) + cds_list_for_each_entry(event, &chan->session->events, list) { + if (event->desc && !strcmp(event->desc->name, event_param->name)) { + ret = -EEXIST; goto exist; + } + } event = zmalloc(sizeof(struct ltt_event)); - if (!event) + if (!event) { + ret = -ENOMEM; goto cache_error; + } event->chan = chan; event->filter = filter; /* @@ -396,6 +475,9 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, goto add_pending_error; } break; + case LTTNG_UST_TRACEPOINT_LOGLEVEL: + assert(0); + break; default: WARN_ON_ONCE(1); } @@ -405,7 +487,8 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, goto statedump_error; } cds_list_add(&event->list, &chan->session->events); - return event; + *_event = event; + return 0; statedump_error: if (event->desc) { @@ -420,7 +503,7 @@ register_error: cache_error: exist: full: - return NULL; + return ret; } /*