2 * SPDX-License-Identifier: LGPL-2.1-or-later
4 * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Userspace RCU library - sys_futex compatibility code
17 #include <urcu/arch.h>
18 #include <urcu/system.h>
20 #include "lib/lttng-ust/futex.h"
23 * This compat header originated in userspace RCU where it's used across
24 * multiple shared objects hence the need to have the mutexes as public weak
25 * symbols, in our case here, it's only used internally by liblttng-ust so we
26 * can hide them. If we end up using this compat header in another library in
27 * this project we will have to use the same scheme, but in the meantime, don't
28 * expose those symbols in the ABI.
32 * This comment will apply if we start using this compat header in multiple
35 * Using attribute "weak" for __lttng_ust_compat_futex_lock and
36 * __lttng_ust_compat_futex_cond. Those are globally visible by the entire
37 * program, even though many shared objects may have their own version.
38 * The first version that gets loaded will be used by the entire program
39 * (executable and all shared objects).
42 static pthread_mutex_t __lttng_ust_compat_futex_lock
= PTHREAD_MUTEX_INITIALIZER
;
43 static pthread_cond_t __lttng_ust_compat_futex_cond
= PTHREAD_COND_INITIALIZER
;
46 * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
47 * For now, timeout, uaddr2 and val3 are unused.
48 * Waiter will relinquish the CPU until woken up.
51 int lttng_ust_compat_futex_noasync(int32_t *uaddr
, int op
, int32_t val
,
52 const struct timespec
*timeout
, int32_t *uaddr2
, int32_t val3
)
57 * Check if NULL. Don't let users expect that they are taken into
65 * memory barriers to serialize with the previous uaddr modification.
69 lockret
= pthread_mutex_lock(&__lttng_ust_compat_futex_lock
);
78 * Wait until *uaddr is changed to something else than "val".
79 * Comparing *uaddr content against val figures out which
80 * thread has been awakened.
82 while (CMM_LOAD_SHARED(*uaddr
) == val
)
83 pthread_cond_wait(&__lttng_ust_compat_futex_cond
,
84 &__lttng_ust_compat_futex_lock
);
88 * Each wake is sending a broadcast, thus attempting wakeup of
89 * all awaiting threads, independently of their respective
92 pthread_cond_broadcast(&__lttng_ust_compat_futex_cond
);
98 lockret
= pthread_mutex_unlock(&__lttng_ust_compat_futex_lock
);
108 * _ASYNC SIGNAL-SAFE_.
109 * For now, timeout, uaddr2 and val3 are unused.
110 * Waiter will busy-loop trying to read the condition.
111 * It is OK to use compat_futex_async() on a futex address on which
112 * futex() WAKE operations are also performed.
115 int lttng_ust_compat_futex_async(int32_t *uaddr
, int op
, int32_t val
,
116 const struct timespec
*timeout
, int32_t *uaddr2
, int32_t val3
)
121 * Check if NULL. Don't let users expect that they are taken into
129 * Ensure previous memory operations on uaddr have completed.
135 while (CMM_LOAD_SHARED(*uaddr
) == val
) {
136 if (poll(NULL
, 0, 10) < 0) {
138 /* Keep poll errno. Caller handles EINTR. */