* control side.
*/
LTTNG_ASSERT(cds_list_empty(&trace->stream_list));
+ ASSERT_RCU_READ_LOCKED();
+
session_put(trace->session);
trace->session = NULL;
free(trace->path);
}
/*
- * Should be called with RCU read-side lock held.
+ * The caller must either:
+ * - hold the RCU read side lock, or
+ * - guarantee the existence of the object by already holding a reference to
+ * the object.
*/
bool ctf_trace_get(struct ctf_trace *trace)
{
- return urcu_ref_get_unless_zero(&trace->ref);
+ const bool ref = urcu_ref_get_unless_zero(&trace->ref);
+
+ if (!ref) {
+ /*
+ * The ref count is already zero. It means the object is being
+ * torn down concurently.
+ * This is only acceptable if we hold the RCU read-side lock,
+ * else it's a logic error.
+ */
+ ASSERT_RCU_READ_LOCKED();
+ }
+
+ return ref;
}
/*
struct cds_lfht_node *node_ptr;
struct relay_index *_index;
+ ASSERT_RCU_READ_LOCKED();
+
DBG2("Adding relay index with stream id %" PRIu64 " and seqnum %" PRIu64,
stream->stream_handle, index->index_n.key);
*/
static bool relay_index_get(struct relay_index *index)
{
+ ASSERT_RCU_READ_LOCKED();
+
DBG2("index get for stream id %" PRIu64 " and seqnum %" PRIu64 " refcount %d",
index->stream->stream_handle, index->index_n.key,
(int) index->ref.refcount);
/* Should be called with RCU read-side lock held. */
bool stream_get(struct relay_stream *stream)
{
+ ASSERT_RCU_READ_LOCKED();
+
return urcu_ref_get_unless_zero(&stream->ref);
}
bool signal = false;
LTTNG_ASSERT(trigger);
+ ASSERT_RCU_READ_LOCKED();
pthread_mutex_lock(&executor->work.lock);
/* Check for queue overflow. */
struct agent_app *app;
LTTNG_ASSERT(sock >= 0);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(the_agent_apps_ht_by_sock,
(void *) ((unsigned long) sock), &iter);
struct lttng_ht_iter iter;
LTTNG_ASSERT(app);
+ ASSERT_RCU_READ_LOCKED();
DBG3("Agent deleting app pid: %d and sock: %d", app->pid, app->sock->fd);
LTTNG_ASSERT(agt);
LTTNG_ASSERT(agt->events);
LTTNG_ASSERT(iter);
+ ASSERT_RCU_READ_LOCKED();
ht = agt->events;
key.name = name;
LTTNG_ASSERT(agt);
LTTNG_ASSERT(agt->events);
+ ASSERT_RCU_READ_LOCKED();
condition = lttng_trigger_get_const_condition(trigger);
{
struct agent_ht_key key;
+ ASSERT_RCU_READ_LOCKED();
+
key.name = name;
cds_lfht_next_duplicate(agt->events->ht, ht_match_event_by_name,
LTTNG_ASSERT(name);
LTTNG_ASSERT(agt);
LTTNG_ASSERT(agt->events);
+ ASSERT_RCU_READ_LOCKED();
ht = agt->events;
key.name = name;
struct buffer_reg_uid *reg = NULL, key;
struct lttng_ht *ht = buffer_registry_uid;
+ ASSERT_RCU_READ_LOCKED();
+
/* Setup key we are looking for. */
key.session_id = session_id;
key.bits_per_long = bits_per_long;
lttcomm_sessiond_command_str((lttcomm_sessiond_command) cmd_ctx->lsm.cmd_type),
cmd_ctx->lsm.cmd_type);
- LTTNG_ASSERT(!rcu_read_ongoing());
-
*sock_error = 0;
switch (cmd_ctx->lsm.cmd_type) {
int consumer_fd;
struct consumer_socket *socket = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
switch (bits) {
case 64:
consumer_fd = uatomic_read(&the_ust_consumerd64_fd);
struct lttng_ht_node_ulong *node;
struct consumer_socket *socket = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
/* Negative keys are lookup failures */
if (key < 0 || consumer == NULL) {
return NULL;
{
LTTNG_ASSERT(sock);
LTTNG_ASSERT(consumer);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_add_unique_ulong(consumer->socks, &sock->node);
}
LTTNG_ASSERT(sock);
LTTNG_ASSERT(consumer);
+ ASSERT_RCU_READ_LOCKED();
iter.iter.node = &sock->node.node;
ret = lttng_ht_del(consumer->socks, &iter);
}
/*
- * Destroy and free socket pointer in a call RCU. Read side lock must be
- * acquired before calling this function.
+ * Destroy and free socket pointer in a call RCU. The call must either:
+ * - have acquired the read side lock before calling this function, or
+ * - guarantee the validity of the `struct consumer_socket` object for the
+ * duration of the call.
*/
void consumer_destroy_socket(struct consumer_socket *sock)
{
struct lttcomm_consumer_msg msg;
LTTNG_ASSERT(socket);
+ ASSERT_RCU_READ_LOCKED();
DBG2("Consumer push metadata to consumer socket %d", *socket->fd_ptr);
struct lttng_ht_iter iter;
struct syscall *ksyscall;
+ ASSERT_RCU_READ_LOCKED();
+
DBG3("Destroying syscall hash table.");
if (!ht) {
struct cds_lfht_node *node;
struct notification_client *client = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
cds_lfht_lookup(state->client_socket_ht,
hash_client_socket(socket),
match_client_socket,
struct cds_lfht_node *node;
struct notification_client *client = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
cds_lfht_lookup(state->client_id_ht,
hash_client_id(id),
match_client_id,
struct cds_lfht_node *node;
struct cds_lfht_iter iter;
+ ASSERT_RCU_READ_LOCKED();
+
cds_lfht_lookup(state->session_triggers_ht,
hash_key_str(session_name, lttng_ht_seed),
match_session_trigger_list,
const char *session_name;
struct lttng_session_trigger_list *trigger_list;
+ ASSERT_RCU_READ_LOCKED();
+
condition = lttng_trigger_get_const_condition(trigger);
switch (lttng_condition_get_type(condition)) {
case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
struct cds_lfht_iter iter;
struct channel_info *channel;
+ ASSERT_RCU_READ_LOCKED();
+
cds_lfht_for_each_entry(state->channels_ht, &iter, channel,
channels_ht_node) {
struct lttng_trigger_list_element *trigger_list_element;
int ret;
struct lttng_condition_list_element *condition_list_element, *tmp;
+ ASSERT_RCU_READ_LOCKED();
+
/* Acquire the client lock to disable its communication atomically. */
pthread_mutex_lock(&client->lock);
client->communication.active = false;
struct lttng_ht_iter iter;
struct ltt_session *ls;
+ ASSERT_RCU_READ_LOCKED();
ASSERT_LOCKED(ltt_session_list.lock);
if (!ltt_sessions_ht_by_id) {
LTTNG_ASSERT(snapshot);
LTTNG_ASSERT(name);
+ ASSERT_RCU_READ_LOCKED();
cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
node.node) {
struct snapshot_output *output = NULL;
LTTNG_ASSERT(snapshot);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(snapshot->output_ht, (void *)((unsigned long) id), &iter);
node = lttng_ht_iter_get_node_ulong(&iter);
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
+ ASSERT_RCU_READ_LOCKED();
/*
* If we receive an empty string for channel name, it means the
* default channel name is requested.
LTTNG_ASSERT(name);
LTTNG_ASSERT(ht);
+ ASSERT_RCU_READ_LOCKED();
key.name = name;
key.filter = filter;
int ret;
LTTNG_ASSERT(ua_ctx);
+ ASSERT_RCU_READ_LOCKED();
if (ua_ctx->obj) {
pthread_mutex_lock(&app->sock_lock);
int ret;
LTTNG_ASSERT(ua_event);
+ ASSERT_RCU_READ_LOCKED();
free(ua_event->filter);
if (ua_event->exclusion != NULL)
struct ust_app *app)
{
LTTNG_ASSERT(stream);
+ ASSERT_RCU_READ_LOCKED();
(void) release_ust_app_stream(sock, stream, app);
free(stream);
struct ust_registry_session *registry;
LTTNG_ASSERT(ua_chan);
+ ASSERT_RCU_READ_LOCKED();
DBG3("UST app deleting channel %s", ua_chan->name);
LTTNG_ASSERT(registry);
LTTNG_ASSERT(socket);
+ ASSERT_RCU_READ_LOCKED();
metadata_key = registry->metadata_key;
LTTNG_ASSERT(registry);
LTTNG_ASSERT(consumer);
+ ASSERT_RCU_READ_LOCKED();
pthread_mutex_lock(®istry->lock);
if (registry->metadata_closed) {
struct ust_registry_session *registry;
LTTNG_ASSERT(ua_sess);
+ ASSERT_RCU_READ_LOCKED();
pthread_mutex_lock(&ua_sess->lock);
struct lttng_ht_node_ulong *node;
struct lttng_ht_iter iter;
+ ASSERT_RCU_READ_LOCKED();
+
lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &iter);
node = lttng_ht_iter_get_node_ulong(&iter);
if (node == NULL) {
struct lttng_ht_node_ulong *node;
struct lttng_ht_iter iter;
+ ASSERT_RCU_READ_LOCKED();
+
lttng_ht_lookup(ust_app_ht_by_notify_sock, (void *)((unsigned long) sock),
&iter);
node = lttng_ht_iter_get_node_ulong(&iter);
struct ust_app_event_notifier_rule *event_notifier_rule = NULL;
LTTNG_ASSERT(ht);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(ht, &token, &iter);
node = lttng_ht_iter_get_node_u64(&iter);
LTTNG_ASSERT(uctx);
LTTNG_ASSERT(ht);
+ ASSERT_RCU_READ_LOCKED();
/* Lookup using the lttng_ust_context_type and a custom match fct. */
cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed),
int ret = 0;
struct ust_app_ctx *ua_ctx;
+ ASSERT_RCU_READ_LOCKED();
+
DBG2("UST app adding context to channel %s", ua_chan->name);
ua_ctx = find_ust_app_context(ua_chan->ctx, uctx);
struct lttng_ht_node_str *ua_chan_node;
struct ust_app_channel *ua_chan;
+ ASSERT_RCU_READ_LOCKED();
+
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
ua_chan_node = lttng_ht_iter_get_node_str(&iter);
if (ua_chan_node == NULL) {
LTTNG_ASSERT(usess);
LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(ua_chan);
+ ASSERT_RCU_READ_LOCKED();
DBG("UST app creating channel %s with per UID buffers", ua_chan->name);
LTTNG_ASSERT(usess->active);
LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(ua_chan);
+ ASSERT_RCU_READ_LOCKED();
/* Handle buffer type before sending the channel to the application. */
switch (usess->buffer_type) {
struct lttng_ht_node_str *ua_chan_node;
struct ust_app_channel *ua_chan;
+ ASSERT_RCU_READ_LOCKED();
+
/* Lookup channel in the ust app session */
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
ua_chan_node = lttng_ht_iter_get_node_str(&iter);
int ret = 0;
struct ust_app_event *ua_event;
+ ASSERT_RCU_READ_LOCKED();
+
ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
if (ua_event == NULL) {
/* Only failure mode of alloc_ust_app_event(). */
int ret = 0;
struct ust_app_event_notifier_rule *ua_event_notifier_rule;
+ ASSERT_RCU_READ_LOCKED();
+
ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(trigger);
if (ua_event_notifier_rule == NULL) {
ret = -ENOMEM;
LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(app);
LTTNG_ASSERT(consumer);
+ ASSERT_RCU_READ_LOCKED();
registry = get_session_registry(ua_sess);
/* The UST app session is held registry shall not be null. */
struct ust_app_event_notifier_rule *event_notifier_rule;
unsigned int count, i;
+ ASSERT_RCU_READ_LOCKED();
+
if (!ust_app_supports_notifiers(app)) {
goto end;
}
LTTNG_ASSERT(usess);
LTTNG_ASSERT(ua_sess);
LTTNG_ASSERT(app);
+ ASSERT_RCU_READ_LOCKED();
cds_lfht_for_each_entry(usess->domain_global.channels->ht, &uchan_iter,
uchan, node.node) {
{
LTTNG_ASSERT(usess);
LTTNG_ASSERT(usess->active);
+ ASSERT_RCU_READ_LOCKED();
DBG2("UST app global update for app sock %d for session id %" PRIu64,
app->sock, usess->id);
*/
void ust_app_global_update_event_notifier_rules(struct ust_app *app)
{
+ ASSERT_RCU_READ_LOCKED();
+
DBG2("UST application global event notifier rules update: app = '%s', pid = %d",
app->name, app->pid);
struct ust_app_session *ua_sess = NULL;
LTTNG_ASSERT(app);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(app->ust_sessions_objd, (void *)((unsigned long) objd), &iter);
node = lttng_ht_iter_get_node_ulong(&iter);
struct ust_app_channel *ua_chan = NULL;
LTTNG_ASSERT(app);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(app->ust_objd, (void *)((unsigned long) objd), &iter);
node = lttng_ht_iter_get_node_ulong(&iter);
/*
* Free event data structure. This does NOT delete it from any hash table. It's
- * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
+ * safe to pass a NULL pointer. This should be called inside a call RCU if the
* event is previously deleted from a rcu hash table.
*/
static void destroy_event(struct ust_registry_event *event)
LTTNG_ASSERT(chan);
LTTNG_ASSERT(name);
LTTNG_ASSERT(sig);
+ ASSERT_RCU_READ_LOCKED();
/* Setup key for the match function. */
strncpy(key.name, name, sizeof(key.name));
LTTNG_ASSERT(chan);
LTTNG_ASSERT(event);
+ ASSERT_RCU_READ_LOCKED();
/* Delete the node first. */
iter.iter.node = &event->node.node;
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
+ ASSERT_RCU_READ_LOCKED();
+
cds_lfht_lookup(session->enums->ht,
ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
ht_match_enum, reg_enum_lookup, &iter.iter);
struct lttng_ht_iter iter;
struct ust_registry_enum reg_enum_lookup;
+ ASSERT_RCU_READ_LOCKED();
+
memset(®_enum_lookup, 0, sizeof(reg_enum_lookup));
strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
LTTNG_ASSERT(reg_session);
LTTNG_ASSERT(reg_enum);
+ ASSERT_RCU_READ_LOCKED();
/* Delete the node first. */
iter.iter.node = ®_enum->node.node;
LTTNG_ASSERT(session);
LTTNG_ASSERT(session->channels);
+ ASSERT_RCU_READ_LOCKED();
DBG3("UST registry channel finding key %" PRIu64, key);
struct lttng_ht_node_u64 *node;
struct lttng_consumer_channel *channel = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
/* -1ULL keys are lookup failures */
if (key == (uint64_t) -1ULL) {
return NULL;
void consumer_flag_relayd_for_destroy(struct consumer_relayd_sock_pair *relayd)
{
LTTNG_ASSERT(relayd);
+ ASSERT_RCU_READ_LOCKED();
/* Set destroy flag for this object */
uatomic_set(&relayd->destroy_flag, 1);
struct lttng_ht_iter iter;
LTTNG_ASSERT(relayd);
+ ASSERT_RCU_READ_LOCKED();
lttng_ht_lookup(the_consumer_data.relayd_ht, &relayd->net_seq_idx,
&iter);
struct lttng_ht_node_u64 *node;
struct consumer_relayd_sock_pair *relayd = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
/* Negative keys are lookup failures */
if (key == (uint64_t) -1ULL) {
goto error;
LTTNG_ASSERT(ctx);
LTTNG_ASSERT(relayd_sock);
+ ASSERT_RCU_READ_LOCKED();
DBG("Consumer adding relayd socket (idx: %" PRIu64 ")", net_seq_idx);
struct lttng_ht_iter iter;
struct consumer_relayd_sock_pair *relayd = NULL;
+ ASSERT_RCU_READ_LOCKED();
+
/* Iterate over all relayd since they are indexed by net_seq_idx. */
cds_lfht_for_each_entry(the_consumer_data.relayd_ht->ht, &iter.iter,
relayd, node.node) {
struct lttng_dynamic_pointer_array streams_packet_to_open;
size_t stream_idx;
+ ASSERT_RCU_READ_LOCKED();
+
DBG("Consumer sample rotate position for channel %" PRIu64, key);
lttng_dynamic_array_init(&stream_rotation_positions,
struct lttng_ht_iter iter;
struct lttng_ht *ht = the_consumer_data.stream_per_chan_id_ht;
+ ASSERT_RCU_READ_LOCKED();
+
rcu_read_lock();
DBG("Consumer rotate ready streams in channel %" PRIu64, key);
#define member_sizeof(type, field) sizeof(((type *) 0)->field)
#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&lock))
+#define ASSERT_RCU_READ_LOCKED(lock) LTTNG_ASSERT(rcu_read_ongoing())
/* Attribute suitable to tag functions as having printf()-like arguments. */
#define ATTR_FORMAT_PRINTF(_string_index, _first_to_check) \
int ret;
struct lttng_consumer_channel *metadata;
+ ASSERT_RCU_READ_LOCKED();
+
DBG("UST consumer setup metadata key %" PRIu64, key);
metadata = consumer_find_channel(key);
LTTNG_ASSERT(path);
LTTNG_ASSERT(ctx);
+ ASSERT_RCU_READ_LOCKED();
DBG("UST consumer snapshot metadata with key %" PRIu64 " at path %s",
key, path);
LTTNG_ASSERT(path);
LTTNG_ASSERT(ctx);
+ ASSERT_RCU_READ_LOCKED();
rcu_read_lock();
LTTNG_ASSERT(ctx);
LTTNG_ASSERT(metadata_stream);
+ ASSERT_RCU_READ_LOCKED();
metadata_channel = metadata_stream->chan;
pthread_mutex_unlock(&metadata_stream->lock);