uatomic/x86: Remove redundant memory barriers
[urcu.git] / src / compat_futex.c
CommitLineData
acdb82a2
MJ
1// SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
49617de1 5/*
49617de1 6 * Userspace RCU library - sys_futex compatibility code
49617de1
MD
7 */
8
9#include <stdio.h>
10#include <pthread.h>
11#include <signal.h>
49617de1
MD
12#include <errno.h>
13#include <poll.h>
6d841bc2 14#include <stdint.h>
49617de1
MD
15
16#include <urcu/arch.h>
01477510 17#include <urcu/assert.h>
41849996 18#include <urcu/futex.h>
f4fe9309 19#include <urcu/system.h>
49617de1 20
5c02e37d
MD
21/*
22 * Using attribute "weak" for __urcu_compat_futex_lock and
23 * __urcu_compat_futex_cond. Those are globally visible by the entire
24 * program, even though many shared objects may have their own version.
25 * The first version that gets loaded will be used by the entire program
26 * (executable and all shared objects).
27 */
28
29__attribute__((weak))
30pthread_mutex_t __urcu_compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
31__attribute__((weak))
32pthread_cond_t __urcu_compat_futex_cond = PTHREAD_COND_INITIALIZER;
49617de1
MD
33
34/*
35 * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
36 * For now, timeout, uaddr2 and val3 are unused.
37 * Waiter will relinquish the CPU until woken up.
38 */
39
6d841bc2
MD
40int compat_futex_noasync(int32_t *uaddr, int op, int32_t val,
41 const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
49617de1 42{
54fd78ef 43 int ret = 0, lockret;
49617de1
MD
44
45 /*
46 * Check if NULL. Don't let users expect that they are taken into
67ecffc0 47 * account.
49617de1 48 */
01477510
FD
49 urcu_posix_assert(!timeout);
50 urcu_posix_assert(!uaddr2);
51 urcu_posix_assert(!val3);
49617de1
MD
52
53 /*
54 * memory barriers to serialize with the previous uaddr modification.
55 */
5481ddb3 56 cmm_smp_mb();
49617de1 57
c8114d9b
MD
58 lockret = pthread_mutex_lock(&__urcu_compat_futex_lock);
59 if (lockret) {
60 errno = lockret;
b0a841b4
MD
61 ret = -1;
62 goto end;
63 }
49617de1
MD
64 switch (op) {
65 case FUTEX_WAIT:
db21eff9
MD
66 /*
67 * Wait until *uaddr is changed to something else than "val".
68 * Comparing *uaddr content against val figures out which
69 * thread has been awakened.
70 */
f4fe9309 71 while (CMM_LOAD_SHARED(*uaddr) == val)
db21eff9
MD
72 pthread_cond_wait(&__urcu_compat_futex_cond,
73 &__urcu_compat_futex_lock);
49617de1
MD
74 break;
75 case FUTEX_WAKE:
db21eff9
MD
76 /*
77 * Each wake is sending a broadcast, thus attempting wakeup of
78 * all awaiting threads, independently of their respective
79 * uaddr.
80 */
5c02e37d 81 pthread_cond_broadcast(&__urcu_compat_futex_cond);
49617de1
MD
82 break;
83 default:
b0a841b4
MD
84 errno = EINVAL;
85 ret = -1;
49617de1 86 }
c8114d9b
MD
87 lockret = pthread_mutex_unlock(&__urcu_compat_futex_lock);
88 if (lockret) {
89 errno = lockret;
b0a841b4
MD
90 ret = -1;
91 }
92end:
93 return ret;
49617de1
MD
94}
95
96/*
97 * _ASYNC SIGNAL-SAFE_.
98 * For now, timeout, uaddr2 and val3 are unused.
99 * Waiter will busy-loop trying to read the condition.
b2633d21
MD
100 * It is OK to use compat_futex_async() on a futex address on which
101 * futex() WAKE operations are also performed.
49617de1
MD
102 */
103
6d841bc2
MD
104int compat_futex_async(int32_t *uaddr, int op, int32_t val,
105 const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
49617de1 106{
b0a841b4
MD
107 int ret = 0;
108
49617de1
MD
109 /*
110 * Check if NULL. Don't let users expect that they are taken into
67ecffc0 111 * account.
49617de1 112 */
01477510
FD
113 urcu_posix_assert(!timeout);
114 urcu_posix_assert(!uaddr2);
115 urcu_posix_assert(!val3);
49617de1
MD
116
117 /*
118 * Ensure previous memory operations on uaddr have completed.
119 */
5481ddb3 120 cmm_smp_mb();
49617de1
MD
121
122 switch (op) {
123 case FUTEX_WAIT:
b0a841b4
MD
124 while (CMM_LOAD_SHARED(*uaddr) == val) {
125 if (poll(NULL, 0, 10) < 0) {
126 ret = -1;
127 /* Keep poll errno. Caller handles EINTR. */
128 goto end;
129 }
130 }
49617de1
MD
131 break;
132 case FUTEX_WAKE:
133 break;
134 default:
b0a841b4
MD
135 errno = EINVAL;
136 ret = -1;
49617de1 137 }
b0a841b4
MD
138end:
139 return ret;
49617de1 140}
This page took 0.048607 seconds and 4 git commands to generate.