summaryrefslogtreecommitdiff
path: root/nptl/pthread_mutex_trylock.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/pthread_mutex_trylock.c')
-rw-r--r--nptl/pthread_mutex_trylock.c130
1 files changed, 73 insertions, 57 deletions
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index ae73ecc39b..5a13ea6925 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -28,6 +28,7 @@ int
__pthread_mutex_trylock (mutex)
pthread_mutex_t *mutex;
{
+ int oldval;
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
@@ -77,73 +78,88 @@ __pthread_mutex_trylock (mutex)
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
- /* Check whether we already hold the mutex. */
- if (abs (mutex->__data.__owner) == id)
- {
- /* Just bump the counter. */
- if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
- /* Overflow of the counter. */
- return EAGAIN;
-
- ++mutex->__data.__count;
-
- return 0;
- }
-
- /* We have to get the mutex. */
- if (lll_mutex_trylock (mutex->__data.__lock) == 0)
- {
- mutex->__data.__count = 1;
-
- goto robust;
- }
-
- break;
-
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
- /* Check whether we already hold the mutex. */
- if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
- return EDEADLK;
-
- /* FALLTHROUGH */
-
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
- if (lll_mutex_trylock (mutex->__data.__lock) != 0)
- break;
-
- robust:
- if (__builtin_expect (mutex->__data.__owner
- == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
- {
- /* This mutex is now not recoverable. */
- mutex->__data.__count = 0;
- lll_mutex_unlock (mutex->__data.__lock);
- return ENOTRECOVERABLE;
- }
-
- /* This mutex is either healthy or we can try to recover it. */
- assert (mutex->__data.__owner == 0
- || mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
-
- /* Record the ownership. */
- int retval = 0;
- if (__builtin_expect (mutex->__data.__owner
- == PTHREAD_MUTEX_OWNERDEAD, 0))
+ oldval = mutex->__data.__lock;
+ do
{
- retval = EOWNERDEAD;
- /* We signal ownership of a not yet recovered robust
- mutex by storing the negative thread ID. */
- id = -id;
+ 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)
+ {
+ if ((newval & FUTEX_OWNER_DIED) == 0)
+ goto normal;
+ oldval = newval;
+ }
+
+ /* We got the mutex. */
+ mutex->__data.__count = 1;
+ /* But it is inconsistent unless marked otherwise. */
+ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+ ENQUEUE_MUTEX (mutex);
+
+ /* Note that we deliberately exist here. If we fall
+ through to the end of the function __nusers would be
+ incremented which is not correct because the old
+ owner has to be discounted. */
+ return EOWNERDEAD;
+ }
+
+ normal:
+ /* Check whether we already hold the mutex. */
+ if (__builtin_expect ((mutex->__data.__lock & FUTEX_TID_MASK)
+ == id, 0))
+ {
+ if (mutex->__data.__kind
+ == PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP)
+ return EDEADLK;
+
+ if (mutex->__data.__kind
+ == PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP)
+ {
+ /* Just bump the counter. */
+ if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ return 0;
+ }
+ }
+
+ oldval = lll_robust_mutex_trylock (mutex->__data.__lock, id);
+ if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
+ return EBUSY;
+
+ robust:
+ if (__builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+ {
+ /* This mutex is now not recoverable. */
+ mutex->__data.__count = 0;
+ if (oldval == id)
+ lll_mutex_unlock (mutex->__data.__lock);
+ return ENOTRECOVERABLE;
+ }
}
+ while ((oldval & FUTEX_OWNER_DIED) != 0);
ENQUEUE_MUTEX (mutex);
mutex->__data.__owner = id;
++mutex->__data.__nusers;
+ mutex->__data.__count = 1;
+
+ return 0;
- return retval
-;
default:
/* Correct code cannot set any other type. */
return EINVAL;