Add NT_PPC_PKEY from Linux 4.16 to elf.h.
[glibc.git] / sysdeps / unix / sysv / linux / futex-internal.h
blob96a07b05b9fc553f2f4e2bb0420045e1cb020758
1 /* futex operations for glibc-internal use. Linux version.
2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #ifndef FUTEX_INTERNAL_H
20 #define FUTEX_INTERNAL_H
22 #include <sysdeps/nptl/futex-internal.h>
23 #include <errno.h>
24 #include <lowlevellock-futex.h>
25 #include <nptl/pthreadP.h>
27 /* See sysdeps/nptl/futex-internal.h for documentation; this file only
28 contains Linux-specific comments.
30 The Linux kernel treats provides absolute timeouts based on the
31 CLOCK_REALTIME clock and relative timeouts measured against the
32 CLOCK_MONOTONIC clock.
34 We expect a Linux kernel version of 2.6.22 or more recent (since this
35 version, EINTR is not returned on spurious wake-ups anymore). */
37 /* FUTEX_SHARED is always supported by the Linux kernel. */
38 static __always_inline int
39 futex_supports_pshared (int pshared)
41 if (__glibc_likely (pshared == PTHREAD_PROCESS_PRIVATE))
42 return 0;
43 else if (pshared == PTHREAD_PROCESS_SHARED)
44 return 0;
45 else
46 return EINVAL;
49 /* The Linux kernel supports relative timeouts measured against the
50 CLOCK_MONOTONIC clock. */
51 static __always_inline bool
52 futex_supports_exact_relative_timeouts (void)
54 return true;
57 /* See sysdeps/nptl/futex-internal.h for details. */
58 static __always_inline int
59 futex_wait (unsigned int *futex_word, unsigned int expected, int private)
61 int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
62 switch (err)
64 case 0:
65 case -EAGAIN:
66 case -EINTR:
67 return -err;
69 case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
70 case -EFAULT: /* Must have been caused by a glibc or application bug. */
71 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
72 being normalized. Must have been caused by a glibc or
73 application bug. */
74 case -ENOSYS: /* Must have been caused by a glibc bug. */
75 /* No other errors are documented at this time. */
76 default:
77 futex_fatal_error ();
81 /* See sysdeps/nptl/futex-internal.h for details. */
82 static __always_inline int
83 futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
84 int private)
86 int oldtype;
87 oldtype = __pthread_enable_asynccancel ();
88 int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
89 __pthread_disable_asynccancel (oldtype);
90 switch (err)
92 case 0:
93 case -EAGAIN:
94 case -EINTR:
95 return -err;
97 case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
98 case -EFAULT: /* Must have been caused by a glibc or application bug. */
99 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
100 being normalized. Must have been caused by a glibc or
101 application bug. */
102 case -ENOSYS: /* Must have been caused by a glibc bug. */
103 /* No other errors are documented at this time. */
104 default:
105 futex_fatal_error ();
109 /* See sysdeps/nptl/futex-internal.h for details. */
110 static __always_inline int
111 futex_reltimed_wait (unsigned int *futex_word, unsigned int expected,
112 const struct timespec *reltime, int private)
114 int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
115 switch (err)
117 case 0:
118 case -EAGAIN:
119 case -EINTR:
120 case -ETIMEDOUT:
121 return -err;
123 case -EFAULT: /* Must have been caused by a glibc or application bug. */
124 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
125 being normalized. Must have been caused by a glibc or
126 application bug. */
127 case -ENOSYS: /* Must have been caused by a glibc bug. */
128 /* No other errors are documented at this time. */
129 default:
130 futex_fatal_error ();
134 /* See sysdeps/nptl/futex-internal.h for details. */
135 static __always_inline int
136 futex_reltimed_wait_cancelable (unsigned int *futex_word,
137 unsigned int expected,
138 const struct timespec *reltime, int private)
140 int oldtype;
141 oldtype = __pthread_enable_asynccancel ();
142 int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
143 __pthread_disable_asynccancel (oldtype);
144 switch (err)
146 case 0:
147 case -EAGAIN:
148 case -EINTR:
149 case -ETIMEDOUT:
150 return -err;
152 case -EFAULT: /* Must have been caused by a glibc or application bug. */
153 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
154 being normalized. Must have been caused by a glibc or
155 application bug. */
156 case -ENOSYS: /* Must have been caused by a glibc bug. */
157 /* No other errors are documented at this time. */
158 default:
159 futex_fatal_error ();
163 /* See sysdeps/nptl/futex-internal.h for details. */
164 static __always_inline int
165 futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
166 const struct timespec *abstime, int private)
168 /* Work around the fact that the kernel rejects negative timeout values
169 despite them being valid. */
170 if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
171 return ETIMEDOUT;
172 int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
173 FUTEX_CLOCK_REALTIME, private);
174 switch (err)
176 case 0:
177 case -EAGAIN:
178 case -EINTR:
179 case -ETIMEDOUT:
180 return -err;
182 case -EFAULT: /* Must have been caused by a glibc or application bug. */
183 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
184 being normalized. Must have been caused by a glibc or
185 application bug. */
186 case -ENOSYS: /* Must have been caused by a glibc bug. */
187 /* No other errors are documented at this time. */
188 default:
189 futex_fatal_error ();
193 /* See sysdeps/nptl/futex-internal.h for details. */
194 static __always_inline int
195 futex_abstimed_wait_cancelable (unsigned int *futex_word,
196 unsigned int expected,
197 const struct timespec *abstime, int private)
199 /* Work around the fact that the kernel rejects negative timeout values
200 despite them being valid. */
201 if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
202 return ETIMEDOUT;
203 int oldtype;
204 oldtype = __pthread_enable_asynccancel ();
205 int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
206 FUTEX_CLOCK_REALTIME, private);
207 __pthread_disable_asynccancel (oldtype);
208 switch (err)
210 case 0:
211 case -EAGAIN:
212 case -EINTR:
213 case -ETIMEDOUT:
214 return -err;
216 case -EFAULT: /* Must have been caused by a glibc or application bug. */
217 case -EINVAL: /* Either due to wrong alignment or due to the timeout not
218 being normalized. Must have been caused by a glibc or
219 application bug. */
220 case -ENOSYS: /* Must have been caused by a glibc bug. */
221 /* No other errors are documented at this time. */
222 default:
223 futex_fatal_error ();
227 /* See sysdeps/nptl/futex-internal.h for details. */
228 static __always_inline void
229 futex_wake (unsigned int *futex_word, int processes_to_wake, int private)
231 int res = lll_futex_wake (futex_word, processes_to_wake, private);
232 /* No error. Ignore the number of woken processes. */
233 if (res >= 0)
234 return;
235 switch (res)
237 case -EFAULT: /* Could have happened due to memory reuse. */
238 case -EINVAL: /* Could be either due to incorrect alignment (a bug in
239 glibc or in the application) or due to memory being
240 reused for a PI futex. We cannot distinguish between the
241 two causes, and one of them is correct use, so we do not
242 act in this case. */
243 return;
244 case -ENOSYS: /* Must have been caused by a glibc bug. */
245 /* No other errors are documented at this time. */
246 default:
247 futex_fatal_error ();
251 #endif /* futex-internal.h */