1 #include "pthread_impl.h"
3 #ifdef __wasilibc_unmodified_upstream
4 #define IS32BIT(x) !((x)+0x80000000ULL>>32)
5 #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
7 static int __futex4(volatile void *addr
, int op
, int val
, const struct timespec
*to
)
9 #ifdef SYS_futex_time64
10 time_t s
= to
? to
->tv_sec
: 0;
11 long ns
= to
? to
->tv_nsec
: 0;
13 if (SYS_futex
== SYS_futex_time64
|| !IS32BIT(s
))
14 r
= __syscall(SYS_futex_time64
, addr
, op
, val
,
15 to
? ((long long[]){s
, ns
}) : 0);
16 if (SYS_futex
== SYS_futex_time64
|| r
!=-ENOSYS
) return r
;
17 to
= to
? (void *)(long[]){CLAMP(s
), ns
} : 0;
19 return __syscall(SYS_futex
, addr
, op
, val
, to
);
22 static int pthread_mutex_timedlock_pi(pthread_mutex_t
*restrict m
, const struct timespec
*restrict at
)
24 int type
= m
->_m_type
;
25 int priv
= (type
& 128) ^ 128;
26 pthread_t self
= __pthread_self();
29 if (!priv
) self
->robust_list
.pending
= &m
->_m_next
;
31 do e
= -__futex4(&m
->_m_lock
, FUTEX_LOCK_PI
|priv
, 0, at
);
33 if (e
) self
->robust_list
.pending
= 0;
37 /* Catch spurious success for non-robust mutexes. */
38 if (!(type
&4) && ((m
->_m_lock
& 0x40000000) || m
->_m_waiters
)) {
39 a_store(&m
->_m_waiters
, -1);
40 __syscall(SYS_futex
, &m
->_m_lock
, FUTEX_UNLOCK_PI
|priv
);
41 self
->robust_list
.pending
= 0;
44 /* Signal to trylock that we already have the lock. */
46 return __pthread_mutex_trylock(m
);
50 if ((type
&3) == PTHREAD_MUTEX_ERRORCHECK
) return e
;
52 do e
= __timedwait(&(int){0}, 0, CLOCK_REALTIME
, at
, 1);
53 while (e
!= ETIMEDOUT
);
58 int __pthread_mutex_timedlock(pthread_mutex_t
*restrict m
, const struct timespec
*restrict at
)
60 if ((m
->_m_type
&15) == PTHREAD_MUTEX_NORMAL
61 && !a_cas(&m
->_m_lock
, 0, EBUSY
))
64 int type
= m
->_m_type
;
65 int r
, t
, priv
= (type
& 128) ^ 128;
67 r
= __pthread_mutex_trylock(m
);
68 if (r
!= EBUSY
) return r
;
70 #ifdef __wasilibc_unmodified_upstream
71 if (type
&8) return pthread_mutex_timedlock_pi(m
, at
);
75 while (spins
-- && m
->_m_lock
&& !m
->_m_waiters
) a_spin();
77 while ((r
=__pthread_mutex_trylock(m
)) == EBUSY
) {
79 int own
= r
& 0x3fffffff;
80 if (!own
&& (!r
|| (type
&4)))
82 if ((type
&3) == PTHREAD_MUTEX_ERRORCHECK
83 && own
== __pthread_self()->tid
)
86 a_inc(&m
->_m_waiters
);
88 a_cas(&m
->_m_lock
, r
, t
);
89 r
= __timedwait(&m
->_m_lock
, t
, CLOCK_REALTIME
, at
, priv
);
90 a_dec(&m
->_m_waiters
);
91 if (r
&& r
!= EINTR
) break;
96 weak_alias(__pthread_mutex_timedlock
, pthread_mutex_timedlock
);