Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 1 | #include "pthread_impl.h" |
2 | |||||
Rich Felker | da8d0fc | 2012-08-17 17:13:53 -0400 | [diff] [blame] | 3 | void __vm_lock_impl(int); |
4 | void __vm_unlock_impl(void); | ||||
5 | |||||
Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 6 | int pthread_mutex_unlock(pthread_mutex_t *m) |
7 | { | ||||
Rich Felker | 047e434 | 2011-03-17 20:41:37 -0400 | [diff] [blame] | 8 | pthread_t self; |
Rich Felker | c68de0b | 2011-08-02 20:31:15 -0400 | [diff] [blame] | 9 | int waiters = m->_m_waiters; |
10 | int cont; | ||||
Rich Felker | bc09d58 | 2014-08-15 23:54:52 -0400 | [diff] [blame] | 11 | int type = m->_m_type & 15; |
12 | int priv = (m->_m_type & 128) ^ 128; | ||||
Rich Felker | 047e434 | 2011-03-17 20:41:37 -0400 | [diff] [blame] | 13 | |
Rich Felker | bc09d58 | 2014-08-15 23:54:52 -0400 | [diff] [blame] | 14 | if (type != PTHREAD_MUTEX_NORMAL) { |
Rich Felker | a1eb8cb | 2011-03-30 10:32:45 -0400 | [diff] [blame] | 15 | if (!m->_m_lock) |
16 | return EPERM; | ||||
Rich Felker | df15168 | 2014-06-10 04:02:40 -0400 | [diff] [blame] | 17 | self = __pthread_self(); |
Rich Felker | fffc5cd | 2014-08-16 19:15:19 -0400 | [diff] [blame^] | 18 | if ((m->_m_lock&0x7fffffff) != self->tid) |
Rich Felker | a1eb8cb | 2011-03-30 10:32:45 -0400 | [diff] [blame] | 19 | return EPERM; |
Rich Felker | bc09d58 | 2014-08-15 23:54:52 -0400 | [diff] [blame] | 20 | if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) |
Rich Felker | 7fe58d3 | 2011-10-03 00:09:08 -0400 | [diff] [blame] | 21 | return m->_m_count--, 0; |
Rich Felker | fffc5cd | 2014-08-16 19:15:19 -0400 | [diff] [blame^] | 22 | if (!priv) { |
Rich Felker | 047e434 | 2011-03-17 20:41:37 -0400 | [diff] [blame] | 23 | self->robust_list.pending = &m->_m_next; |
Rich Felker | da8d0fc | 2012-08-17 17:13:53 -0400 | [diff] [blame] | 24 | __vm_lock_impl(+1); |
Rich Felker | 047e434 | 2011-03-17 20:41:37 -0400 | [diff] [blame] | 25 | } |
Rich Felker | fffc5cd | 2014-08-16 19:15:19 -0400 | [diff] [blame^] | 26 | *(void **)m->_m_prev = m->_m_next; |
27 | if (m->_m_next) ((void **)m->_m_next)[-1] = m->_m_prev; | ||||
Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 28 | } |
Rich Felker | c68de0b | 2011-08-02 20:31:15 -0400 | [diff] [blame] | 29 | cont = a_swap(&m->_m_lock, 0); |
Rich Felker | fffc5cd | 2014-08-16 19:15:19 -0400 | [diff] [blame^] | 30 | if (type != PTHREAD_MUTEX_NORMAL && !priv) { |
Rich Felker | b6f9974 | 2011-10-03 00:19:05 -0400 | [diff] [blame] | 31 | self->robust_list.pending = 0; |
Rich Felker | da8d0fc | 2012-08-17 17:13:53 -0400 | [diff] [blame] | 32 | __vm_unlock_impl(); |
33 | } | ||||
Rich Felker | c68de0b | 2011-08-02 20:31:15 -0400 | [diff] [blame] | 34 | if (waiters || cont<0) |
Rich Felker | bc09d58 | 2014-08-15 23:54:52 -0400 | [diff] [blame] | 35 | __wake(&m->_m_lock, 1, priv); |
Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 36 | return 0; |
37 | } |