blob: 593bb9d9bf022c2e2ff1ae42a3d953df664d8e73 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* futex operations for glibc-internal use. NaCl version.
2 Copyright (C) 2014-2015 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19#ifndef FUTEX_INTERNAL_H
20#define FUTEX_INTERNAL_H
21
22#include <sysdeps/nptl/futex-internal.h>
23#include <errno.h>
24#include <lowlevellock-futex.h>
25#include <nacl-interfaces.h>
26#include <nptl/pthreadP.h>
27
28/* See sysdeps/nptl/futex-internal.h for documentation; this file only
29 contains NaCl-specific comments.
30
31 There is no support yet for shared futexes nor for exact relative
32 timeouts. */
33
34/* See sysdeps/nptl/futex-internal.h for constraints on the value of the
35 FUTEX_PRIVATE and FUTEX_SHARED constants.
36 Shared futexes are not yet supported, and we never allow clients to
37 actually request shared futexes. Therefore, we do not need a different
38 value. */
39#undef FUTEX_SHARED
40#define FUTEX_SHARED FUTEX_PRIVATE
41
42/* FUTEX_SHARED is not yet supported. */
43static __always_inline int
44futex_supports_pshared (int pshared)
45{
46 if (__glibc_likely (pshared == PTHREAD_PROCESS_PRIVATE))
47 return 0;
48 else if (pshared == PTHREAD_PROCESS_SHARED)
49 return ENOTSUP;
50 else
51 return EINVAL;
52}
53
54/* Relative timeouts are only emulated via absolute timeouts using the
55 system clock. */
56static __always_inline bool
57futex_supports_exact_relative_timeouts (void)
58{
59 return false;
60}
61
62/* See sysdeps/nptl/futex-internal.h for details. */
63static __always_inline int
64futex_wait (unsigned int *futex_word, unsigned int expected, int private)
65{
66 int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
67 switch (err)
68 {
69 case 0:
70 case -EAGAIN:
71 case -EINTR:
72 return -err;
73
74 case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
75 case -EFAULT: /* Must have been caused by a glibc or application bug. */
76 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
77 being normalized. Must have been caused by a glibc or
78 application bug. */
79 case -ENOSYS: /* Must have been caused by a glibc bug. */
80 /* No other errors are documented at this time. */
81 default:
82 futex_fatal_error ();
83 }
84}
85
86/* See sysdeps/nptl/futex-internal.h for details. */
87static __always_inline int
88futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
89 int private)
90{
91 int oldtype;
92 oldtype = __pthread_enable_asynccancel ();
93 int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
94 __pthread_disable_asynccancel (oldtype);
95 switch (err)
96 {
97 case 0:
98 case -EAGAIN:
99 case -EINTR:
100 return -err;
101
102 case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
103 case -EFAULT: /* Must have been caused by a glibc or application bug. */
104 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
105 being normalized. Must have been caused by a glibc or
106 application bug. */
107 case -ENOSYS: /* Must have been caused by a glibc bug. */
108 /* No other errors are documented at this time. */
109 default:
110 futex_fatal_error ();
111 }
112}
113
114/* See sysdeps/nptl/futex-internal.h for details. */
115static __always_inline int
116futex_reltimed_wait (unsigned int *futex_word, unsigned int expected,
117 const struct timespec *reltime, int private)
118{
119 int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
120 switch (err)
121 {
122 case 0:
123 case -EAGAIN:
124 case -EINTR:
125 case -ETIMEDOUT:
126 return -err;
127
128 case -EFAULT: /* Must have been caused by a glibc or application bug. */
129 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
130 being normalized. Must have been caused by a glibc or
131 application bug. */
132 case -ENOSYS: /* Must have been caused by a glibc bug. */
133 /* No other errors are documented at this time. */
134 default:
135 futex_fatal_error ();
136 }
137}
138
139/* See sysdeps/nptl/futex-internal.h for details. */
140static __always_inline int
141futex_reltimed_wait_cancelable (unsigned int *futex_word,
142 unsigned int expected,
143 const struct timespec *reltime, int private)
144{
145 int oldtype;
146 oldtype = __pthread_enable_asynccancel ();
147 int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
148 __pthread_disable_asynccancel (oldtype);
149 switch (err)
150 {
151 case 0:
152 case -EAGAIN:
153 case -EINTR:
154 case -ETIMEDOUT:
155 return -err;
156
157 case -EFAULT: /* Must have been caused by a glibc or application bug. */
158 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
159 being normalized. Must have been caused by a glibc or
160 application bug. */
161 case -ENOSYS: /* Must have been caused by a glibc bug. */
162 /* No other errors are documented at this time. */
163 default:
164 futex_fatal_error ();
165 }
166}
167
168/* See sysdeps/nptl/futex-internal.h for details. */
169static __always_inline int
170futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
171 const struct timespec *abstime, int private)
172{
173 int err = __nacl_irt_futex.futex_wait_abs ((volatile int *) futex_word,
174 expected, abstime);
175 switch (err)
176 {
177 case 0:
178 case EAGAIN:
179 case EINTR:
180 case ETIMEDOUT:
181 return err;
182
183 case EFAULT: /* Must have been caused by a glibc or application bug. */
184 case EINVAL: /* Either due to wrong alignment or due to the timeout not
185 being normalized. Must have been caused by a glibc or
186 application bug. */
187 case ENOSYS: /* Must have been caused by a glibc bug. */
188 /* No other errors are documented at this time. */
189 default:
190 futex_fatal_error ();
191 }
192}
193
194/* See sysdeps/nptl/futex-internal.h for details. */
195static __always_inline int
196futex_abstimed_wait_cancelable (unsigned int *futex_word,
197 unsigned int expected,
198 const struct timespec *abstime, int private)
199{
200 int oldtype;
201 oldtype = __pthread_enable_asynccancel ();
202 int err = __nacl_irt_futex.futex_wait_abs ((volatile int *) futex_word,
203 expected, abstime);
204 __pthread_disable_asynccancel (oldtype);
205 switch (err)
206 {
207 case 0:
208 case EAGAIN:
209 case EINTR:
210 case ETIMEDOUT:
211 return err;
212
213 case EFAULT: /* Must have been caused by a glibc or application bug. */
214 case EINVAL: /* Either due to wrong alignment or due to the timeout not
215 being normalized. Must have been caused by a glibc or
216 application bug. */
217 case ENOSYS: /* Must have been caused by a glibc bug. */
218 /* No other errors are documented at this time. */
219 default:
220 futex_fatal_error ();
221 }
222}
223
224/* See sysdeps/nptl/futex-internal.h for details. */
225static __always_inline void
226futex_wake (unsigned int *futex_word, int processes_to_wake, int private)
227{
228 int res = lll_futex_wake (futex_word, processes_to_wake, private);
229 /* No error. Ignore the number of woken processes. */
230 if (res >= 0)
231 return;
232 switch (res)
233 {
234 case -EFAULT: /* Could have happened due to memory reuse. */
235 case -EINVAL: /* Could be either due to incorrect alignment (a bug in
236 glibc or in the application) or due to memory being
237 reused for a PI futex. We cannot distinguish between the
238 two causes, and one of them is correct use, so we do not
239 act in this case. */
240 return;
241 case -ENOSYS: /* Must have been caused by a glibc bug. */
242 /* No other errors are documented at this time. */
243 default:
244 futex_fatal_error ();
245 }
246}
247
248#endif /* futex-internal.h */