X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fconsumer-timer.c;h=f9c41c0eb0f8f9f32def26028f743ce7df45d322;hb=3cc048812bf25b42003b40b6b868b9366faefafb;hp=ef056d1188d69571f6131c89c34cf3d8f622d2a9;hpb=331744e34f56a5aec69b05d356d6901e67926acc;p=lttng-tools.git diff --git a/src/common/consumer-timer.c b/src/common/consumer-timer.c index ef056d118..f9c41c0eb 100644 --- a/src/common/consumer-timer.c +++ b/src/common/consumer-timer.c @@ -26,7 +26,12 @@ #include "consumer-timer.h" #include "ust-consumer/ust-consumer.h" -static struct timer_signal_data timer_signal; +static struct timer_signal_data timer_signal = { + .tid = 0, + .setup_done = 0, + .qs_done = 0, + .lock = PTHREAD_MUTEX_INITIALIZER, +}; /* * Set custom signal mask to current thread. @@ -61,17 +66,17 @@ static void metadata_switch_timer(struct lttng_consumer_local_data *ctx, channel = si->si_value.sival_ptr; assert(channel); + if (channel->switch_timer_error) { + return; + } + DBG("Switch timer for channel %" PRIu64, channel->key); switch (ctx->type) { case LTTNG_CONSUMER32_UST: case LTTNG_CONSUMER64_UST: ret = lttng_ustconsumer_request_metadata(ctx, channel); if (ret < 0) { - /* - * An error means that we were unable to request the metadata to - * the session daemon so stop the timer for that channel. - */ - consumer_timer_switch_stop(channel); + channel->switch_timer_error = 1; } break; case LTTNG_CONSUMER_KERNEL: @@ -81,6 +86,57 @@ static void metadata_switch_timer(struct lttng_consumer_local_data *ctx, } } +static +void consumer_timer_signal_thread_qs(unsigned int signr) +{ + sigset_t pending_set; + int ret; + + /* + * We need to be the only thread interacting with the thread + * that manages signals for teardown synchronization. + */ + pthread_mutex_lock(&timer_signal.lock); + + /* Ensure we don't have any signal queued for this channel. */ + for (;;) { + ret = sigemptyset(&pending_set); + if (ret == -1) { + PERROR("sigemptyset"); + } + ret = sigpending(&pending_set); + if (ret == -1) { + PERROR("sigpending"); + } + if (!sigismember(&pending_set, LTTNG_CONSUMER_SIG_SWITCH)) { + break; + } + caa_cpu_relax(); + } + + /* + * From this point, no new signal handler will be fired that would try to + * access "chan". However, we still need to wait for any currently + * executing handler to complete. + */ + cmm_smp_mb(); + CMM_STORE_SHARED(timer_signal.qs_done, 0); + cmm_smp_mb(); + + /* + * Kill with LTTNG_CONSUMER_SIG_TEARDOWN, so signal management thread wakes + * up. + */ + kill(getpid(), LTTNG_CONSUMER_SIG_TEARDOWN); + + while (!CMM_LOAD_SHARED(timer_signal.qs_done)) { + caa_cpu_relax(); + } + cmm_smp_mb(); + + pthread_mutex_unlock(&timer_signal.lock); +} + /* * Set the timer for periodical metadata flush. */ @@ -124,7 +180,6 @@ void consumer_timer_switch_start(struct lttng_consumer_channel *channel, void consumer_timer_switch_stop(struct lttng_consumer_channel *channel) { int ret; - sigset_t pending_set; assert(channel); @@ -133,41 +188,10 @@ void consumer_timer_switch_stop(struct lttng_consumer_channel *channel) PERROR("timer_delete"); } - /* Ensure we don't have any signal queued for this channel. */ - for (;;) { - ret = sigemptyset(&pending_set); - if (ret == -1) { - PERROR("sigemptyset"); - } - ret = sigpending(&pending_set); - if (ret == -1) { - PERROR("sigpending"); - } - if (!sigismember(&pending_set, LTTNG_CONSUMER_SIG_SWITCH)) { - break; - } - caa_cpu_relax(); - } - - /* - * From this point, no new signal handler will be fired that would try to - * access "chan". However, we still need to wait for any currently - * executing handler to complete. - */ - cmm_smp_mb(); - CMM_STORE_SHARED(timer_signal.qs_done, 0); - cmm_smp_mb(); + consumer_timer_signal_thread_qs(LTTNG_CONSUMER_SIG_SWITCH); - /* - * Kill with LTTNG_CONSUMER_SIG_TEARDOWN, so signal management thread wakes - * up. - */ - kill(getpid(), LTTNG_CONSUMER_SIG_TEARDOWN); - - while (!CMM_LOAD_SHARED(timer_signal.qs_done)) { - caa_cpu_relax(); - } - cmm_smp_mb(); + channel->switch_timer = 0; + channel->switch_timer_enabled = 0; } /*