X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ust%2Flttng-ust-comm.c;h=0fe2da466ad1cce241b0b82efd864e651223341e;hb=8e95eaadb72a1a97486f15cc128ff6ed2fcd0196;hp=384a6a582af8a2034c9678b31b400b4e33b95f50;hpb=ab64db3571ab2b39a2218f81b3483768f815822a;p=lttng-ust.git diff --git a/src/lib/lttng-ust/lttng-ust-comm.c b/src/lib/lttng-ust/lttng-ust-comm.c index 384a6a58..0fe2da46 100644 --- a/src/lib/lttng-ust/lttng-ust-comm.c +++ b/src/lib/lttng-ust/lttng-ust-comm.c @@ -118,6 +118,28 @@ static int lttng_ust_comm_should_quit; */ int lttng_ust_loaded __attribute__((weak)); +/* + * Notes on async-signal-safety of ust lock: a few libc functions are used + * which are not strictly async-signal-safe: + * + * - pthread_setcancelstate + * - pthread_mutex_lock + * - pthread_mutex_unlock + * + * As of glibc 2.35, the implementation of pthread_setcancelstate only + * touches TLS data, and it appears to be safe to use from signal + * handlers. If the libc implementation changes, this will need to be + * revisited, and we may ask glibc to provide an async-signal-safe + * pthread_setcancelstate. + * + * As of glibc 2.35, the implementation of pthread_mutex_lock/unlock + * for fast mutexes only relies on the pthread_mutex_t structure. + * Disabling signals around all uses of this mutex ensures + * signal-safety. If the libc implementation changes and eventually uses + * other global resources, this will need to be revisited and we may + * need to implement our own mutex. + */ + /* * Return 0 on success, -1 if should quit. * The lock is taken in both cases. @@ -365,7 +387,7 @@ const char *get_lttng_home_dir(void) * Force a read (imply TLS allocation for dlopen) of TLS variables. */ static -void lttng_nest_count_alloc_tls(void) +void lttng_ust_nest_count_alloc_tls(void) { asm volatile ("" : : "m" (URCU_TLS(lttng_ust_nest_count))); } @@ -380,26 +402,26 @@ void lttng_ust_mutex_nest_alloc_tls(void) * Allocate lttng-ust urcu TLS. */ static -void lttng_lttng_ust_urcu_alloc_tls(void) +void lttng_ust_urcu_alloc_tls(void) { (void) lttng_ust_urcu_read_ongoing(); } -void lttng_ust_alloc_tls(void) +void lttng_ust_common_init_thread(int flags) { - lttng_lttng_ust_urcu_alloc_tls(); + lttng_ust_urcu_alloc_tls(); lttng_ringbuffer_alloc_tls(); - lttng_vtid_alloc_tls(); - lttng_nest_count_alloc_tls(); - lttng_procname_alloc_tls(); + lttng_ust_vtid_init_thread(flags); + lttng_ust_nest_count_alloc_tls(); + lttng_ust_procname_init_thread(flags); lttng_ust_mutex_nest_alloc_tls(); - lttng_ust_perf_counter_alloc_tls(); + lttng_ust_perf_counter_init_thread(flags); lttng_ust_common_alloc_tls(); - lttng_cgroup_ns_alloc_tls(); - lttng_ipc_ns_alloc_tls(); - lttng_net_ns_alloc_tls(); - lttng_time_ns_alloc_tls(); - lttng_uts_ns_alloc_tls(); + lttng_ust_cgroup_ns_init_thread(flags); + lttng_ust_ipc_ns_init_thread(flags); + lttng_ust_net_ns_init_thread(flags); + lttng_ust_time_ns_init_thread(flags); + lttng_ust_uts_ns_init_thread(flags); lttng_ust_ring_buffer_client_discard_alloc_tls(); lttng_ust_ring_buffer_client_discard_rt_alloc_tls(); lttng_ust_ring_buffer_client_overwrite_alloc_tls(); @@ -424,7 +446,9 @@ void lttng_ust_init_thread(void) * ensure those are initialized before a signal handler nesting over * this thread attempts to use them. */ - lttng_ust_alloc_tls(); + lttng_ust_common_init_thread(LTTNG_UST_INIT_THREAD_MASK); + + lttng_ust_urcu_register_thread(); } int lttng_get_notify_socket(void *owner) @@ -1735,18 +1759,25 @@ void wait_for_sessiond(struct sock_info *sock_info) DBG("Waiting for %s apps sessiond", sock_info->name); /* Wait for futex wakeup */ - if (uatomic_read((int32_t *) sock_info->wait_shm_mmap)) - goto end_wait; - - while (lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap, - FUTEX_WAIT, 0, NULL, NULL, 0)) { + while (!uatomic_read((int32_t *) sock_info->wait_shm_mmap)) { + if (!lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap, FUTEX_WAIT, 0, NULL, NULL, 0)) { + /* + * Prior queued wakeups queued by unrelated code + * using the same address can cause futex wait to + * return 0 even through the futex value is still + * 0 (spurious wakeups). Check the value again + * in user-space to validate whether it really + * differs from 0. + */ + continue; + } switch (errno) { - case EWOULDBLOCK: + case EAGAIN: /* Value already changed. */ goto end_wait; case EINTR: /* Retry if interrupted by signal. */ - break; /* Get out of switch. */ + break; /* Get out of switch. Check again. */ case EFAULT: wait_poll_fallback = 1; DBG( @@ -1786,7 +1817,7 @@ void *ust_listener_thread(void *arg) int sock, ret, prev_connect_failed = 0, has_waited = 0, fd; long timeout; - lttng_ust_alloc_tls(); + lttng_ust_common_init_thread(0); /* * If available, add '-ust' to the end of this thread's * process name @@ -2154,7 +2185,7 @@ void lttng_ust_ctor(void) * to be the dynamic linker mutex) and ust_lock, taken within * the ust lock. */ - lttng_ust_alloc_tls(); + lttng_ust_common_init_thread(0); lttng_ust_loaded = 1; @@ -2468,7 +2499,7 @@ void lttng_ust_before_fork(sigset_t *save_sigset) int ret; /* Allocate lttng-ust TLS. */ - lttng_ust_alloc_tls(); + lttng_ust_common_init_thread(0); if (URCU_TLS(lttng_ust_nest_count)) return;