X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ftrace-ust.c;h=3881084f04fb4024b14970120e44e85c02b1d59d;hp=1f6fd52736abe4f8abde125fdc092601d491ec46;hb=b93a4a13a2724a73069e1d661df5df83c629bb36;hpb=1e199c04cd2f0b9c378d89a11e42c516d5f8d90e diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 1f6fd5273..3881084f0 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -28,6 +29,8 @@ #include "buffer-registry.h" #include "trace-ust.h" #include "utils.h" +#include "ust-app.h" +#include "agent.h" /* * Match function for the events hash table lookup. @@ -202,6 +205,9 @@ error: /* * Lookup an agent in the session agents hash table by domain type and return * the object if found else NULL. + * + * RCU read side lock must be acquired before calling and only released + * once the agent is no longer in scope or being used. */ struct agent *trace_ust_find_agent(struct ltt_ust_session *session, enum lttng_domain_type domain_type) @@ -362,6 +368,7 @@ error: /* * Allocate and initialize a ust event. Set name and event type. + * We own filter_expression, filter, and exclusion. * * Return pointer to structure or NULL. */ @@ -437,6 +444,9 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev, error_free_event: free(lue); error: + free(filter_expression); + free(filter); + free(exclusion); return NULL; } @@ -462,7 +472,12 @@ int trace_ust_context_type_event_to_ust(enum lttng_event_context_type type) utype = LTTNG_UST_CONTEXT_IP; break; case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER: - utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER; + if (!ustctl_has_perf_counters()) { + utype = -1; + WARN("Perf counters not implemented in UST"); + } else { + utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER; + } break; default: ERR("Invalid UST context"); @@ -554,6 +569,290 @@ error: return NULL; } +static +void destroy_pid_tracker_node_rcu(struct rcu_head *head) +{ + struct ust_pid_tracker_node *tracker_node = + caa_container_of(head, struct ust_pid_tracker_node, node.head); + free(tracker_node); +} + +static +void destroy_pid_tracker_node(struct ust_pid_tracker_node *tracker_node) +{ + + call_rcu(&tracker_node->node.head, destroy_pid_tracker_node_rcu); +} + +static +int init_pid_tracker(struct ust_pid_tracker *pid_tracker) +{ + int ret = 0; + + pid_tracker->ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + if (!pid_tracker->ht) { + ret = -1; + goto end; + } + +end: + return ret; +} + +/* + * Teardown pid tracker content, but don't free pid_tracker object. + */ +static +void fini_pid_tracker(struct ust_pid_tracker *pid_tracker) +{ + struct ust_pid_tracker_node *tracker_node; + struct lttng_ht_iter iter; + + if (!pid_tracker->ht) { + return; + } + rcu_read_lock(); + cds_lfht_for_each_entry(pid_tracker->ht->ht, + &iter.iter, tracker_node, node.node) { + int ret = lttng_ht_del(pid_tracker->ht, &iter); + + assert(!ret); + destroy_pid_tracker_node(tracker_node); + } + rcu_read_unlock(); + ht_cleanup_push(pid_tracker->ht); + pid_tracker->ht = NULL; +} + +static +struct ust_pid_tracker_node *pid_tracker_lookup( + struct ust_pid_tracker *pid_tracker, int pid, + struct lttng_ht_iter *iter) +{ + unsigned long _pid = (unsigned long) pid; + struct lttng_ht_node_ulong *node; + + lttng_ht_lookup(pid_tracker->ht, (void *) _pid, iter); + node = lttng_ht_iter_get_node_ulong(iter); + if (node) { + return caa_container_of(node, struct ust_pid_tracker_node, + node); + } else { + return NULL; + } +} + +static +int pid_tracker_add_pid(struct ust_pid_tracker *pid_tracker, int pid) +{ + int retval = LTTNG_OK; + struct ust_pid_tracker_node *tracker_node; + struct lttng_ht_iter iter; + + if (pid < 0) { + retval = LTTNG_ERR_INVALID; + goto end; + } + tracker_node = pid_tracker_lookup(pid_tracker, pid, &iter); + if (tracker_node) { + /* Already exists. */ + retval = LTTNG_ERR_PID_TRACKED; + goto end; + } + tracker_node = zmalloc(sizeof(*tracker_node)); + if (!tracker_node) { + retval = LTTNG_ERR_NOMEM; + goto end; + } + lttng_ht_node_init_ulong(&tracker_node->node, (unsigned long) pid); + lttng_ht_add_unique_ulong(pid_tracker->ht, &tracker_node->node); +end: + return retval; +} + +static +int pid_tracker_del_pid(struct ust_pid_tracker *pid_tracker, int pid) +{ + int retval = LTTNG_OK, ret; + struct ust_pid_tracker_node *tracker_node; + struct lttng_ht_iter iter; + + if (pid < 0) { + retval = LTTNG_ERR_INVALID; + goto end; + } + tracker_node = pid_tracker_lookup(pid_tracker, pid, &iter); + if (!tracker_node) { + /* Not found */ + retval = LTTNG_ERR_PID_NOT_TRACKED; + goto end; + } + ret = lttng_ht_del(pid_tracker->ht, &iter); + assert(!ret); + + destroy_pid_tracker_node(tracker_node); +end: + return retval; +} + +/* + * The session lock is held when calling this function. + */ +int trace_ust_pid_tracker_lookup(struct ltt_ust_session *session, int pid) +{ + struct lttng_ht_iter iter; + + if (!session->pid_tracker.ht) { + return 1; + } + if (pid_tracker_lookup(&session->pid_tracker, pid, &iter)) { + return 1; + } + return 0; +} + +/* + * Called with the session lock held. + */ +int trace_ust_track_pid(struct ltt_ust_session *session, int pid) +{ + int retval = LTTNG_OK; + + if (pid == -1) { + /* Track all pids: destroy tracker if exists. */ + if (session->pid_tracker.ht) { + fini_pid_tracker(&session->pid_tracker); + /* Ensure all apps have session. */ + ust_app_global_update_all(session); + } + } else { + int ret; + + if (!session->pid_tracker.ht) { + /* Create tracker. */ + if (init_pid_tracker(&session->pid_tracker)) { + ERR("Error initializing PID tracker"); + retval = LTTNG_ERR_NOMEM; + goto end; + } + ret = pid_tracker_add_pid(&session->pid_tracker, pid); + if (ret != LTTNG_OK) { + retval = ret; + fini_pid_tracker(&session->pid_tracker); + goto end; + } + /* Remove all apps from session except pid. */ + ust_app_global_update_all(session); + } else { + struct ust_app *app; + + ret = pid_tracker_add_pid(&session->pid_tracker, pid); + if (ret != LTTNG_OK) { + retval = ret; + goto end; + } + /* Add session to application */ + app = ust_app_find_by_pid(pid); + if (app) { + ust_app_global_update(session, app); + } + } + } +end: + return retval; +} + +/* + * Called with the session lock held. + */ +int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid) +{ + int retval = LTTNG_OK; + + if (pid == -1) { + /* Create empty tracker, replace old tracker. */ + struct ust_pid_tracker tmp_tracker; + + tmp_tracker = session->pid_tracker; + if (init_pid_tracker(&session->pid_tracker)) { + ERR("Error initializing PID tracker"); + retval = LTTNG_ERR_NOMEM; + /* Rollback operation. */ + session->pid_tracker = tmp_tracker; + goto end; + } + fini_pid_tracker(&tmp_tracker); + + /* Remove session from all applications */ + ust_app_global_update_all(session); + } else { + int ret; + struct ust_app *app; + + if (!session->pid_tracker.ht) { + retval = LTTNG_ERR_INVALID; + goto end; + } + /* Remove PID from tracker */ + ret = pid_tracker_del_pid(&session->pid_tracker, pid); + if (ret != LTTNG_OK) { + retval = ret; + goto end; + } + /* Remove session from application. */ + app = ust_app_find_by_pid(pid); + if (app) { + ust_app_global_update(session, app); + } + } +end: + return retval; +} + +/* + * Called with session lock held. + */ +ssize_t trace_ust_list_tracker_pids(struct ltt_ust_session *session, + int32_t **_pids) +{ + struct ust_pid_tracker_node *tracker_node; + struct lttng_ht_iter iter; + unsigned long count, i = 0; + long approx[2]; + int32_t *pids; + int ret = 0; + + if (!session->pid_tracker.ht) { + /* Tracker disabled. Set first entry to -1. */ + pids = zmalloc(sizeof(*pids)); + if (!pids) { + ret = -1; + goto end; + } + pids[0] = -1; + *_pids = pids; + return 1; + } + + rcu_read_lock(); + cds_lfht_count_nodes(session->pid_tracker.ht->ht, + &approx[0], &count, &approx[1]); + pids = zmalloc(sizeof(*pids) * count); + if (!pids) { + ret = -1; + goto end; + } + cds_lfht_for_each_entry(session->pid_tracker.ht->ht, + &iter.iter, tracker_node, node.node) { + pids[i++] = tracker_node->node.key; + } + *_pids = pids; + ret = count; +end: + rcu_read_unlock(); + return ret; +} + /* * RCU safe free context structure. */ @@ -749,10 +1048,16 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) /* Cleaning up UST domain */ destroy_domain_global(&session->domain_global); + rcu_read_lock(); cds_lfht_for_each_entry(session->agents->ht, &iter.iter, agt, node.node) { - lttng_ht_del(session->agents, &iter); + int ret = lttng_ht_del(session->agents, &iter); + + assert(!ret); agent_destroy(agt); } + rcu_read_unlock(); + + ht_cleanup_push(session->agents); /* Cleanup UID buffer registry object(s). */ cds_list_for_each_entry_safe(reg, sreg, &session->buffer_reg_uid_list, @@ -765,5 +1070,7 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) consumer_destroy_output(session->consumer); consumer_destroy_output(session->tmp_consumer); + fini_pid_tracker(&session->pid_tracker); + free(session); }