1 #include "threads_impl.h"
2 
pthread_mutex_timedlock(pthread_mutex_t * restrict m,const struct timespec * restrict at)3 int pthread_mutex_timedlock(pthread_mutex_t* restrict m, const struct timespec* restrict at) {
4     if ((m->_m_type & PTHREAD_MUTEX_MASK) == PTHREAD_MUTEX_NORMAL &&
5         !a_cas_shim(&m->_m_lock, 0, EBUSY))
6         return 0;
7 
8     int r, t;
9 
10     r = pthread_mutex_trylock(m);
11     if (r != EBUSY)
12         return r;
13 
14     int spins = 100;
15     while (spins-- && atomic_load(&m->_m_lock) && !atomic_load(&m->_m_waiters))
16         a_spin();
17 
18     while ((r = pthread_mutex_trylock(m)) == EBUSY) {
19         if (!(r = atomic_load(&m->_m_lock)))
20             continue;
21         if ((m->_m_type & PTHREAD_MUTEX_MASK) == PTHREAD_MUTEX_ERRORCHECK &&
22             (r & PTHREAD_MUTEX_OWNED_LOCK_MASK) == __thread_get_tid())
23             return EDEADLK;
24 
25         atomic_fetch_add(&m->_m_waiters, 1);
26         t = r | PTHREAD_MUTEX_OWNED_LOCK_BIT;
27         a_cas_shim(&m->_m_lock, r, t);
28         r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at);
29         atomic_fetch_sub(&m->_m_waiters, 1);
30         if (r)
31             break;
32     }
33     return r;
34 }
35