static pthread_t dispatch_thread;
static pthread_t agent_reg_thread;
static pthread_t load_session_thread;
-static pthread_t notification_thread;
static pthread_t rotation_thread;
static pthread_t timer_thread;
struct lttng_pipe *ust32_channel_monitor_pipe = NULL,
*ust64_channel_monitor_pipe = NULL,
*kernel_channel_monitor_pipe = NULL;
- bool notification_thread_launched = false;
bool rotation_thread_launched = false;
bool timer_thread_launched = false;
struct lttng_thread *ht_cleanup_thread = NULL;
struct timer_thread_parameters timer_thread_ctx;
/* Queue of rotation jobs populated by the sessiond-timer. */
struct rotation_thread_timer_queue *rotation_timer_queue = NULL;
- sem_t notification_thread_ready;
init_kernel_workarounds();
goto exit_health;
}
- /*
- * The rotation thread needs the notification thread to be ready before
- * creating the rotate_notification_channel, so we use this semaphore as
- * a rendez-vous point.
- */
- sem_init(¬ification_thread_ready, 0, 0);
-
/* notification_thread_data acquires the pipes' read side. */
notification_thread_handle = notification_thread_handle_create(
ust32_channel_monitor_pipe,
ust64_channel_monitor_pipe,
- kernel_channel_monitor_pipe,
- ¬ification_thread_ready);
+ kernel_channel_monitor_pipe);
if (!notification_thread_handle) {
retval = -1;
ERR("Failed to create notification thread shared data");
- stop_threads();
goto exit_notification;
}
/* Create notification thread. */
- ret = pthread_create(¬ification_thread, default_pthread_attr(),
- thread_notification, notification_thread_handle);
- if (ret) {
- errno = ret;
- PERROR("pthread_create notification");
+ if (!launch_notification_thread(notification_thread_handle)) {
retval = -1;
- stop_threads();
goto exit_notification;
+
}
- notification_thread_launched = true;
/* Create timer thread. */
ret = pthread_create(&timer_thread, default_pthread_attr(),
/* rotation_thread_data acquires the pipes' read side. */
rotation_thread_handle = rotation_thread_handle_create(
rotation_timer_queue,
- notification_thread_handle,
- ¬ification_thread_ready);
+ notification_thread_handle);
if (!rotation_thread_handle) {
retval = -1;
ERR("Failed to create rotation thread shared data");
exit_client:
exit_rotation:
exit_notification:
- sem_destroy(¬ification_thread_ready);
lttng_thread_list_shutdown_orphans();
exit_health:
exit_init_data:
*/
rcu_barrier();
- /*
- * The teardown of the notification system is performed after the
- * session daemon's teardown in order to allow it to be notified
- * of the active session and channels at the moment of the teardown.
- */
- if (notification_thread_handle) {
- if (notification_thread_launched) {
- notification_thread_command_quit(
- notification_thread_handle);
- ret = pthread_join(notification_thread, &status);
- if (ret) {
- errno = ret;
- PERROR("pthread_join notification thread");
- retval = -1;
- }
- }
- notification_thread_handle_destroy(notification_thread_handle);
- }
-
if (rotation_thread_handle) {
if (rotation_thread_launched) {
ret = pthread_join(rotation_thread, &status);
rcu_thread_offline();
rcu_unregister_thread();
+ /*
+ * The teardown of the notification system is performed after the
+ * session daemon's teardown in order to allow it to be notified
+ * of the active session and channels at the moment of the teardown.
+ */
+ if (notification_thread_handle) {
+ notification_thread_handle_destroy(notification_thread_handle);
+ }
lttng_pipe_destroy(ust32_channel_monitor_pipe);
lttng_pipe_destroy(ust64_channel_monitor_pipe);
lttng_pipe_destroy(kernel_channel_monitor_pipe);
#include "notification-thread-commands.h"
#include "lttng-sessiond.h"
#include "health-sessiond.h"
+#include "thread.h"
#include <urcu.h>
#include <urcu/list.h>
assert(cds_list_empty(&handle->cmd_queue.list));
pthread_mutex_destroy(&handle->cmd_queue.lock);
+ sem_destroy(&handle->ready);
if (handle->cmd_queue.event_pipe) {
lttng_pipe_destroy(handle->cmd_queue.event_pipe);
struct notification_thread_handle *notification_thread_handle_create(
struct lttng_pipe *ust32_channel_monitor_pipe,
struct lttng_pipe *ust64_channel_monitor_pipe,
- struct lttng_pipe *kernel_channel_monitor_pipe,
- sem_t *notification_thread_ready)
+ struct lttng_pipe *kernel_channel_monitor_pipe)
{
int ret;
struct notification_thread_handle *handle;
goto end;
}
+ sem_init(&handle->ready, 0, 0);
+
event_pipe = lttng_pipe_open(FD_CLOEXEC);
if (!event_pipe) {
ERR("event_pipe creation");
} else {
handle->channel_monitoring_pipes.kernel_consumer = -1;
}
- handle->notification_thread_ready = notification_thread_ready;
end:
return handle;
error:
lttng_poll_clean(&state->events);
}
+static
+void mark_thread_as_ready(struct notification_thread_handle *handle)
+{
+ DBG("Marking notification thread as ready");
+ sem_post(&handle->ready);
+}
+
+static
+void wait_until_thread_is_ready(struct notification_thread_handle *handle)
+{
+ DBG("Waiting for notification thread to be ready");
+ sem_wait(&handle->ready);
+ DBG("Notification thread is ready");
+}
+
static
int init_thread_state(struct notification_thread_handle *handle,
struct notification_thread_state *state)
if (!state->triggers_ht) {
goto error;
}
- sem_post(handle->notification_thread_ready);
+ mark_thread_as_ready(handle);
end:
return 0;
error:
* This thread services notification channel clients and commands received
* from various lttng-sessiond components over a command queue.
*/
+static
void *thread_notification(void *data)
{
int ret;
goto end;
}
- /* Ready to handle client connections. */
- sessiond_notify_ready();
-
while (true) {
int fd_count, i;
end:
return NULL;
}
+
+static
+bool shutdown_notification_thread(void *thread_data)
+{
+ struct notification_thread_handle *handle = thread_data;
+
+ notification_thread_command_quit(handle);
+ return true;
+}
+
+bool launch_notification_thread(struct notification_thread_handle *handle)
+{
+ struct lttng_thread *thread;
+
+ thread = lttng_thread_create("Notification",
+ thread_notification,
+ shutdown_notification_thread,
+ NULL,
+ handle);
+ if (!thread) {
+ goto error;
+ }
+
+ /*
+ * Wait for the thread to be marked as "ready" before returning
+ * as other subsystems depend on the notification subsystem
+ * (e.g. rotation thread).
+ */
+ wait_until_thread_is_ready(handle);
+ lttng_thread_put(thread);
+ return true;
+error:
+ return false;
+}
int ust64_consumer;
int kernel_consumer;
} channel_monitoring_pipes;
- /*
- * To inform the rotation thread we are ready.
- */
- sem_t *notification_thread_ready;
+ /* Used to wait for the launch of the notification thread. */
+ sem_t ready;
};
/**
struct notification_thread_handle *notification_thread_handle_create(
struct lttng_pipe *ust32_channel_monitor_pipe,
struct lttng_pipe *ust64_channel_monitor_pipe,
- struct lttng_pipe *kernel_channel_monitor_pipe,
- sem_t *notification_thread_ready);
+ struct lttng_pipe *kernel_channel_monitor_pipe);
void notification_thread_handle_destroy(
struct notification_thread_handle *handle);
-
-void *thread_notification(void *data);
+bool launch_notification_thread(struct notification_thread_handle *handle);
#endif /* NOTIFICATION_THREAD_H */
struct rotation_thread_timer_queue *rotation_timer_queue;
/* Access to the notification thread cmd_queue */
struct notification_thread_handle *notification_thread_handle;
- sem_t *notification_thread_ready;
};
static
struct rotation_thread_handle *rotation_thread_handle_create(
struct rotation_thread_timer_queue *rotation_timer_queue,
- struct notification_thread_handle *notification_thread_handle,
- sem_t *notification_thread_ready)
+ struct notification_thread_handle *notification_thread_handle)
{
struct rotation_thread_handle *handle;
handle->rotation_timer_queue = rotation_timer_queue;
handle->notification_thread_handle = notification_thread_handle;
- handle->notification_thread_ready = notification_thread_ready;
end:
return handle;
goto end;
}
- /*
- * We wait until the notification thread is ready to create the
- * notification channel and add it to the poll_set.
- */
- sem_wait(handle->notification_thread_ready);
rotate_notification_channel = lttng_notification_channel_create(
lttng_session_daemon_notification_endpoint);
if (!rotate_notification_channel) {
struct rotation_thread_handle *rotation_thread_handle_create(
struct rotation_thread_timer_queue *rotation_timer_queue,
- struct notification_thread_handle *notification_thread_handle,
- sem_t *notification_thread_ready);
+ struct notification_thread_handle *notification_thread_handle);
void rotation_thread_handle_destroy(
struct rotation_thread_handle *handle);