]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
1 | #include "pthread_impl.h" |
2 | ||
3 | int __pthread_mutex_unlock(pthread_mutex_t *m) | |
4 | { | |
5 | pthread_t self; | |
6 | int waiters = m->_m_waiters; | |
7 | int cont; | |
8 | int type = m->_m_type & 15; | |
9 | int priv = (m->_m_type & 128) ^ 128; | |
f41256b6 DG |
10 | int new = 0; |
11 | int old; | |
320054e8 DG |
12 | |
13 | if (type != PTHREAD_MUTEX_NORMAL) { | |
14 | self = __pthread_self(); | |
f41256b6 DG |
15 | old = m->_m_lock; |
16 | int own = old & 0x3fffffff; | |
17 | if (own != self->tid) | |
320054e8 DG |
18 | return EPERM; |
19 | if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) | |
20 | return m->_m_count--, 0; | |
f41256b6 DG |
21 | if ((type&4) && (old&0x40000000)) |
22 | new = 0x7fffffff; | |
320054e8 DG |
23 | if (!priv) { |
24 | self->robust_list.pending = &m->_m_next; | |
25 | __vm_lock(); | |
26 | } | |
27 | volatile void *prev = m->_m_prev; | |
28 | volatile void *next = m->_m_next; | |
29 | *(volatile void *volatile *)prev = next; | |
30 | if (next != &self->robust_list.head) *(volatile void *volatile *) | |
31 | ((char *)next - sizeof(void *)) = prev; | |
32 | } | |
f41256b6 DG |
33 | if (type&8) { |
34 | if (old<0 || a_cas(&m->_m_lock, old, new)!=old) { | |
35 | if (new) a_store(&m->_m_waiters, -1); | |
36 | __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv); | |
37 | } | |
38 | cont = 0; | |
39 | waiters = 0; | |
40 | } else { | |
41 | cont = a_swap(&m->_m_lock, new); | |
42 | } | |
320054e8 DG |
43 | if (type != PTHREAD_MUTEX_NORMAL && !priv) { |
44 | self->robust_list.pending = 0; | |
45 | __vm_unlock(); | |
46 | } | |
47 | if (waiters || cont<0) | |
48 | __wake(&m->_m_lock, 1, priv); | |
49 | return 0; | |
50 | } | |
51 | ||
52 | weak_alias(__pthread_mutex_unlock, pthread_mutex_unlock); |