1 #include "pthread_impl.h"
3 #define IS32BIT(x) !((x)+0x80000000ULL>>32)
4 #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
6 static int __futex4(volatile void *addr
, int op
, int val
, const struct timespec
*to
)
8 #ifdef SYS_futex_time64
9 time_t s
= to
? to
->tv_sec
: 0;
10 long ns
= to
? to
->tv_nsec
: 0;
12 if (SYS_futex
== SYS_futex_time64
|| !IS32BIT(s
))
13 r
= __syscall(SYS_futex_time64
, addr
, op
, val
,
14 to
? ((long long[]){s
, ns
}) : 0);
15 if (SYS_futex
== SYS_futex_time64
|| r
!=-ENOSYS
) return r
;
16 to
= to
? (void *)(long[]){CLAMP(s
), ns
} : 0;
18 return __syscall(SYS_futex
, addr
, op
, val
, to
);
21 static int pthread_mutex_timedlock_pi(pthread_mutex_t
*restrict m
, const struct timespec
*restrict at
)
23 int type
= m
->_m_type
;
24 int priv
= (type
& 128) ^ 128;
25 pthread_t self
= __pthread_self();
28 if (!priv
) self
->robust_list
.pending
= &m
->_m_next
;
30 do e
= -__futex4(&m
->_m_lock
, FUTEX_LOCK_PI
|priv
, 0, at
);
32 if (e
) self
->robust_list
.pending
= 0;
36 /* Catch spurious success for non-robust mutexes. */
37 if (!(type
&4) && ((m
->_m_lock
& 0x40000000) || m
->_m_waiters
)) {
38 a_store(&m
->_m_waiters
, -1);
39 __syscall(SYS_futex
, &m
->_m_lock
, FUTEX_UNLOCK_PI
|priv
);
40 self
->robust_list
.pending
= 0;
43 /* Signal to trylock that we already have the lock. */
45 return __pthread_mutex_trylock(m
);
49 if ((type
&3) == PTHREAD_MUTEX_ERRORCHECK
) return e
;
51 do e
= __timedwait(&(int){0}, 0, CLOCK_REALTIME
, at
, 1);
52 while (e
!= ETIMEDOUT
);
56 int __pthread_mutex_timedlock(pthread_mutex_t
*restrict m
, const struct timespec
*restrict at
)
58 if ((m
->_m_type
&15) == PTHREAD_MUTEX_NORMAL
59 && !a_cas(&m
->_m_lock
, 0, EBUSY
))
62 int type
= m
->_m_type
;
63 int r
, t
, priv
= (type
& 128) ^ 128;
65 r
= __pthread_mutex_trylock(m
);
66 if (r
!= EBUSY
) return r
;
68 if (type
&8) return pthread_mutex_timedlock_pi(m
, at
);
71 while (spins
-- && m
->_m_lock
&& !m
->_m_waiters
) a_spin();
73 while ((r
=__pthread_mutex_trylock(m
)) == EBUSY
) {
75 int own
= r
& 0x3fffffff;
76 if (!own
&& (!r
|| (type
&4)))
78 if ((type
&3) == PTHREAD_MUTEX_ERRORCHECK
79 && own
== __pthread_self()->tid
)
82 a_inc(&m
->_m_waiters
);
84 a_cas(&m
->_m_lock
, r
, t
);
85 r
= __timedwait(&m
->_m_lock
, t
, CLOCK_REALTIME
, at
, priv
);
86 a_dec(&m
->_m_waiters
);
87 if (r
&& r
!= EINTR
) break;
92 weak_alias(__pthread_mutex_timedlock
, pthread_mutex_timedlock
);