From: Jérémie Galarneau Date: Thu, 13 Feb 2020 21:50:52 +0000 (-0500) Subject: sessiond: notification: add support for async commands X-Git-Tag: v2.13.0-rc1~500 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=0ab399e0bcf4e99492845f02e3e5b405155dea92;p=lttng-tools.git sessiond: notification: add support for async commands Notification thread commands are currently all blocking. This means that the emitter of the command uses the notification_thread_command APIs to (stack) allocate a command context and wait on an lttng_waiter for a reply. In preparation for the addition of non-blocking commands, a new type of asynchroneous commands is introduced. Asynchroneous commands are "fire-and-forget"; the caller has no way of obtaining the result of the command. Asynchroneous command contexts are heap-allocated and their ownership is transferred to the notification thread. The notification thread will not attempt to wake-up the emitter and will free() the command context regardless of the command's result. Signed-off-by: Jérémie Galarneau Change-Id: I6951987dda0262d1500a3b4e1403fb2559a3ff44 --- diff --git a/src/bin/lttng-sessiond/notification-thread-commands.c b/src/bin/lttng-sessiond/notification-thread-commands.c index 4474d1978..a3b41f989 100644 --- a/src/bin/lttng-sessiond/notification-thread-commands.c +++ b/src/bin/lttng-sessiond/notification-thread-commands.c @@ -17,7 +17,6 @@ static void init_notification_thread_command(struct notification_thread_command *cmd) { - memset(cmd, 0, sizeof(*cmd)); CDS_INIT_LIST_HEAD(&cmd->cmd_list_node); lttng_waiter_init(&cmd->reply_waiter); } @@ -54,13 +53,69 @@ error_unlock_queue: return -1; } +static +struct notification_thread_command *notification_thread_command_copy( + const struct notification_thread_command *original_cmd) +{ + struct notification_thread_command *new_cmd; + + new_cmd = zmalloc(sizeof(*new_cmd)); + if (!new_cmd) { + goto end; + } + + *new_cmd = *original_cmd; + init_notification_thread_command(new_cmd); +end: + return new_cmd; +} + +static +int run_command_no_wait(struct notification_thread_handle *handle, + const struct notification_thread_command *in_cmd) +{ + int ret; + uint64_t notification_counter = 1; + struct notification_thread_command *new_cmd = + notification_thread_command_copy(in_cmd); + + if (!new_cmd) { + goto error; + } + new_cmd->is_async = true; + + pthread_mutex_lock(&handle->cmd_queue.lock); + /* Add to queue. */ + cds_list_add_tail(&new_cmd->cmd_list_node, + &handle->cmd_queue.list); + /* Wake-up thread. */ + ret = lttng_write(lttng_pipe_get_writefd(handle->cmd_queue.event_pipe), + ¬ification_counter, sizeof(notification_counter)); + if (ret != sizeof(notification_counter)) { + PERROR("write to notification thread's queue event fd"); + /* + * Remove the command from the list so the notification + * thread does not process it. + */ + cds_list_del(&new_cmd->cmd_list_node); + goto error_unlock_queue; + } + pthread_mutex_unlock(&handle->cmd_queue.lock); + return 0; +error_unlock_queue: + free(new_cmd); + pthread_mutex_unlock(&handle->cmd_queue.lock); +error: + return -1; +} + enum lttng_error_code notification_thread_command_register_trigger( struct notification_thread_handle *handle, struct lttng_trigger *trigger) { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -83,7 +138,7 @@ enum lttng_error_code notification_thread_command_unregister_trigger( { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -108,7 +163,7 @@ enum lttng_error_code notification_thread_command_add_channel( { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -137,7 +192,7 @@ enum lttng_error_code notification_thread_command_remove_channel( { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -162,7 +217,7 @@ enum lttng_error_code notification_thread_command_session_rotation_ongoing( { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -191,7 +246,7 @@ enum lttng_error_code notification_thread_command_session_rotation_completed( { int ret; enum lttng_error_code ret_code; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); @@ -217,7 +272,7 @@ void notification_thread_command_quit( struct notification_thread_handle *handle) { int ret; - struct notification_thread_command cmd; + struct notification_thread_command cmd = {}; init_notification_thread_command(&cmd); diff --git a/src/bin/lttng-sessiond/notification-thread-commands.h b/src/bin/lttng-sessiond/notification-thread-commands.h index a90d1ac2b..11889f934 100644 --- a/src/bin/lttng-sessiond/notification-thread-commands.h +++ b/src/bin/lttng-sessiond/notification-thread-commands.h @@ -15,6 +15,7 @@ #include "notification-thread-internal.h" #include "notification-thread-events.h" #include +#include struct notification_thread_data; struct lttng_trigger; @@ -67,6 +68,7 @@ struct notification_thread_command { /* lttng_waiter on which to wait for command reply (optional). */ struct lttng_waiter reply_waiter; enum lttng_error_code reply_code; + bool is_async; }; enum lttng_error_code notification_thread_command_register_trigger( diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index 6e507642a..3f8cb4804 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -2475,7 +2475,12 @@ int handle_notification_thread_command( } end: cds_list_del(&cmd->cmd_list_node); - lttng_waiter_wake_up(&cmd->reply_waiter); + if (cmd->is_async) { + free(cmd); + cmd = NULL; + } else { + lttng_waiter_wake_up(&cmd->reply_waiter); + } pthread_mutex_unlock(&handle->cmd_queue.lock); return ret; error_unlock: