1 /* futex helper functions for glibc-internal use.
2 Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>. */
22 #include <futex-internal.h>
23 #include <kernel-features.h>
25 #ifndef __ASSUME_TIME64_SYSCALLS
27 __futex_abstimed_wait_common32 (unsigned int* futex_word
,
28 unsigned int expected
, int op
,
29 const struct __timespec64
* abstime
,
30 int private, bool cancel
)
32 struct timespec ts32
, *pts32
= NULL
;
35 ts32
= valid_timespec64_to_timespec (*abstime
);
40 return INTERNAL_SYSCALL_CANCEL (futex
, futex_word
, op
, expected
,
41 pts32
, NULL
/* Unused. */,
42 FUTEX_BITSET_MATCH_ANY
);
44 return INTERNAL_SYSCALL_CALL (futex
, futex_word
, op
, expected
,
45 pts32
, NULL
/* Unused. */,
46 FUTEX_BITSET_MATCH_ANY
);
48 #endif /* ! __ASSUME_TIME64_SYSCALLS */
51 __futex_abstimed_wait_common64 (unsigned int* futex_word
,
52 unsigned int expected
, int op
,
53 const struct __timespec64
* abstime
,
54 int private, bool cancel
)
57 return INTERNAL_SYSCALL_CANCEL (futex_time64
, futex_word
, op
, expected
,
58 abstime
, NULL
/* Unused. */,
59 FUTEX_BITSET_MATCH_ANY
);
61 return INTERNAL_SYSCALL_CALL (futex_time64
, futex_word
, op
, expected
,
62 abstime
, NULL
/* Ununsed. */,
63 FUTEX_BITSET_MATCH_ANY
);
67 __futex_abstimed_wait_common (unsigned int* futex_word
,
68 unsigned int expected
, clockid_t clockid
,
69 const struct __timespec64
* abstime
,
70 int private, bool cancel
)
73 unsigned int clockbit
;
75 /* Work around the fact that the kernel rejects negative timeout values
76 despite them being valid. */
77 if (__glibc_unlikely ((abstime
!= NULL
) && (abstime
->tv_sec
< 0)))
80 if (! lll_futex_supported_clockid (clockid
))
83 clockbit
= (clockid
== CLOCK_REALTIME
) ? FUTEX_CLOCK_REALTIME
: 0;
84 int op
= __lll_private_flag (FUTEX_WAIT_BITSET
| clockbit
, private);
86 #ifdef __ASSUME_TIME64_SYSCALLS
87 err
= __futex_abstimed_wait_common64 (futex_word
, expected
, op
, abstime
,
90 bool need_time64
= abstime
!= NULL
&& !in_time_t_range (abstime
->tv_sec
);
93 err
= __futex_abstimed_wait_common64 (futex_word
, expected
, op
, abstime
,
99 err
= __futex_abstimed_wait_common32 (futex_word
, expected
, op
, abstime
,
110 case -EOVERFLOW
: /* Passed absolute timeout uses 64 bit time_t type, but
111 underlying kernel does not support 64 bit time_t futex
115 case -EFAULT
: /* Must have been caused by a glibc or application bug. */
116 case -ENOSYS
: /* Must have been caused by a glibc bug. */
117 /* No other errors are documented at this time. */
119 futex_fatal_error ();
124 __futex_abstimed_wait64 (unsigned int* futex_word
, unsigned int expected
,
126 const struct __timespec64
* abstime
, int private)
128 return __futex_abstimed_wait_common (futex_word
, expected
, clockid
,
129 abstime
, private, false);
131 libc_hidden_def (__futex_abstimed_wait64
)
134 __futex_abstimed_wait_cancelable64 (unsigned int* futex_word
,
135 unsigned int expected
, clockid_t clockid
,
136 const struct __timespec64
* abstime
,
139 return __futex_abstimed_wait_common (futex_word
, expected
, clockid
,
140 abstime
, private, true);
142 libc_hidden_def (__futex_abstimed_wait_cancelable64
)
145 __futex_lock_pi64 (int *futex_word
, clockid_t clockid
,
146 const struct __timespec64
*abstime
, int private)
150 unsigned int clockbit
= clockid
== CLOCK_REALTIME
151 ? FUTEX_CLOCK_REALTIME
: 0;
152 int op_pi2
= __lll_private_flag (FUTEX_LOCK_PI2
| clockbit
, private);
153 #if __ASSUME_FUTEX_LOCK_PI2
154 /* Assume __ASSUME_TIME64_SYSCALLS since FUTEX_LOCK_PI2 was added later. */
155 err
= INTERNAL_SYSCALL_CALL (futex_time64
, futex_word
, op_pi2
, 0, abstime
);
157 /* FUTEX_LOCK_PI does not support clock selection, so for CLOCK_MONOTONIC
158 the only option is to use FUTEX_LOCK_PI2. */
159 int op_pi1
= __lll_private_flag (FUTEX_LOCK_PI
, private);
160 int op_pi
= abstime
!= NULL
&& clockid
!= CLOCK_REALTIME
? op_pi2
: op_pi1
;
162 # ifdef __ASSUME_TIME64_SYSCALLS
163 err
= INTERNAL_SYSCALL_CALL (futex_time64
, futex_word
, op_pi
, 0, abstime
);
165 bool need_time64
= abstime
!= NULL
&& !in_time_t_range (abstime
->tv_sec
);
167 err
= INTERNAL_SYSCALL_CALL (futex_time64
, futex_word
, op_pi
, 0, abstime
);
170 struct timespec ts32
, *pts32
= NULL
;
173 ts32
= valid_timespec64_to_timespec (*abstime
);
176 err
= INTERNAL_SYSCALL_CALL (futex
, futex_word
, op_pi
, 0, pts32
);
178 # endif /* __ASSUME_TIME64_SYSCALLS */
179 /* FUTEX_LOCK_PI2 is not available on this kernel. */
182 #endif /* __ASSUME_FUTEX_LOCK_PI2 */
192 case -EINVAL
: /* This indicates either state corruption or that the kernel
193 found a waiter on futex address which is waiting via
194 FUTEX_WAIT or FUTEX_WAIT_BITSET. This is reported on
195 some futex_lock_pi usage (pthread_mutex_timedlock for
199 case -EFAULT
: /* Must have been caused by a glibc or application bug. */
200 case -ENOSYS
: /* Must have been caused by a glibc bug. */
201 /* No other errors are documented at this time. */
203 futex_fatal_error ();