blob: b4ed3f876def83ba826ebe32c2766cf01e91da49 [file] [log] [blame]
Rich Felker0b44a032011-02-12 00:22:29 -05001#include "pthread_impl.h"
2
Rich Felkerda8d0fc2012-08-17 17:13:53 -04003void __vm_lock_impl(int);
4void __vm_unlock_impl(void);
5
Rich Felker0b44a032011-02-12 00:22:29 -05006int pthread_mutex_unlock(pthread_mutex_t *m)
7{
Rich Felker047e4342011-03-17 20:41:37 -04008 pthread_t self;
Rich Felkerc68de0b2011-08-02 20:31:15 -04009 int waiters = m->_m_waiters;
10 int cont;
Rich Felkerbc09d582014-08-15 23:54:52 -040011 int type = m->_m_type & 15;
12 int priv = (m->_m_type & 128) ^ 128;
Rich Felker047e4342011-03-17 20:41:37 -040013
Rich Felkerbc09d582014-08-15 23:54:52 -040014 if (type != PTHREAD_MUTEX_NORMAL) {
Rich Felkera1eb8cb2011-03-30 10:32:45 -040015 if (!m->_m_lock)
16 return EPERM;
Rich Felkerdf151682014-06-10 04:02:40 -040017 self = __pthread_self();
Rich Felkerfffc5cd2014-08-16 19:15:19 -040018 if ((m->_m_lock&0x7fffffff) != self->tid)
Rich Felkera1eb8cb2011-03-30 10:32:45 -040019 return EPERM;
Rich Felkerbc09d582014-08-15 23:54:52 -040020 if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count)
Rich Felker7fe58d32011-10-03 00:09:08 -040021 return m->_m_count--, 0;
Rich Felkerfffc5cd2014-08-16 19:15:19 -040022 if (!priv) {
Rich Felker047e4342011-03-17 20:41:37 -040023 self->robust_list.pending = &m->_m_next;
Rich Felkerda8d0fc2012-08-17 17:13:53 -040024 __vm_lock_impl(+1);
Rich Felker047e4342011-03-17 20:41:37 -040025 }
Rich Felkerfffc5cd2014-08-16 19:15:19 -040026 *(void **)m->_m_prev = m->_m_next;
27 if (m->_m_next) ((void **)m->_m_next)[-1] = m->_m_prev;
Rich Felker0b44a032011-02-12 00:22:29 -050028 }
Rich Felkerc68de0b2011-08-02 20:31:15 -040029 cont = a_swap(&m->_m_lock, 0);
Rich Felkerfffc5cd2014-08-16 19:15:19 -040030 if (type != PTHREAD_MUTEX_NORMAL && !priv) {
Rich Felkerb6f99742011-10-03 00:19:05 -040031 self->robust_list.pending = 0;
Rich Felkerda8d0fc2012-08-17 17:13:53 -040032 __vm_unlock_impl();
33 }
Rich Felkerc68de0b2011-08-02 20:31:15 -040034 if (waiters || cont<0)
Rich Felkerbc09d582014-08-15 23:54:52 -040035 __wake(&m->_m_lock, 1, priv);
Rich Felker0b44a032011-02-12 00:22:29 -050036 return 0;
37}