6 #include "pthread_impl.h"
8 #define IS32BIT(x) !((x)+0x80000000ULL>>32)
9 #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
11 static int __futex4_cp(volatile void *addr
, int op
, int val
, const struct timespec
*to
)
14 #ifdef SYS_futex_time64
15 time_t s
= to
? to
->tv_sec
: 0;
16 long ns
= to
? to
->tv_nsec
: 0;
18 if (SYS_futex
== SYS_futex_time64
|| !IS32BIT(s
))
19 r
= __syscall_cp(SYS_futex_time64
, addr
, op
, val
,
20 to
? ((long long[]){s
, ns
}) : 0);
21 if (SYS_futex
== SYS_futex_time64
|| r
!=-ENOSYS
) return r
;
22 to
= to
? (void *)(long[]){CLAMP(s
), ns
} : 0;
24 r
= __syscall_cp(SYS_futex
, addr
, op
, val
, to
);
25 if (r
!= -ENOSYS
) return r
;
26 return __syscall_cp(SYS_futex
, addr
, op
& ~FUTEX_PRIVATE
, val
, to
);
29 static volatile int dummy
= 0;
30 weak_alias(dummy
, __eintr_valid_flag
);
32 int __timedwait_cp(volatile int *addr
, int val
,
33 clockid_t clk
, const struct timespec
*at
, int priv
)
36 struct timespec to
, *top
=0;
38 if (priv
) priv
= FUTEX_PRIVATE
;
41 if (at
->tv_nsec
>= 1000000000UL) return EINVAL
;
42 if (__clock_gettime(clk
, &to
)) return EINVAL
;
43 to
.tv_sec
= at
->tv_sec
- to
.tv_sec
;
44 if ((to
.tv_nsec
= at
->tv_nsec
- to
.tv_nsec
) < 0) {
46 to
.tv_nsec
+= 1000000000;
48 if (to
.tv_sec
< 0) return ETIMEDOUT
;
52 r
= -__futex4_cp(addr
, FUTEX_WAIT
|priv
, val
, top
);
53 if (r
!= EINTR
&& r
!= ETIMEDOUT
&& r
!= ECANCELED
) r
= 0;
54 /* Mitigate bug in old kernels wrongly reporting EINTR for non-
55 * interrupting (SA_RESTART) signal handlers. This is only practical
56 * when NO interrupting signal handlers have been installed, and
57 * works by sigaction tracking whether that's the case. */
58 if (r
== EINTR
&& !__eintr_valid_flag
) r
= 0;
63 int __timedwait(volatile int *addr
, int val
,
64 clockid_t clk
, const struct timespec
*at
, int priv
)
67 __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cs
);
68 r
= __timedwait_cp(addr
, val
, clk
, at
, priv
);
69 __pthread_setcancelstate(cs
, 0);