X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-events.c;h=f77db60c512f7d3d1f7a5d6bdef970d307368a4e;hb=32ce85691c17b331072b1c0df96f69e8b388d134;hp=5e6c90cbd8383b2324e5cb73ed9db74395f993f9;hpb=1f49fc05ef59d2732d1f84423d0afda5fe4d4265;p=lttng-ust.git diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c index 5e6c90cb..f77db60c 100644 --- a/liblttng-ust/lttng-events.c +++ b/liblttng-ust/lttng-events.c @@ -45,6 +45,8 @@ #include #include +#include +#include #include "error.h" #include "compat.h" #include "lttng-ust-uuid.h" @@ -76,7 +78,6 @@ void ust_unlock(void) static CDS_LIST_HEAD(sessions); static void _lttng_event_destroy(struct lttng_event *event); -static void _lttng_channel_destroy(struct lttng_channel *chan); static int _lttng_event_unregister(struct lttng_event *event); static int _lttng_event_metadata_statedump(struct lttng_session *session, @@ -92,6 +93,20 @@ void lttng_session_sync_enablers(struct lttng_session *session); static void lttng_enabler_destroy(struct lttng_enabler *enabler); +/* + * Called with ust lock held. + */ +int lttng_session_active(void) +{ + struct lttng_session *iter; + + cds_list_for_each_entry(iter, &sessions, node) { + if (iter->active) + return 1; + } + return 0; +} + static int lttng_loglevel_match(int loglevel, unsigned int has_loglevel, @@ -127,7 +142,7 @@ void synchronize_trace(void) struct lttng_session *lttng_session_create(void) { struct lttng_session *session; - int ret; + int i; session = zmalloc(sizeof(struct lttng_session)); if (!session) @@ -135,14 +150,32 @@ struct lttng_session *lttng_session_create(void) CDS_INIT_LIST_HEAD(&session->chan_head); CDS_INIT_LIST_HEAD(&session->events_head); CDS_INIT_LIST_HEAD(&session->enablers_head); - ret = lttng_ust_uuid_generate(session->uuid); - if (ret != 0) { - session->uuid[0] = '\0'; - } + for (i = 0; i < LTTNG_UST_EVENT_HT_SIZE; i++) + CDS_INIT_HLIST_HEAD(&session->events_ht.table[i]); cds_list_add(&session->node, &sessions); return session; } +/* + * Only used internally at session destruction. + */ +static +void _lttng_channel_unmap(struct lttng_channel *lttng_chan) +{ + struct channel *chan; + struct lttng_ust_shm_handle *handle; + + cds_list_del(<tng_chan->node); + lttng_destroy_context(lttng_chan->ctx); + chan = lttng_chan->chan; + handle = lttng_chan->handle; + /* + * note: lttng_chan is private data contained within handle. It + * will be freed along with the handle. + */ + channel_destroy(chan, handle, 0); +} + void lttng_session_destroy(struct lttng_session *session) { struct lttng_channel *chan, *tmpchan; @@ -163,7 +196,7 @@ void lttng_session_destroy(struct lttng_session *session) &session->events_head, node) _lttng_event_destroy(event); cds_list_for_each_entry_safe(chan, tmpchan, &session->chan_head, node) - _lttng_channel_destroy(chan); + _lttng_channel_unmap(chan); cds_list_del(&session->node); free(session); } @@ -172,12 +205,17 @@ int lttng_session_enable(struct lttng_session *session) { int ret = 0; struct lttng_channel *chan; + int notify_socket; if (session->active) { ret = -EBUSY; goto end; } + notify_socket = lttng_get_notify_socket(session->owner); + if (notify_socket < 0) + return notify_socket; + /* We need to sync enablers with session before activation. */ lttng_session_sync_enablers(session); @@ -186,12 +224,27 @@ int lttng_session_enable(struct lttng_session *session) * we need to use. */ cds_list_for_each_entry(chan, &session->chan_head, node) { + const struct lttng_ctx *ctx; + const struct lttng_event_field *fields = NULL; + size_t nr_fields = 0; + + /* don't change it if session stop/restart */ if (chan->header_type) - continue; /* don't change it if session stop/restart */ - if (chan->free_event_id < 31) - chan->header_type = 1; /* compact */ - else - chan->header_type = 2; /* large */ + continue; + ctx = chan->ctx; + if (ctx) { + nr_fields = ctx->nr_fields; + fields = &ctx->fields->event_field; + } + ret = ustcomm_register_channel(notify_socket, + session->objd, + chan->objd, + nr_fields, + fields, + &chan->id, + &chan->header_type); + if (ret) + return ret; } CMM_ACCESS_ONCE(session->active) = 1; @@ -264,62 +317,6 @@ int lttng_event_disable(struct lttng_event *event) return 0; } -struct lttng_channel *lttng_channel_create(struct lttng_session *session, - const char *transport_name, - void *buf_addr, - size_t subbuf_size, size_t num_subbuf, - unsigned int switch_timer_interval, - unsigned int read_timer_interval, - int **shm_fd, int **wait_fd, - uint64_t **memory_map_size, - struct lttng_channel *chan_priv_init) -{ - struct lttng_channel *chan = NULL; - struct lttng_transport *transport; - - if (session->been_active) - goto active; /* Refuse to add channel to active session */ - transport = lttng_transport_find(transport_name); - if (!transport) { - DBG("LTTng transport %s not found\n", - transport_name); - goto notransport; - } - chan_priv_init->id = session->free_chan_id++; - chan_priv_init->session = session; - /* - * Note: the channel creation op already writes into the packet - * headers. Therefore the "chan" information used as input - * should be already accessible. - */ - chan = transport->ops.channel_create(transport_name, buf_addr, - subbuf_size, num_subbuf, switch_timer_interval, - read_timer_interval, shm_fd, wait_fd, - memory_map_size, chan_priv_init); - if (!chan) - goto create_error; - chan->enabled = 1; - chan->ops = &transport->ops; - cds_list_add(&chan->node, &session->chan_head); - return chan; - -create_error: -notransport: -active: - return NULL; -} - -/* - * Only used internally at session destruction. - */ -static -void _lttng_channel_destroy(struct lttng_channel *chan) -{ - cds_list_del(&chan->node); - lttng_destroy_context(chan->ctx); - chan->ops->channel_destroy(chan); -} - /* * Supports event creation while tracing session is active. */ @@ -329,17 +326,18 @@ int lttng_event_create(const struct lttng_event_desc *desc, { const char *event_name = desc->name; struct lttng_event *event; + struct lttng_session *session = chan->session; + struct cds_hlist_head *head; + struct cds_hlist_node *node; int ret = 0; - - if (chan->used_event_id == -1U) { - 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_head, node) { + size_t name_len = strlen(event_name); + uint32_t hash; + int notify_socket, loglevel; + const char *uri; + + hash = jhash(event_name, name_len, 0); + head = &chan->session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)]; + cds_hlist_for_each_entry(event, node, head, hlist) { assert(event->desc); if (!strncmp(event->desc->name, desc->name, @@ -349,6 +347,12 @@ int lttng_event_create(const struct lttng_event_desc *desc, } } + notify_socket = lttng_get_notify_socket(session->owner); + if (notify_socket < 0) { + ret = notify_socket; + goto socket_error; + } + /* * Check if loglevel match. Refuse to connect event if not. */ @@ -359,39 +363,59 @@ int lttng_event_create(const struct lttng_event_desc *desc, } event->chan = chan; - /* - * used_event_id counts the maximum number of event IDs that can - * register if all probes register. - */ - chan->used_event_id++; event->enabled = 1; CDS_INIT_LIST_HEAD(&event->bytecode_runtime_head); CDS_INIT_LIST_HEAD(&event->enablers_ref_head); event->desc = desc; + + if (desc->loglevel) + loglevel = *(*event->desc->loglevel); + else + loglevel = TRACE_DEFAULT; + if (desc->u.ext.model_emf_uri) + uri = *(desc->u.ext.model_emf_uri); + else + uri = NULL; + + /* Fetch event ID from sessiond */ + ret = ustcomm_register_event(notify_socket, + session->objd, + chan->objd, + event_name, + loglevel, + desc->signature, + desc->nr_fields, + desc->fields, + uri, + &event->id); + if (ret < 0) { + goto sessiond_register_error; + } /* Populate lttng_event structure before tracepoint registration. */ cmm_smp_wmb(); ret = __tracepoint_probe_register(event_name, desc->probe_callback, event, desc->signature); if (ret) - goto register_error; - event->id = chan->free_event_id++; + goto tracepoint_register_error; + ret = _lttng_event_metadata_statedump(chan->session, chan, event); if (ret) goto statedump_error; cds_list_add(&event->node, &chan->session->events_head); + cds_hlist_add_head(&event->hlist, head); return 0; statedump_error: WARN_ON_ONCE(__tracepoint_probe_unregister(event_name, desc->probe_callback, event)); - lttng_event_put(event->desc); -register_error: +tracepoint_register_error: +sessiond_register_error: free(event); cache_error: +socket_error: exist: -full: return ret; } @@ -499,17 +523,24 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler) cds_list_for_each_entry(probe_desc, probe_list, head) { for (i = 0; i < probe_desc->nr_events; i++) { int found = 0, ret; + struct cds_hlist_head *head; + struct cds_hlist_node *node; + const char *event_name; + size_t name_len; + uint32_t hash; desc = probe_desc->event_desc[i]; if (!lttng_desc_match_enabler(desc, enabler)) continue; + event_name = desc->name; + name_len = strlen(event_name); /* - * For each event in session event list, - * check if already created. + * Check if already created. */ - cds_list_for_each_entry(event, - &session->events_head, node) { + hash = jhash(event_name, name_len, 0); + head = &session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)]; + cds_hlist_for_each_entry(event, node, head, hlist) { if (event->desc == desc) found = 1; } @@ -523,8 +554,8 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler) ret = lttng_event_create(probe_desc->event_desc[i], enabler->chan); if (ret) { - DBG("Unable to create event %s\n", - probe_desc->event_desc[i]->name); + DBG("Unable to create event %s, error %d\n", + probe_desc->event_desc[i]->name, ret); } } } @@ -610,7 +641,6 @@ void _lttng_event_destroy(struct lttng_event *event) { 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); @@ -1078,7 +1108,7 @@ uint64_t measure_clock_offset(void) static int _lttng_session_metadata_statedump(struct lttng_session *session) { - unsigned char *uuid_c = session->uuid; + unsigned char *uuid_c; char uuid_s[LTTNG_UST_UUID_STR_LEN], clock_uuid_s[LTTNG_UST_UUID_STR_LEN]; struct lttng_channel *chan; @@ -1095,6 +1125,7 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n"); return -EPERM; } + uuid_c = session->metadata->uuid; snprintf(uuid_s, sizeof(uuid_s), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", @@ -1425,16 +1456,3 @@ void lttng_session_lazy_sync_enablers(struct lttng_session *session) return; lttng_session_sync_enablers(session); } - -/* - * Take the TLS "fault" in libuuid if dlopen'd, which can take the - * dynamic linker mutex, outside of the UST lock, since the UST lock is - * taken in constructors, which are called with dynamic linker mutex - * held. - */ -void lttng_fixup_event_tls(void) -{ - unsigned char uuid[LTTNG_UST_UUID_STR_LEN]; - - (void) lttng_ust_uuid_generate(uuid); -}