pthread_mutex_trylock.c raw

   1  #include "pthread_impl.h"
   2  
   3  int __pthread_mutex_trylock_owner(pthread_mutex_t *m)
   4  {
   5  	int old, own;
   6  	int type = m->_m_type;
   7  	pthread_t self = __pthread_self();
   8  	int tid = self->tid;
   9  
  10  	old = m->_m_lock;
  11  	own = old & 0x3fffffff;
  12  	if (own == tid) {
  13  		if ((type&8) && m->_m_count<0) {
  14  			old &= 0x40000000;
  15  			m->_m_count = 0;
  16  			goto success;
  17  		}
  18  		if ((type&3) == PTHREAD_MUTEX_RECURSIVE) {
  19  			if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
  20  			m->_m_count++;
  21  			return 0;
  22  		}
  23  	}
  24  	if (own == 0x3fffffff) return ENOTRECOVERABLE;
  25  	if (own || (old && !(type & 4))) return EBUSY;
  26  
  27  	if (type & 128) {
  28  		if (!self->robust_list.off) {
  29  			self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next;
  30  			__syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long));
  31  		}
  32  		if (m->_m_waiters) tid |= 0x80000000;
  33  		self->robust_list.pending = &m->_m_next;
  34  	}
  35  	tid |= old & 0x40000000;
  36  
  37  	if (a_cas(&m->_m_lock, old, tid) != old) {
  38  		self->robust_list.pending = 0;
  39  		if ((type&12)==12 && m->_m_waiters) return ENOTRECOVERABLE;
  40  		return EBUSY;
  41  	}
  42  
  43  success:
  44  	if ((type&8) && m->_m_waiters) {
  45  		int priv = (type & 128) ^ 128;
  46  		__syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
  47  		self->robust_list.pending = 0;
  48  		return (type&4) ? ENOTRECOVERABLE : EBUSY;
  49  	}
  50  
  51  	volatile void *next = self->robust_list.head;
  52  	m->_m_next = next;
  53  	m->_m_prev = &self->robust_list.head;
  54  	if (next != &self->robust_list.head) *(volatile void *volatile *)
  55  		((char *)next - sizeof(void *)) = &m->_m_next;
  56  	self->robust_list.head = &m->_m_next;
  57  	self->robust_list.pending = 0;
  58  
  59  	if (old) {
  60  		m->_m_count = 0;
  61  		return EOWNERDEAD;
  62  	}
  63  
  64  	return 0;
  65  }
  66  
  67  int __pthread_mutex_trylock(pthread_mutex_t *m)
  68  {
  69  	if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL)
  70  		return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY;
  71  	return __pthread_mutex_trylock_owner(m);
  72  }
  73  
  74  weak_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
  75