X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Ftrace-ust.c;h=b1066072bf711bbffff2bf87a98bab3b1c359d48;hp=a9aa1abceb8cf3779ec7e02ab4f96eb9dc7613f3;hb=f6a9efaa0fe496b7fa4850daa2eae98a240433e1;hpb=0177d773712c6d6b11e395708ae2cc686d6917a4 diff --git a/ltt-sessiond/trace-ust.c b/ltt-sessiond/trace-ust.c index a9aa1abce..b1066072b 100644 --- a/ltt-sessiond/trace-ust.c +++ b/ltt-sessiond/trace-ust.c @@ -24,70 +24,55 @@ #include #include +#include "hashtable.h" #include "trace-ust.h" /* - * Return an UST session by traceable app PID. + * Find the channel in the hashtable. */ -struct ltt_ust_session *trace_ust_get_session_by_pid(pid_t pid, - struct ltt_ust_session_list *session_list) +struct ltt_ust_channel *trace_ust_find_channel_by_name(struct cds_lfht *ht, + char *name) { - struct ltt_ust_session *lus; - - cds_list_for_each_entry(lus, &session_list->head, list) { - if (lus->app->pid == pid) { - DBG("Found UST session by pid %d", pid); - return lus; - } - } - - return NULL; -} - -/* - * Find the channel name for the given ust session. - */ -struct ltt_ust_channel *trace_ust_get_channel_by_name( - char *name, struct ltt_ust_session *session) -{ - struct ltt_ust_channel *chan; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - if (session == NULL) { - ERR("Undefine session"); + rcu_read_lock(); + node = hashtable_lookup(ht, (void *) name, strlen(name), &iter); + if (node == NULL) { + rcu_read_unlock(); goto error; } + rcu_read_unlock(); - cds_list_for_each_entry(chan, &session->channels.head, list) { - if (strcmp(name, chan->name) == 0) { - DBG("Found UST channel by name %s", name); - return chan; - } - } + DBG2("Trace UST channel %s found by name", name); + + return caa_container_of(node, struct ltt_ust_channel, node); error: + DBG2("Trace UST channel %s not found by name", name); return NULL; } /* - * Find the event name for the given channel. + * Find the event in the hashtable. */ -struct ltt_ust_event *trace_ust_get_event_by_name( - char *name, struct ltt_ust_channel *channel) +struct ltt_ust_event *trace_ust_find_event_by_name(struct cds_lfht *ht, + char *name) { - struct ltt_ust_event *ev; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - if (channel == NULL) { - ERR("Undefine channel"); + rcu_read_lock(); + node = hashtable_lookup(ht, (void *) name, strlen(name), &iter); + if (node == NULL) { + rcu_read_unlock(); goto error; } + rcu_read_unlock(); - cds_list_for_each_entry(ev, &channel->events.head, list) { - if (strcmp(name, ev->event->name) == 0) { - DBG("Found UST event by name %s for channel %s", name, - channel->name); - return ev; - } - } + DBG2("Found UST event by name %s", name); + + return caa_container_of(node, struct ltt_ust_event, node); error: return NULL; @@ -98,7 +83,8 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid) +struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, + struct lttng_domain *domain) { int ret; struct ltt_ust_session *lus; @@ -113,20 +99,25 @@ struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid) /* Init data structure */ lus->handle = -1; lus->enabled = 1; - lus->uconsumer_fds_sent = 0; - lus->path = NULL; + lus->consumer_fds_sent = 0; lus->metadata = NULL; - lus->app = NULL; /* TODO: Search app by PID */ - lus->channels.count = 0; - CDS_INIT_LIST_HEAD(&lus->channels.head); + + /* Alloc UST domain hash tables */ + lus->domain_pid = hashtable_new(0); + lus->domain_exec = hashtable_new_str(0); + + /* Alloc UST global domain channels' HT */ + lus->domain_global.channels = hashtable_new_str(0); /* Set session path */ - ret = asprintf(&lus->path, "%s/ust_%d", path, pid); + ret = snprintf(lus->path, PATH_MAX, "%s/ust_%d", path, pid); if (ret < 0) { - perror("asprintf kernel traces path"); + PERROR("snprintf kernel traces path"); goto error; } + DBG2("UST trace session create successful"); + return lus; error: @@ -138,8 +129,8 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path, - struct lttng_ust_channel *chan) +struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, + char *path) { int ret; struct ltt_ust_channel *luc; @@ -150,29 +141,38 @@ struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path, goto error; } - luc->attr = malloc(sizeof(struct lttng_ust_channel)); - if (luc->attr == NULL) { - perror("lttng_ust_channel malloc"); - goto error; + /* Copy UST channel attributes */ + memcpy(&luc->attr, &chan->attr, sizeof(struct lttng_ust_channel)); + + /* Translate to UST output enum */ + switch (luc->attr.output) { + default: + luc->attr.output = LTTNG_UST_MMAP; + break; } - memcpy(luc->attr, chan, sizeof(struct lttng_ust_channel)); luc->handle = -1; luc->enabled = 1; - luc->ctx = NULL; - luc->events.count = 0; - CDS_INIT_LIST_HEAD(&luc->events.head); /* Copy channel name */ - strncpy(luc->name, name, LTTNG_UST_SYM_NAME_LEN); + strncpy(luc->name, chan->name, sizeof(&luc->name)); luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + /* Init node */ + hashtable_node_init(&luc->node, (void *) luc->name, strlen(luc->name)); + /* Alloc hash tables */ + luc->events = hashtable_new_str(0); + luc->ctx = hashtable_new_str(0); + /* Set trace output path */ - ret = asprintf(&luc->trace_path, "%s", path); + ret = snprintf(luc->trace_path, PATH_MAX, "%s", path); if (ret < 0) { perror("asprintf ust create channel"); goto error; } + CDS_INIT_LIST_HEAD(&luc->stream_list.head); + + DBG2("Trace UST channel %s created", luc->name); return luc; @@ -188,27 +188,25 @@ error: struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) { struct ltt_ust_event *lue; - struct lttng_ust_event *event; lue = malloc(sizeof(struct ltt_ust_event)); - event = malloc(sizeof(struct lttng_ust_event)); - if (lue == NULL || event == NULL) { - perror("ust event malloc"); + if (lue == NULL) { + PERROR("ust event malloc"); goto error; } switch (ev->type) { case LTTNG_EVENT_PROBE: - event->instrumentation = LTTNG_UST_PROBE; + lue->attr.instrumentation = LTTNG_UST_PROBE; break; case LTTNG_EVENT_FUNCTION: - event->instrumentation = LTTNG_UST_FUNCTION; + lue->attr.instrumentation = LTTNG_UST_FUNCTION; break; case LTTNG_EVENT_FUNCTION_ENTRY: - event->instrumentation = LTTNG_UST_FUNCTION; + lue->attr.instrumentation = LTTNG_UST_FUNCTION; break; case LTTNG_EVENT_TRACEPOINT: - event->instrumentation = LTTNG_UST_TRACEPOINT; + lue->attr.instrumentation = LTTNG_UST_TRACEPOINT; break; default: ERR("Unknown ust instrumentation type (%d)", ev->type); @@ -216,14 +214,18 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) } /* Copy event name */ - strncpy(event->name, ev->name, LTTNG_UST_SYM_NAME_LEN); - event->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); + lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; /* Setting up a ust event */ lue->handle = -1; - lue->event = event; lue->enabled = 1; - lue->ctx = NULL; + + /* Init node */ + hashtable_node_init(&lue->node, (void *) lue->attr.name, + strlen(lue->attr.name)); + /* Alloc context hash tables */ + lue->ctx = hashtable_new_str(5); return lue; @@ -240,27 +242,24 @@ struct ltt_ust_metadata *trace_ust_create_metadata(char *path) { int ret; struct ltt_ust_metadata *lum; - struct lttng_ust_channel *attr; lum = malloc(sizeof(struct ltt_ust_metadata)); - attr = malloc(sizeof(struct lttng_ust_channel)); - if (lum == NULL || attr == NULL) { + if (lum == NULL) { perror("ust metadata malloc"); goto error; } /* Set default attributes */ - attr->overwrite = DEFAULT_CHANNEL_OVERWRITE; - attr->subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE; - attr->num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; - attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; - attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; - attr->output = DEFAULT_UST_CHANNEL_OUTPUT; - - lum->attr = attr; + lum->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; + lum->attr.subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE; + lum->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; + lum->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; + lum->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + lum->attr.output = DEFAULT_UST_CHANNEL_OUTPUT; + lum->handle = -1; /* Set metadata trace path */ - ret = asprintf(&lum->trace_path, "%s/metadata", path); + ret = snprintf(lum->pathname, PATH_MAX, "%s/metadata", path); if (ret < 0) { perror("asprintf ust metadata"); goto error; @@ -272,20 +271,59 @@ error: return NULL; } +/* + * RCU safe free context structure. + */ +static void destroy_context_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_context *ctx = + caa_container_of(node, struct ltt_ust_context, node); + + free(ctx); +} + +/* + * Cleanup UST context hash table. + */ +static void destroy_context(struct cds_lfht *ht) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht, &iter); + if (!ret) { + call_rcu(&node->head, destroy_context_rcu); + } + hashtable_get_next(ht, &iter); + } +} + /* * Cleanup ust event structure. */ void trace_ust_destroy_event(struct ltt_ust_event *event) { - DBG("[trace] Destroy ust event %s", event->event->name); + DBG2("Trace destroy UST event %s", event->attr.name); + destroy_context(event->ctx); + free(event); +} - /* Free attributes */ - free(event->event); - free(event->ctx); +/* + * URCU intermediate call to complete destroy event. + */ +static void destroy_event_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_event *event = + caa_container_of(node, struct ltt_ust_event, node); - /* Remove from event list */ - cds_list_del(&event->list); - free(event); + trace_ust_destroy_event(event); } /* @@ -293,23 +331,41 @@ void trace_ust_destroy_event(struct ltt_ust_event *event) */ void trace_ust_destroy_channel(struct ltt_ust_channel *channel) { - struct ltt_ust_event *event, *etmp; + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - DBG("[trace] Destroy ust channel %d", channel->handle); + DBG2("Trace destroy UST channel %s", channel->name); - free(channel->trace_path); - /* Free attributes structure */ - free(channel->attr); - free(channel->ctx); + rcu_read_lock(); - /* For each event in the channel list */ - cds_list_for_each_entry_safe(event, etmp, &channel->events.head, list) { - trace_ust_destroy_event(event); + hashtable_get_first(channel->events, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(channel->events, &iter); + if (!ret) { + call_rcu(&node->head, destroy_event_rcu); + } + hashtable_get_next(channel->events, &iter); } - /* Remove from channel list */ - cds_list_del(&channel->list); + free(channel->events); + destroy_context(channel->ctx); free(channel); + + rcu_read_unlock(); +} + +/* + * URCU intermediate call to complete destroy channel. + */ +static void destroy_channel_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_channel *channel = + caa_container_of(node, struct ltt_ust_channel, node); + + trace_ust_destroy_channel(channel); } /* @@ -317,37 +373,104 @@ void trace_ust_destroy_channel(struct ltt_ust_channel *channel) */ void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata) { - DBG("[trace] Destroy ust metadata %d", metadata->handle); - - /* Free attributes */ - free(metadata->attr); - free(metadata->trace_path); + DBG2("Trace UST destroy metadata %d", metadata->handle); free(metadata); } /* - * Cleanup ust session structure + * Iterate over a hash table containing channels and cleanup safely. */ -void trace_ust_destroy_session(struct ltt_ust_session *session) +static void destroy_channels(struct cds_lfht *channels) { - struct ltt_ust_channel *channel, *ctmp; + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + hashtable_get_first(channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(channels, &iter); + if (!ret) { + call_rcu(&node->head, destroy_channel_rcu); + } + hashtable_get_next(channels, &iter); + } +} - DBG("[trace] Destroy ust session %d", session->handle); +/* + * Cleanup UST pid domain. + */ +static void destroy_domain_pid(struct cds_lfht *ht) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + struct ltt_ust_domain_pid *d; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht , &iter); + if (!ret) { + d = caa_container_of(node, struct ltt_ust_domain_pid, node); + destroy_channels(d->channels); + } + hashtable_get_next(ht, &iter); + } +} + +/* + * Cleanup UST exec name domain. + */ +static void destroy_domain_exec(struct cds_lfht *ht) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + struct ltt_ust_domain_exec *d; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht , &iter); + if (!ret) { + d = caa_container_of(node, struct ltt_ust_domain_exec, node); + destroy_channels(d->channels); + } + hashtable_get_next(ht, &iter); + } +} +/* + * Cleanup UST global domain. + */ +static void destroy_domain_global(struct ltt_ust_domain_global *dom) +{ + destroy_channels(dom->channels); +} + +/* + * Cleanup ust session structure + */ +void trace_ust_destroy_session(struct ltt_ust_session *session) +{ /* Extra safety */ if (session == NULL) { return; } + rcu_read_lock(); + + DBG2("Trace UST destroy session %d", session->handle); + if (session->metadata != NULL) { trace_ust_destroy_metadata(session->metadata); } - cds_list_for_each_entry_safe(channel, ctmp, &session->channels.head, list) { - trace_ust_destroy_channel(channel); - } + /* Cleaning up UST domain */ + destroy_domain_global(&session->domain_global); + destroy_domain_pid(session->domain_pid); + destroy_domain_exec(session->domain_exec); - free(session->path); free(session); + + rcu_read_unlock(); }