sessiond: notification: add support for async commands
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 13 Feb 2020 21:50:52 +0000 (16:50 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 11 Aug 2020 21:05:27 +0000 (17:05 -0400)
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 <jeremie.galarneau@efficios.com>
Change-Id: I6951987dda0262d1500a3b4e1403fb2559a3ff44

src/bin/lttng-sessiond/notification-thread-commands.c
src/bin/lttng-sessiond/notification-thread-commands.h
src/bin/lttng-sessiond/notification-thread-events.c

index 4474d1978ed524f29866248910c6b697cc494282..a3b41f989e72d5de6e116af5f5730a03f8f05c33 100644 (file)
@@ -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),
+                       &notification_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);
 
index a90d1ac2b2f662697fd54412596cba2e06689b9d..11889f934f120f2e056a03cce29f3e224179d180 100644 (file)
@@ -15,6 +15,7 @@
 #include "notification-thread-internal.h"
 #include "notification-thread-events.h"
 #include <common/waiter.h>
+#include <stdbool.h>
 
 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(
index 6e507642a224be3affae1540bd762bc2a138849a..3f8cb4804ddd0800061f634afb3d6e92022e8103 100644 (file)
@@ -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:
This page took 0.027798 seconds and 4 git commands to generate.