1#include <sys/membarrier.h> 2#include <semaphore.h> 3#include <signal.h> 4#include <string.h> 5#include "pthread_impl.h" 6#include "syscall.h" 7 8static void dummy_0(void) 9{ 10} 11 12weak_alias(dummy_0, __tl_lock); 13weak_alias(dummy_0, __tl_unlock); 14 15static sem_t barrier_sem; 16 17static void bcast_barrier(int s) 18{ 19 sem_post(&barrier_sem); 20} 21 22int __membarrier(int cmd, int flags) 23{ 24 int r = __syscall(SYS_membarrier, cmd, flags); 25 /* Emulate the private expedited command, which is needed by the 26 * dynamic linker for installation of dynamic TLS, for older 27 * kernels that lack the syscall. Unlike the syscall, this only 28 * synchronizes with threads of the process, not other processes 29 * sharing the VM, but such sharing is not a supported usage 30 * anyway. */ 31 if (r && cmd == MEMBARRIER_CMD_PRIVATE_EXPEDITED && !flags) { 32 pthread_t self=__pthread_self(), td; 33 sigset_t set; 34 __block_app_sigs(&set); 35 __tl_lock(); 36 sem_init(&barrier_sem, 0, 0); 37 struct sigaction sa = { 38 .sa_flags = SA_RESTART | SA_ONSTACK, 39 .sa_handler = bcast_barrier 40 }; 41 memset(&sa.sa_mask, -1, sizeof sa.sa_mask); 42 if (!__libc_sigaction(SIGSYNCCALL, &sa, 0)) { 43 for (td=self->next; td!=self; td=td->next) 44 __syscall(SYS_tkill, td->tid, SIGSYNCCALL); 45 for (td=self->next; td!=self; td=td->next) 46 sem_wait(&barrier_sem); 47 r = 0; 48 sa.sa_handler = SIG_IGN; 49 __libc_sigaction(SIGSYNCCALL, &sa, 0); 50 } 51 sem_destroy(&barrier_sem); 52 __tl_unlock(); 53 __restore_sigs(&set); 54 } 55 return __syscall_ret(r); 56} 57 58void __membarrier_init(void) 59{ 60 /* If membarrier is linked, attempt to pre-register to be able to use 61 * the private expedited command before the process becomes multi- 62 * threaded, since registering later has bad, potentially unbounded 63 * latency. This syscall should be essentially free, and it's arguably 64 * a mistake in the API design that registration was even required. 65 * For other commands, registration may impose some cost, so it's left 66 * to the application to do so if desired. Unfortunately this means 67 * library code initialized after the process becomes multi-threaded 68 * cannot use these features without accepting registration latency. */ 69 __syscall(SYS_membarrier, MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0); 70} 71 72weak_alias(__membarrier, membarrier); 73