diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-03-17 20:41:37 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-03-17 20:41:37 -0400 |
commit | 047e434ef5fd5437a74f98f63c40a77a683f7f3f (patch) | |
tree | 30102ca55dc34c2b5ec078e3b3ab7891abcccb5f /src/thread/pthread_mutex_trylock.c | |
parent | 18c7ea8055cf733f168d2c74d7cc8523a360f5f1 (diff) | |
download | musl-047e434ef5fd5437a74f98f63c40a77a683f7f3f.tar.gz musl-047e434ef5fd5437a74f98f63c40a77a683f7f3f.tar.xz musl-047e434ef5fd5437a74f98f63c40a77a683f7f3f.zip |
implement robust mutexes
some of this code should be cleaned up, e.g. using macros for some of the bit flags, masks, etc. nonetheless, the code is believed to be working and correct at this point.
Diffstat (limited to 'src/thread/pthread_mutex_trylock.c')
-rw-r--r-- | src/thread/pthread_mutex_trylock.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c index de57ff9e..f48aaade 100644 --- a/src/thread/pthread_mutex_trylock.c +++ b/src/thread/pthread_mutex_trylock.c @@ -3,19 +3,51 @@ int pthread_mutex_trylock(pthread_mutex_t *m) { int tid; + int own; + pthread_t self; if (m->_m_type == PTHREAD_MUTEX_NORMAL) return (m->_m_lock || a_swap(&m->_m_lock, 1)) ? EBUSY : 0; - tid = pthread_self()->tid; + self = pthread_self(); + tid = self->tid | 0x80000000; - if (m->_m_lock == tid && m->_m_type == PTHREAD_MUTEX_RECURSIVE) { + if (m->_m_type >= 4) { + if (!self->robust_list.off) + syscall2(__NR_set_robust_list, + (long)&self->robust_list, 3*sizeof(long)); + self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next; + self->robust_list.pending = &m->_m_next; + } + + if (m->_m_lock == tid && (m->_m_type&3) == PTHREAD_MUTEX_RECURSIVE) { if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN; m->_m_count++; return 0; } - if (m->_m_lock || a_cas(&m->_m_lock, 0, tid)) return EBUSY; + own = m->_m_lock; + if ((own && !(own & 0x40000000)) || a_cas(&m->_m_lock, own, tid)!=own) + return EBUSY; + m->_m_count = 1; + + if (m->_m_type < 4) return 0; + + if (m->_m_type >= 8) { + m->_m_lock = 0; + return ENOTRECOVERABLE; + } + m->_m_next = self->robust_list.head; + m->_m_prev = &self->robust_list.head; + if (self->robust_list.head) + self->robust_list.head[-1] = &m->_m_next; + self->robust_list.head = &m->_m_next; + self->robust_list.pending = 0; + if (own) { + m->_m_type += 8; + return EOWNERDEAD; + } + return 0; } |