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