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