trigger: use condition and action ref counting to ease internal objects management
[lttng-tools.git] / src / bin / lttng-sessiond / timer.c
index 06d1d4a9803213850366699992729f7a26f0e3dd..56fc4635a312211a8772330fcfec7c57816e407e 100644 (file)
@@ -1,19 +1,9 @@
 /*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License, version 2 only, as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
@@ -24,6 +14,7 @@
 #include "timer.h"
 #include "health-sessiond.h"
 #include "rotation-thread.h"
+#include "thread.h"
 
 #define LTTNG_SESSIOND_SIG_QS                          SIGRTMIN + 10
 #define LTTNG_SESSIOND_SIG_EXIT                                SIGRTMIN + 11
@@ -149,7 +140,7 @@ void timer_signal_thread_qs(unsigned int signr)
  * a positive value if no timer was created (not an error).
  */
 static
-int timer_start(timer_t *timer_id, uint64_t session_id,
+int timer_start(timer_t *timer_id, struct ltt_session *session,
                unsigned int timer_interval_us, int signal, bool one_shot)
 {
        int ret = 0, delete_ret;
@@ -158,7 +149,7 @@ int timer_start(timer_t *timer_id, uint64_t session_id,
 
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_signo = signal;
-       sev.sigev_value.sival_ptr = UINT_TO_PTR(session_id);
+       sev.sigev_value.sival_ptr = session;
        ret = timer_create(CLOCK_MONOTONIC, &sev, timer_id);
        if (ret == -1) {
                PERROR("timer_create");
@@ -214,6 +205,10 @@ int timer_session_rotation_pending_check_start(struct ltt_session *session,
 {
        int ret;
 
+       if (!session_get(session)) {
+               ret = -1;
+               goto end;
+       }
        DBG("Enabling session rotation pending check timer on session %" PRIu64,
                        session->id);
        /*
@@ -226,13 +221,13 @@ int timer_session_rotation_pending_check_start(struct ltt_session *session,
         * no need to go through the whole signal teardown scheme everytime.
         */
        ret = timer_start(&session->rotation_pending_check_timer,
-                       session->id, interval_us,
+                       session, interval_us,
                        LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK,
                        /* one-shot */ true);
        if (ret == 0) {
                session->rotation_pending_check_timer_enabled = true;
        }
-
+end:
        return ret;
 }
 
@@ -244,6 +239,7 @@ int timer_session_rotation_pending_check_stop(struct ltt_session *session)
        int ret;
 
        assert(session);
+       assert(session->rotation_pending_check_timer_enabled);
 
        DBG("Disabling session rotation pending check timer on session %" PRIu64,
                        session->id);
@@ -253,6 +249,10 @@ int timer_session_rotation_pending_check_stop(struct ltt_session *session)
                ERR("Failed to stop rotate_pending_check timer");
        } else {
                session->rotation_pending_check_timer_enabled = false;
+               /*
+                * The timer's reference to the session can be released safely.
+                */
+               session_put(session);
        }
        return ret;
 }
@@ -265,9 +265,13 @@ int timer_session_rotation_schedule_timer_start(struct ltt_session *session,
 {
        int ret;
 
-       DBG("Enabling scheduled rotation timer on session \"%s\" (%ui µs)", session->name,
-                       interval_us);
-       ret = timer_start(&session->rotation_schedule_timer, session->id,
+       if (!session_get(session)) {
+               ret = -1;
+               goto end;
+       }
+       DBG("Enabling scheduled rotation timer on session \"%s\" (%ui %s)", session->name,
+                       interval_us, USEC_UNIT);
+       ret = timer_start(&session->rotation_schedule_timer, session,
                        interval_us, LTTNG_SESSIOND_SIG_SCHEDULED_ROTATION,
                        /* one-shot */ false);
        if (ret < 0) {
@@ -301,6 +305,8 @@ int timer_session_rotation_schedule_timer_stop(struct ltt_session *session)
        }
 
        session->rotation_schedule_timer_enabled = false;
+       /* The timer's reference to the session can be released safely. */
+       session_put(session);
        ret = 0;
 end:
        return ret;
@@ -329,7 +335,8 @@ int timer_signal_init(void)
 /*
  * This thread is the sighandler for the timer signals.
  */
-void *timer_thread_func(void *data)
+static
+void *thread_timer(void *data)
 {
        int signr;
        sigset_t mask;
@@ -370,13 +377,22 @@ void *timer_thread_func(void *data)
                } else if (signr == LTTNG_SESSIOND_SIG_EXIT) {
                        goto end;
                } else if (signr == LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK) {
+                       struct ltt_session *session =
+                                       (struct ltt_session *) info.si_value.sival_ptr;
+
                        rotation_thread_enqueue_job(ctx->rotation_thread_job_queue,
                                        ROTATION_THREAD_JOB_TYPE_CHECK_PENDING_ROTATION,
-                                       /* session_id */ PTR_TO_UINT(info.si_value.sival_ptr));
+                                       session);
                } else if (signr == LTTNG_SESSIOND_SIG_SCHEDULED_ROTATION) {
                        rotation_thread_enqueue_job(ctx->rotation_thread_job_queue,
                                        ROTATION_THREAD_JOB_TYPE_SCHEDULED_ROTATION,
-                                       /* session_id */ PTR_TO_UINT(info.si_value.sival_ptr));
+                                       (struct ltt_session *) info.si_value.sival_ptr);
+                       /*
+                        * The scheduled periodic rotation timer is not in
+                        * "one-shot" mode. The reference to the session is not
+                        * released since the timer is still enabled and can
+                        * still fire.
+                        */
                } else {
                        ERR("Unexpected signal %d\n", info.si_signo);
                }
@@ -390,7 +406,27 @@ end:
        return NULL;
 }
 
-void timer_exit(void)
+static
+bool shutdown_timer_thread(void *data)
+{
+       return kill(getpid(), LTTNG_SESSIOND_SIG_EXIT) == 0;
+}
+
+bool launch_timer_thread(
+               struct timer_thread_parameters *timer_thread_parameters)
 {
-       kill(getpid(), LTTNG_SESSIOND_SIG_EXIT);
+       struct lttng_thread *thread;
+
+       thread = lttng_thread_create("Timer",
+                       thread_timer,
+                       shutdown_timer_thread,
+                       NULL,
+                       timer_thread_parameters);
+       if (!thread) {
+               goto error;
+       }
+       lttng_thread_put(thread);
+       return true;
+error:
+       return false;
 }
This page took 0.025573 seconds and 4 git commands to generate.