1 #include <sys/membarrier.h>
5 #include "pthread_impl.h"
8 static void dummy_0(void)
12 weak_alias(dummy_0
, __tl_lock
);
13 weak_alias(dummy_0
, __tl_unlock
);
15 static sem_t barrier_sem
;
17 static void bcast_barrier(int s
)
19 sem_post(&barrier_sem
);
22 int __membarrier(int cmd
, int flags
)
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
31 if (r
&& cmd
== MEMBARRIER_CMD_PRIVATE_EXPEDITED
&& !flags
) {
32 pthread_t self
=__pthread_self(), td
;
34 __block_app_sigs(&set
);
36 sem_init(&barrier_sem
, 0, 0);
37 struct sigaction sa
= {
38 .sa_flags
= SA_RESTART
| SA_ONSTACK
,
39 .sa_handler
= bcast_barrier
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
);
48 sa
.sa_handler
= SIG_IGN
;
49 __libc_sigaction(SIGSYNCCALL
, &sa
, 0);
51 sem_destroy(&barrier_sem
);
55 return __syscall_ret(r
);
58 void __membarrier_init(void)
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);
72 weak_alias(__membarrier
, membarrier
);