]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/futex-internal.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / futex-internal.h
1 /* futex operations for glibc-internal use. Linux version.
2 Copyright (C) 2014-2016 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 <nptl/pthreadP.h>
26
27 /* See sysdeps/nptl/futex-internal.h for documentation; this file only
28 contains Linux-specific comments.
29
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.
33
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). */
36
37 /* FUTEX_SHARED is always supported by the Linux kernel. */
38 static __always_inline int
39 futex_supports_pshared (int pshared)
40 {
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;
47 }
48
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)
53 {
54 return true;
55 }
56
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)
60 {
61 int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
62 switch (err)
63 {
64 case 0:
65 case -EAGAIN:
66 case -EINTR:
67 return -err;
68
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 ();
78 }
79 }
80
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)
85 {
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)
91 {
92 case 0:
93 case -EAGAIN:
94 case -EINTR:
95 return -err;
96
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 ();
106 }
107 }
108
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)
113 {
114 int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
115 switch (err)
116 {
117 case 0:
118 case -EAGAIN:
119 case -EINTR:
120 case -ETIMEDOUT:
121 return -err;
122
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 ();
131 }
132 }
133
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)
139 {
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)
145 {
146 case 0:
147 case -EAGAIN:
148 case -EINTR:
149 case -ETIMEDOUT:
150 return -err;
151
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 ();
160 }
161 }
162
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)
167 {
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)
175 {
176 case 0:
177 case -EAGAIN:
178 case -EINTR:
179 case -ETIMEDOUT:
180 return -err;
181
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 ();
190 }
191 }
192
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)
198 {
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)
209 {
210 case 0:
211 case -EAGAIN:
212 case -EINTR:
213 case -ETIMEDOUT:
214 return -err;
215
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 ();
224 }
225 }
226
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)
230 {
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)
236 {
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 ();
248 }
249 }
250
251 #endif /* futex-internal.h */