pthread_mutex_trylock.c 1.8 KB

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