#include <usterr-signal-safe.h>
#include <helper.h>
+#include <ust-ctl.h>
+#include <ust-comm.h>
#include "error.h"
#include "compat.h"
#include "lttng-ust-uuid.h"
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,
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,
struct lttng_session *lttng_session_create(void)
{
struct lttng_session *session;
- int ret;
+ int i;
session = zmalloc(sizeof(struct lttng_session));
if (!session)
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;
&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);
}
{
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);
* 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;
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.
*/
{
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,
}
}
+ 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.
*/
}
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;
}
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;
}
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);
}
}
}
{
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);
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;
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",
cds_list_for_each_entry(event, &session->events_head, node) {
struct lttng_enabler_ref *enabler_ref;
struct lttng_bytecode_runtime *runtime;
- int enabled = 0;
+ int enabled = 0, has_enablers_without_bytecode = 0;
/* Enable events */
cds_list_for_each_entry(enabler_ref,
}
event->enabled = enabled;
+ /* Check if has enablers without bytecode enabled */
+ cds_list_for_each_entry(enabler_ref,
+ &event->enablers_ref_head, node) {
+ if (enabler_ref->ref->enabled
+ && cds_list_empty(&enabler_ref->ref->filter_bytecode_head)) {
+ has_enablers_without_bytecode = 1;
+ break;
+ }
+ }
+ event->has_enablers_without_bytecode =
+ has_enablers_without_bytecode;
+
/* Enable filters */
cds_list_for_each_entry(runtime,
&event->bytecode_runtime_head, node) {
lttng_filter_sync_state(runtime);
}
-
}
}
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);
-}