diff options
Diffstat (limited to 'nptl/pthread_mutex_lock.c')
-rw-r--r-- | nptl/pthread_mutex_lock.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index dd22567c71..06eef49c71 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -108,25 +108,33 @@ __pthread_mutex_lock (mutex) assert (mutex->__data.__owner == 0); break; - case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP: - case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP: - case PTHREAD_MUTEX_ROBUST_PRIVATE_NP: - case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP: + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + oldval = mutex->__data.__lock; do { + again: if ((oldval & FUTEX_OWNER_DIED) != 0) { /* The previous owner died. Try locking the mutex. */ - int newval; - while ((newval - = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, - id, oldval)) - != oldval) + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#endif + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + + if (newval != oldval) { - if ((newval & FUTEX_OWNER_DIED) == 0) - goto normal; oldval = newval; + goto again; } /* We got the mutex. */ @@ -135,6 +143,7 @@ __pthread_mutex_lock (mutex) mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); /* Note that we deliberately exit here. If we fall through to the end of the function __nusers would be @@ -149,18 +158,23 @@ __pthread_mutex_lock (mutex) return EOWNERDEAD; } - normal: /* Check whether we already hold the mutex. */ - if (__builtin_expect ((mutex->__data.__lock & FUTEX_TID_MASK) - == id, 0)) + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) { if (mutex->__data.__kind - == PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP) - return EDEADLK; + == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } if (mutex->__data.__kind - == PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP) + == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + /* Just bump the counter. */ if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) /* Overflow of the counter. */ @@ -180,6 +194,7 @@ __pthread_mutex_lock (mutex) /* This mutex is now not recoverable. */ mutex->__data.__count = 0; lll_mutex_unlock (mutex->__data.__lock); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); return ENOTRECOVERABLE; } } @@ -187,6 +202,7 @@ __pthread_mutex_lock (mutex) mutex->__data.__count = 1; ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); break; default: |