diff options
author | Rich Felker <dalias@aerifal.cx> | 2019-02-22 02:56:10 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2019-02-22 03:25:39 -0500 |
commit | ba18c1ecc6a18203ad8496791154af86f706f632 (patch) | |
tree | d1e407e0b4f3fbe9e4463e66c960473112159981 /ldso | |
parent | 7865d569de7b29dd90b94b5680ec7a2a86ed27af (diff) | |
download | musl-ba18c1ecc6a18203ad8496791154af86f706f632.tar.gz musl-ba18c1ecc6a18203ad8496791154af86f706f632.tar.bz2 musl-ba18c1ecc6a18203ad8496791154af86f706f632.tar.xz musl-ba18c1ecc6a18203ad8496791154af86f706f632.zip |
add membarrier syscall wrapper, refactor dynamic tls install to use it
the motivation for this change is twofold. first, it gets the fallback
logic out of the dynamic linker, improving code readability and
organization. second, it provides application code that wants to use
the membarrier syscall, which depends on preregistration of intent
before the process becomes multithreaded unless unbounded latency is
acceptable, with a symbol that, when linked, ensures that this
registration happens.
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/dynlink.c | 38 |
1 files changed, 6 insertions, 32 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c index c7d9dd39..025ed1b0 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -18,6 +18,7 @@ #include <ctype.h> #include <dlfcn.h> #include <semaphore.h> +#include <sys/membarrier.h> #include "pthread_impl.h" #include "libc.h" #include "dynlink.h" @@ -1351,18 +1352,6 @@ static void update_tls_size() tls_align); } -void __dl_prepare_for_threads(void) -{ - /* MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED */ - __syscall(SYS_membarrier, 1<<4, 0); -} - -static sem_t barrier_sem; -static void bcast_barrier(int s) -{ - sem_post(&barrier_sem); -} - static void install_new_tls(void) { sigset_t set; @@ -1397,26 +1386,11 @@ static void install_new_tls(void) } /* Broadcast barrier to ensure contents of new dtv is visible - * if the new dtv pointer is. Use SYS_membarrier if it works, - * otherwise emulate with a signal. */ - - /* MEMBARRIER_CMD_PRIVATE_EXPEDITED */ - if (__syscall(SYS_membarrier, 1<<3, 0)) { - sem_init(&barrier_sem, 0, 0); - struct sigaction sa = { - .sa_flags = SA_RESTART, - .sa_handler = bcast_barrier - }; - memset(&sa.sa_mask, -1, sizeof sa.sa_mask); - __libc_sigaction(SIGSYNCCALL, &sa, 0); - for (td=self->next; td!=self; td=td->next) - __syscall(SYS_tkill, td->tid, SIGSYNCCALL); - for (td=self->next; td!=self; td=td->next) - sem_wait(&barrier_sem); - sa.sa_handler = SIG_IGN; - __libc_sigaction(SIGSYNCCALL, &sa, 0); - sem_destroy(&barrier_sem); - } + * if the new dtv pointer is. The __membarrier function has a + * fallback emulation using signals for kernels that lack the + * feature at the syscall level. */ + + __membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0); /* Install new dtv for each thread. */ for (j=0, td=self; !j || td!=self; j++, td=td->next) { |