mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
* sysdeps/unix/sysv/linux/not-cancel.h (__openat_not_cancel,
__openat64_not_cancel): Remove prototypes. (__openat_nocancel, __openat64_nocancel): New prototypes or defines. (openat_not_cancel, openat_not_cancel_3, openat64_not_cancel, openat64_not_cancel_3): Use them.
This commit is contained in:
parent
b007ce7cc6
commit
683040c3b2
@ -1,3 +1,11 @@
|
||||
2006-02-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/not-cancel.h (__openat_not_cancel,
|
||||
__openat64_not_cancel): Remove prototypes.
|
||||
(__openat_nocancel, __openat64_nocancel): New prototypes or defines.
|
||||
(openat_not_cancel, openat_not_cancel_3, openat64_not_cancel,
|
||||
openat64_not_cancel_3): Use them.
|
||||
|
||||
2006-02-12 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* io/ftw.c: Start using *at functions.
|
||||
|
@ -1,3 +1,30 @@
|
||||
2006-02-15 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* pthreadp.h: Define PTHREAD_MUTEX_INCONSISTENT instead of
|
||||
PTHREAD_MUTEX_OWNERDEAD.
|
||||
(PTHREAD_MUTEX_ROBUST_PRIVATE_NP): Define as 16, not 256.
|
||||
Define FUTEX_WAITERS, FUTEX_OWNER_DIED, FUTEX_TID_MASK.
|
||||
* Makefile (libpthread-routines): Add lowlevelrobustlock.
|
||||
* pthread_create.c (start_thread): Very much simplify robust_list loop.
|
||||
* pthread_mutex_consistent.c: Inconsistent mutex have __owner now set
|
||||
to PTHREAD_MUTEX_INCONSISTENT.
|
||||
* pthread_mutex_destroy.c: Allow destroying of inconsistent mutexes.
|
||||
* pthread_mutex_lock.c: Reimplement robust mutex handling.
|
||||
* pthread_mutex_trylock.c: Likewise.
|
||||
* pthread_mutex_timedlock.c: Likewise.
|
||||
* pthread_mutex_unlock.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add
|
||||
lowlevelrobustlock.sym.
|
||||
* sysdeps/unix/sysv/linux/lowlevelrobustlock.sym: New file.
|
||||
* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add lll_robust_mutex_*
|
||||
definitions.
|
||||
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
|
||||
* sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: New file.
|
||||
* sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S: New file.
|
||||
* sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S: New file.
|
||||
* sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: New file.
|
||||
|
||||
2006-02-12 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* allocatestack.c (allocate_stack): Initialize robust_list.
|
||||
|
@ -100,7 +100,7 @@ libpthread-routines = init vars events version \
|
||||
cleanup_defer_compat unwind \
|
||||
pt-longjmp pt-cleanup\
|
||||
cancellation \
|
||||
lowlevellock \
|
||||
lowlevellock lowlevelrobustlock \
|
||||
pt-vfork \
|
||||
ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \
|
||||
ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \
|
||||
|
@ -166,7 +166,7 @@ struct pthread
|
||||
do { \
|
||||
__pthread_slist_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list.__next);\
|
||||
if (runp == &mutex->__data.__list) \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list, runp->__next); \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \
|
||||
else \
|
||||
{ \
|
||||
while (runp->__next != &mutex->__data.__list) \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
|
||||
/* Magic cookie representing robust mutex with dead owner. */
|
||||
#define PTHREAD_MUTEX_OWNERDEAD INT_MAX
|
||||
#define PTHREAD_MUTEX_INCONSISTENT INT_MAX
|
||||
/* Magic cookie representing not recoverable robust mutex. */
|
||||
#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1)
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
/* Internal mutex type value. */
|
||||
enum
|
||||
{
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_NP = 256,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_NP = 16,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP
|
||||
= PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP
|
||||
@ -77,6 +77,12 @@ enum
|
||||
(PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED)
|
||||
|
||||
|
||||
/* Bits used in robust mutex implementation. */
|
||||
#define FUTEX_WAITERS 0x80000000
|
||||
#define FUTEX_OWNER_DIED 0x40000000
|
||||
#define FUTEX_TID_MASK 0x1fffffff
|
||||
|
||||
|
||||
/* Internal variables. */
|
||||
|
||||
|
||||
|
@ -324,17 +324,12 @@ start_thread (void *arg)
|
||||
((char *) robust - offsetof (struct __pthread_mutex_s, __list));
|
||||
robust = robust->__next;
|
||||
|
||||
assert (lll_mutex_islocked (this->__lock));
|
||||
this->__count = 0;
|
||||
--this->__nusers;
|
||||
assert (this->__owner != PTHREAD_MUTEX_NOTRECOVERABLE);
|
||||
this->__owner = PTHREAD_MUTEX_OWNERDEAD;
|
||||
this->__list.__next = NULL;
|
||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||
this->__list.__prev = NULL;
|
||||
#endif
|
||||
|
||||
lll_mutex_unlock (this->__lock);
|
||||
lll_robust_mutex_dead (this->__lock);
|
||||
}
|
||||
while (robust != &pd->robust_list);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
@ -27,10 +27,10 @@ pthread_mutex_consistent_np (mutex)
|
||||
{
|
||||
/* Test whether this is a robust mutex with a dead owner. */
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_PRIVATE_NP) == 0
|
||||
|| mutex->__data.__owner != -THREAD_GETMEM (THREAD_SELF, tid))
|
||||
|| mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT)
|
||||
return EINVAL;
|
||||
|
||||
mutex->__data.__owner = -mutex->__data.__owner;
|
||||
mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
@ -26,9 +26,17 @@ __pthread_mutex_destroy (mutex)
|
||||
pthread_mutex_t *mutex;
|
||||
{
|
||||
if (mutex->__data.__nusers != 0)
|
||||
return EBUSY;
|
||||
{
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_PRIVATE_NP) != 0
|
||||
&& (mutex->__data.__lock & FUTEX_OWNER_DIED) != 0
|
||||
&& mutex->__data.__nusers == 1)
|
||||
goto dead_robust_mutex;
|
||||
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
/* Set to an invalid value. */
|
||||
dead_robust_mutex:
|
||||
mutex->__data.__kind = -1;
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#ifndef LLL_MUTEX_LOCK
|
||||
# define LLL_MUTEX_LOCK(mutex) lll_mutex_lock (mutex)
|
||||
# define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_trylock (mutex)
|
||||
# define LLL_ROBUST_MUTEX_LOCK(mutex, id) lll_robust_mutex_lock (mutex, id)
|
||||
#endif
|
||||
|
||||
|
||||
@ -36,6 +37,7 @@ __pthread_mutex_lock (mutex)
|
||||
{
|
||||
assert (sizeof (mutex->__size) >= sizeof (mutex->__data));
|
||||
|
||||
int oldval;
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
|
||||
int retval = 0;
|
||||
@ -107,60 +109,83 @@ __pthread_mutex_lock (mutex)
|
||||
break;
|
||||
|
||||
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. */
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
|
||||
goto robust;
|
||||
|
||||
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:
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
oldval = mutex->__data.__lock;
|
||||
do
|
||||
{
|
||||
/* 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);
|
||||
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
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 exit 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. If we are not supposed
|
||||
to increment __nusers we actually have to decrement
|
||||
it here. */
|
||||
#ifdef NO_INCR
|
||||
--mutex->__data.__nusers;
|
||||
#endif
|
||||
|
||||
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_LOCK (mutex->__data.__lock, id);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
while ((oldval & FUTEX_OWNER_DIED) != 0);
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
break;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2004, 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 @@ pthread_mutex_timedlock (mutex, abstime)
|
||||
pthread_mutex_t *mutex;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
int oldval;
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
int result = 0;
|
||||
|
||||
@ -103,67 +104,83 @@ pthread_mutex_timedlock (mutex, abstime)
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We have to get the mutex. */
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
if (result != 0)
|
||||
goto out;
|
||||
|
||||
/* Only locked once so far. */
|
||||
mutex->__data.__count = 1;
|
||||
goto robust;
|
||||
|
||||
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:
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
if (result != 0)
|
||||
goto out;
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
oldval = mutex->__data.__lock;
|
||||
do
|
||||
{
|
||||
/* 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);
|
||||
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
result = EOWNERDEAD;
|
||||
/* We signal ownership of a not yet recovered robust mutex
|
||||
by storing the negative thread ID. */
|
||||
mutex->__data.__owner = -id;
|
||||
++mutex->__data.__nusers;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
result = lll_robust_mutex_timedlock (mutex->__data.__lock, abstime,
|
||||
id);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (result == ETIMEDOUT || result == EINVAL)
|
||||
goto out;
|
||||
|
||||
oldval = result;
|
||||
}
|
||||
while ((oldval & FUTEX_OWNER_DIED) != 0);
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
break;
|
||||
|
||||
|
@ -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))
|
||||
oldval = mutex->__data.__lock;
|
||||
do
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* This mutex is either healthy or we can try to recover it. */
|
||||
assert (mutex->__data.__owner == 0
|
||||
|| mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
|
||||
/* We got the mutex. */
|
||||
mutex->__data.__count = 1;
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
||||
|
||||
/* Record the ownership. */
|
||||
int retval = 0;
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
retval = EOWNERDEAD;
|
||||
/* We signal ownership of a not yet recovered robust
|
||||
mutex by storing the negative thread ID. */
|
||||
id = -id;
|
||||
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;
|
||||
|
@ -41,23 +41,32 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return 0;
|
||||
break;
|
||||
goto normal;
|
||||
|
||||
case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
/* Error checking mutex. */
|
||||
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
||||
return EPERM;
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_TIMED_NP:
|
||||
case PTHREAD_MUTEX_ADAPTIVE_NP:
|
||||
/* Normal mutex. Nothing special to do. */
|
||||
/* Always reset the owner field. */
|
||||
normal:
|
||||
mutex->__data.__owner = 0;
|
||||
if (decr)
|
||||
/* One less user. */
|
||||
--mutex->__data.__nusers;
|
||||
|
||||
/* Unlock. */
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
|
||||
/* Recursive mutex. */
|
||||
if (mutex->__data.__owner == -THREAD_GETMEM (THREAD_SELF, tid))
|
||||
if ((mutex->__data.__lock & FUTEX_TID_MASK)
|
||||
== THREAD_GETMEM (THREAD_SELF, tid))
|
||||
{
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
@ -78,7 +87,8 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||
if (abs (mutex->__data.__owner) != THREAD_GETMEM (THREAD_SELF, tid)
|
||||
if ((mutex->__data.__lock & FUTEX_TID_MASK)
|
||||
!= THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
||||
return EPERM;
|
||||
|
||||
@ -86,15 +96,21 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
making the state consistent, mark the mutex as unrecoverable
|
||||
and make all waiters. */
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== -THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE), 0))
|
||||
== PTHREAD_MUTEX_INCONSISTENT, 0))
|
||||
notrecoverable:
|
||||
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
|
||||
|
||||
robust:
|
||||
/* Remove mutex from the list. */
|
||||
DEQUEUE_MUTEX (mutex);
|
||||
|
||||
mutex->__data.__owner = newowner;
|
||||
if (decr)
|
||||
/* One less user. */
|
||||
--mutex->__data.__nusers;
|
||||
|
||||
/* Unlock. */
|
||||
lll_robust_mutex_unlock (mutex->__data.__lock);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -102,15 +118,6 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Always reset the owner field. */
|
||||
mutex->__data.__owner = newowner;
|
||||
if (decr)
|
||||
/* One less user. */
|
||||
--mutex->__data.__nusers;
|
||||
|
||||
/* Unlock. */
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -24,7 +24,8 @@ sysdep_routines += register-atfork unregister-atfork libc_pthread_init \
|
||||
libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
|
||||
|
||||
gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \
|
||||
lowlevelbarrier.sym unwindbuf.sym
|
||||
lowlevelbarrier.sym unwindbuf.sym \
|
||||
lowlevelrobustlock.sym
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),posix)
|
||||
|
@ -43,6 +43,13 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
typedef struct __pthread_internal_list
|
||||
{
|
||||
struct __pthread_internal_list *__prev;
|
||||
struct __pthread_internal_list *__next;
|
||||
} __pthread_list_t;
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is deliberately not exposed. */
|
||||
typedef union
|
||||
@ -57,8 +64,7 @@ typedef union
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
struct __pthread_mutex_s *__prev;
|
||||
__pthread_list_t __list;
|
||||
#define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
|
186
nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
Normal file
186
nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
Normal file
@ -0,0 +1,186 @@
|
||||
/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <pthread-errnos.h>
|
||||
#include <lowlevelrobustlock.h>
|
||||
|
||||
.text
|
||||
|
||||
#ifndef LOCK
|
||||
# ifdef UP
|
||||
# define LOCK
|
||||
# else
|
||||
# define LOCK lock
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define SYS_gettimeofday __NR_gettimeofday
|
||||
#define SYS_futex 240
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
#define FUTEX_WAITERS 0x80000000
|
||||
#define FUTEX_OWNER_DIED 0x40000000
|
||||
|
||||
|
||||
.globl __lll_robust_mutex_lock_wait
|
||||
.type __lll_robust_mutex_lock_wait,@function
|
||||
.hidden __lll_robust_mutex_lock_wait
|
||||
.align 16
|
||||
__lll_robust_mutex_lock_wait:
|
||||
pushl %edx
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
|
||||
movl %ecx, %ebx
|
||||
xorl %esi, %esi /* No timeout. */
|
||||
xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
|
||||
|
||||
4: movl %eax, %edx
|
||||
orl $FUTEX_WAITERS, %edx
|
||||
|
||||
testl $FUTEX_OWNER_DIED, %eax
|
||||
jnz 3f
|
||||
|
||||
cmpl %edx, %eax /* NB: %edx == 2 */
|
||||
je 1f
|
||||
|
||||
LOCK
|
||||
cmpxchgl %edx, (%ebx)
|
||||
jnz 2f
|
||||
|
||||
1: movl $SYS_futex, %eax
|
||||
ENTER_KERNEL
|
||||
|
||||
movl (%ebx), %eax
|
||||
|
||||
2: test %eax, %eax
|
||||
jne 4b
|
||||
|
||||
movl %gs:TID, %edx
|
||||
LOCK
|
||||
cmpxchgl %edx, (%ebx)
|
||||
jnz 4b
|
||||
/* NB: %eax == 0 */
|
||||
|
||||
3: popl %esi
|
||||
popl %ebx
|
||||
popl %edx
|
||||
ret
|
||||
.size __lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
|
||||
|
||||
|
||||
.globl __lll_robust_mutex_timedlock_wait
|
||||
.type __lll_robust_mutex_timedlock_wait,@function
|
||||
.hidden __lll_robust_mutex_timedlock_wait
|
||||
.align 16
|
||||
__lll_robust_mutex_timedlock_wait:
|
||||
/* Check for a valid timeout value. */
|
||||
cmpl $1000000000, 4(%edx)
|
||||
jae 3f
|
||||
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
pushl %ebp
|
||||
|
||||
/* Stack frame for the timespec and timeval structs. */
|
||||
subl $12, %esp
|
||||
|
||||
movl %ecx, %ebp
|
||||
movl %edx, %edi
|
||||
|
||||
1: movl %eax, 8(%esp)
|
||||
|
||||
/* Get current time. */
|
||||
movl %esp, %ebx
|
||||
xorl %ecx, %ecx
|
||||
movl $SYS_gettimeofday, %eax
|
||||
ENTER_KERNEL
|
||||
|
||||
/* Compute relative timeout. */
|
||||
movl 4(%esp), %eax
|
||||
movl $1000, %edx
|
||||
mul %edx /* Milli seconds to nano seconds. */
|
||||
movl (%edi), %ecx
|
||||
movl 4(%edi), %edx
|
||||
subl (%esp), %ecx
|
||||
subl %eax, %edx
|
||||
jns 4f
|
||||
addl $1000000000, %edx
|
||||
subl $1, %ecx
|
||||
4: testl %ecx, %ecx
|
||||
js 8f /* Time is already up. */
|
||||
|
||||
/* Store relative timeout. */
|
||||
movl %ecx, (%esp)
|
||||
movl %edx, 4(%esp)
|
||||
|
||||
movl %ebp, %ebx
|
||||
|
||||
movl 8(%esp), %edx
|
||||
movl %edx, %eax
|
||||
orl $FUTEX_WAITERS, %edx
|
||||
|
||||
testl $FUTEX_OWNER_DIED, %eax
|
||||
jnz 6f
|
||||
|
||||
cmpl %eax, %edx
|
||||
je 2f
|
||||
|
||||
LOCK
|
||||
cmpxchgl %edx, (%ebx)
|
||||
movl $0, %ecx /* Must use mov to avoid changing cc. */
|
||||
jnz 5f
|
||||
|
||||
2:
|
||||
/* Futex call. */
|
||||
movl %esp, %esi
|
||||
xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
|
||||
movl $SYS_futex, %eax
|
||||
ENTER_KERNEL
|
||||
movl %eax, %ecx
|
||||
|
||||
movl (%ebx), %eax
|
||||
|
||||
5: testl %eax, %eax
|
||||
jne 7f
|
||||
|
||||
movl %gs:TID, %edx
|
||||
LOCK
|
||||
cmpxchgl %edx, (%ebx)
|
||||
jnz 7f
|
||||
|
||||
6: addl $12, %esp
|
||||
popl %ebp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
ret
|
||||
|
||||
/* Check whether the time expired. */
|
||||
7: cmpl $-ETIMEDOUT, %ecx
|
||||
jne 1b
|
||||
|
||||
8: movl $ETIMEDOUT, %eax
|
||||
jmp 6b
|
||||
|
||||
3: movl $EINVAL, %eax
|
||||
ret
|
||||
.size __lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
|
20
nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
Normal file
20
nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
Normal file
@ -0,0 +1,20 @@
|
||||
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "../i486/lowlevelrobustlock.S"
|
20
nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
Normal file
20
nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
Normal file
@ -0,0 +1,20 @@
|
||||
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "../i486/lowlevelrobustlock.S"
|
@ -139,6 +139,16 @@ extern int __lll_mutex_unlock_wake (int *__futex)
|
||||
ret; })
|
||||
|
||||
|
||||
#define lll_robust_mutex_trylock(futex, id) \
|
||||
({ int ret; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
|
||||
: "=a" (ret), "=m" (futex) \
|
||||
: "r" (id), "m" (futex), \
|
||||
"0" (LLL_MUTEX_LOCK_INITIALIZER) \
|
||||
: "memory"); \
|
||||
ret; })
|
||||
|
||||
|
||||
#define lll_mutex_cond_trylock(futex) \
|
||||
({ int ret; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
|
||||
@ -167,6 +177,25 @@ extern int __lll_mutex_unlock_wake (int *__futex)
|
||||
: "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_lock(futex, id) \
|
||||
({ int result, ignore; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \
|
||||
"jnz _L_mutex_lock_%=\n\t" \
|
||||
".subsection 1\n\t" \
|
||||
".type _L_mutex_lock_%=,@function\n" \
|
||||
"_L_mutex_lock_%=:\n\t" \
|
||||
"leal %2, %%ecx\n\t" \
|
||||
"call __lll_robust_mutex_lock_wait\n\t" \
|
||||
"jmp 1f\n\t" \
|
||||
".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \
|
||||
".previous\n" \
|
||||
"1:" \
|
||||
: "=a" (result), "=c" (ignore), "=m" (futex) \
|
||||
: "0" (0), "1" (id), "m" (futex) \
|
||||
: "memory"); \
|
||||
result; })
|
||||
|
||||
|
||||
/* Special version of lll_mutex_lock which causes the unlock function to
|
||||
always wakeup waiters. */
|
||||
#define lll_mutex_cond_lock(futex) \
|
||||
@ -187,6 +216,25 @@ extern int __lll_mutex_unlock_wake (int *__futex)
|
||||
: "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_cond_lock(futex, id) \
|
||||
({ int result, ignore; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \
|
||||
"jnz _L_mutex_cond_lock_%=\n\t" \
|
||||
".subsection 1\n\t" \
|
||||
".type _L_mutex_cond_lock_%=,@function\n" \
|
||||
"_L_mutex_cond_lock_%=:\n\t" \
|
||||
"leal %2, %%ecx\n\t" \
|
||||
"call __lll_robust_mutex_lock_wait\n\t" \
|
||||
"jmp 1f\n\t" \
|
||||
".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"\
|
||||
".previous\n" \
|
||||
"1:" \
|
||||
: "=a" (result), "=c" (ignore), "=m" (futex) \
|
||||
: "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex) \
|
||||
: "memory"); \
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_mutex_timedlock(futex, timeout) \
|
||||
({ int result, ignore1, ignore2; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \
|
||||
@ -208,9 +256,30 @@ extern int __lll_mutex_unlock_wake (int *__futex)
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_robust_mutex_timedlock(futex, timeout, id) \
|
||||
({ int result, ignore1, ignore2; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \
|
||||
"jnz _L_mutex_timedlock_%=\n\t" \
|
||||
".subsection 1\n\t" \
|
||||
".type _L_mutex_timedlock_%=,@function\n" \
|
||||
"_L_mutex_timedlock_%=:\n\t" \
|
||||
"leal %3, %%ecx\n\t" \
|
||||
"movl %7, %%edx\n\t" \
|
||||
"call __lll_robust_mutex_timedlock_wait\n\t" \
|
||||
"jmp 1f\n\t" \
|
||||
".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\
|
||||
".previous\n" \
|
||||
"1:" \
|
||||
: "=a" (result), "=c" (ignore1), "=&d" (ignore2), \
|
||||
"=m" (futex) \
|
||||
: "0" (0), "1" (id), "m" (futex), "m" (timeout) \
|
||||
: "memory"); \
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_mutex_unlock(futex) \
|
||||
(void) ({ int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "subl $1,%0\n\t" \
|
||||
__asm __volatile (LOCK_INSTR "subl $1, %0\n\t" \
|
||||
"jne _L_mutex_unlock_%=\n\t" \
|
||||
".subsection 1\n\t" \
|
||||
".type _L_mutex_unlock_%=,@function\n" \
|
||||
@ -226,6 +295,53 @@ extern int __lll_mutex_unlock_wake (int *__futex)
|
||||
: "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_unlock(futex) \
|
||||
(void) ({ int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "andl %2, %0\n\t" \
|
||||
"jne _L_mutex_unlock_%=\n\t" \
|
||||
".subsection 1\n\t" \
|
||||
".type _L_mutex_unlock_%=,@function\n" \
|
||||
"_L_mutex_unlock_%=:\n\t" \
|
||||
"leal %0, %%eax\n\t" \
|
||||
"call __lll_mutex_unlock_wake\n\t" \
|
||||
"jmp 1f\n\t" \
|
||||
".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
|
||||
".previous\n" \
|
||||
"1:" \
|
||||
: "=m" (futex), "=&a" (ignore) \
|
||||
: "i" (FUTEX_TID_MASK), "m" (futex) \
|
||||
: "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_dead(futex) \
|
||||
(void) ({ int __ignore; \
|
||||
register int _nr asm ("edx") = 1; \
|
||||
__asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t" \
|
||||
LLL_EBX_LOAD \
|
||||
LLL_ENTER_KERNEL \
|
||||
LLL_EBX_LOAD \
|
||||
: "=a" (__ignore) \
|
||||
: "0" (SYS_futex), LLL_EBX_REG (&(futex)), \
|
||||
"c" (FUTEX_WAKE), "d" (_nr), \
|
||||
"i" (FUTEX_OWNER_DIED), \
|
||||
"i" (offsetof (tcbhead_t, sysinfo))); })
|
||||
|
||||
|
||||
#define lll_futex_wake(futex, nr) \
|
||||
do { \
|
||||
int __ignore; \
|
||||
register __typeof (nr) _nr asm ("edx") = (nr); \
|
||||
__asm __volatile (LLL_EBX_LOAD \
|
||||
LLL_ENTER_KERNEL \
|
||||
LLL_EBX_LOAD \
|
||||
: "=a" (__ignore) \
|
||||
: "0" (SYS_futex), LLL_EBX_REG (futex), \
|
||||
"c" (FUTEX_WAKE), "d" (_nr), \
|
||||
"i" (0) /* phony, to align next arg's number */, \
|
||||
"i" (offsetof (tcbhead_t, sysinfo))); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define lll_mutex_islocked(futex) \
|
||||
(futex != 0)
|
||||
|
||||
|
@ -43,6 +43,13 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
typedef struct __pthread_internal_list
|
||||
{
|
||||
struct __pthread_internal_list *__prev;
|
||||
struct __pthread_internal_list *__next;
|
||||
} __pthread_list_t;
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
@ -57,8 +64,7 @@ typedef union
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
struct __pthread_mutex_s *__prev;
|
||||
__pthread_list_t __list;
|
||||
#define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
|
6
nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym
Normal file
6
nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stddef.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
--
|
||||
|
||||
TID offsetof (struct pthread, tid)
|
@ -58,6 +58,20 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
typedef struct __pthread_internal_list
|
||||
{
|
||||
struct __pthread_internal_list *__prev;
|
||||
struct __pthread_internal_list *__next;
|
||||
} __pthread_list_t;
|
||||
#else
|
||||
typedef struct __pthread_internal_slist
|
||||
{
|
||||
struct __pthread_internal_slist *__next;
|
||||
} __pthread_slist_t;
|
||||
#endif
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is deliberately not exposed. */
|
||||
typedef union
|
||||
@ -75,15 +89,14 @@ typedef union
|
||||
int __kind;
|
||||
#if __WORDSIZE == 64
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
struct __pthread_mutex_s *__prev;
|
||||
__pthread_list_t __list;
|
||||
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
#else
|
||||
unsigned int __nusers;
|
||||
__extension__ union
|
||||
{
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
__pthread_slist_t __list;
|
||||
};
|
||||
#endif
|
||||
} __data;
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include <pthreadP.h>
|
||||
|
||||
#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex)
|
||||
#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex)
|
||||
#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock (mutex)
|
||||
#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock (mutex)
|
||||
#define LLL_ROBUST_MUTEX_LOCK(mutex, id) lll_robust_mutex_cond_lock (mutex, id)
|
||||
#define __pthread_mutex_lock __pthread_mutex_cond_lock
|
||||
#define NO_INCR
|
||||
|
||||
|
@ -57,6 +57,20 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
typedef struct __pthread_internal_list
|
||||
{
|
||||
struct __pthread_internal_list *__prev;
|
||||
struct __pthread_internal_list *__next;
|
||||
} __pthread_list_t;
|
||||
#else
|
||||
typedef struct __pthread_internal_slist
|
||||
{
|
||||
struct __pthread_internal_slist *__next;
|
||||
} __pthread_slist_t;
|
||||
#endif
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
@ -74,15 +88,14 @@ typedef union
|
||||
int __kind;
|
||||
#if __WORDSIZE == 64
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
struct __pthread_mutex_s *__prev;
|
||||
__pthread_list_t __list;
|
||||
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
#else
|
||||
unsigned int __nusers;
|
||||
__extension__ union
|
||||
{
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
__pthread_slist_t __list;
|
||||
};
|
||||
#endif
|
||||
} __data;
|
||||
|
@ -44,6 +44,12 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
typedef struct __pthread_internal_slist
|
||||
{
|
||||
struct __pthread_internal_slist *__next;
|
||||
} __pthread_slist_t;
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
@ -60,7 +66,7 @@ typedef union
|
||||
__extension__ union
|
||||
{
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
__pthread_slist_t __list;
|
||||
};
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
|
@ -58,6 +58,20 @@ typedef union
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
typedef struct __pthread_internal_list
|
||||
{
|
||||
struct __pthread_internal_list *__prev;
|
||||
struct __pthread_internal_list *__next;
|
||||
} __pthread_list_t;
|
||||
#else
|
||||
typedef struct __pthread_internal_slist
|
||||
{
|
||||
struct __pthread_internal_slist *__next;
|
||||
} __pthread_slist_t;
|
||||
#endif
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is deliberately not exposed. */
|
||||
typedef union
|
||||
@ -75,15 +89,14 @@ typedef union
|
||||
int __kind;
|
||||
#if __WORDSIZE == 64
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
struct __pthread_mutex_s *__prev;
|
||||
__pthread_list_t __list;
|
||||
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
#else
|
||||
unsigned int __nusers;
|
||||
__extension__ union
|
||||
{
|
||||
int __spins;
|
||||
struct __pthread_mutex_s *__next;
|
||||
__pthread_slist_t __list;
|
||||
};
|
||||
#endif
|
||||
} __data;
|
||||
|
@ -111,6 +111,16 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
|
||||
ret; })
|
||||
|
||||
|
||||
#define lll_robust_mutex_trylock(futex, id) \
|
||||
({ int ret; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
|
||||
: "=a" (ret), "=m" (futex) \
|
||||
: "r" (id), "m" (futex), \
|
||||
"0" (LLL_MUTEX_LOCK_INITIALIZER) \
|
||||
: "memory"); \
|
||||
ret; })
|
||||
|
||||
|
||||
#define lll_mutex_cond_trylock(futex) \
|
||||
({ int ret; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
|
||||
@ -139,6 +149,25 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
|
||||
: "cx", "r11", "cc", "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_lock(futex, id) \
|
||||
({ int result, ignore1, ignore2; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t" \
|
||||
"jnz 1f\n\t" \
|
||||
".subsection 1\n" \
|
||||
"1:\tleaq %2, %%rdi\n\t" \
|
||||
"subq $128, %%rsp\n\t" \
|
||||
"callq __lll_robust_mutex_lock_wait\n\t" \
|
||||
"addq $128, %%rsp\n\t" \
|
||||
"jmp 2f\n\t" \
|
||||
".previous\n" \
|
||||
"2:" \
|
||||
: "=S" (ignore1), "=&D" (ignore2), "=m" (futex), \
|
||||
"=a" (result) \
|
||||
: "0" (id), "m" (futex), "3" (0) \
|
||||
: "cx", "r11", "cc", "memory"); \
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_mutex_cond_lock(futex) \
|
||||
(void) ({ int ignore1, ignore2, ignore3; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t" \
|
||||
@ -157,6 +186,25 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
|
||||
: "cx", "r11", "cc", "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_cond_lock(futex, id) \
|
||||
({ int result, ignore1, ignore2; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t" \
|
||||
"jnz 1f\n\t" \
|
||||
".subsection 1\n" \
|
||||
"1:\tleaq %2, %%rdi\n\t" \
|
||||
"subq $128, %%rsp\n\t" \
|
||||
"callq __lll_robust_mutex_lock_wait\n\t" \
|
||||
"addq $128, %%rsp\n\t" \
|
||||
"jmp 2f\n\t" \
|
||||
".previous\n" \
|
||||
"2:" \
|
||||
: "=S" (ignore1), "=&D" (ignore2), "=m" (futex), \
|
||||
"=a" (result) \
|
||||
: "0" (id | FUTEX_WAITERS), "m" (futex), "3" (0) \
|
||||
: "cx", "r11", "cc", "memory"); \
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_mutex_timedlock(futex, timeout) \
|
||||
({ int result, ignore1, ignore2, ignore3; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t" \
|
||||
@ -177,6 +225,26 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_robust_mutex_timedlock(futex, timeout, id) \
|
||||
({ int result, ignore1, ignore2, ignore3; \
|
||||
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t" \
|
||||
"jnz 1f\n\t" \
|
||||
".subsection 1\n" \
|
||||
"1:\tleaq %4, %%rdi\n\t" \
|
||||
"movq %8, %%rdx\n\t" \
|
||||
"subq $128, %%rsp\n\t" \
|
||||
"callq __lll_robust_mutex_timedlock_wait\n\t" \
|
||||
"addq $128, %%rsp\n\t" \
|
||||
"jmp 2f\n\t" \
|
||||
".previous\n" \
|
||||
"2:" \
|
||||
: "=a" (result), "=&D" (ignore1), "=S" (ignore2), \
|
||||
"=&d" (ignore3), "=m" (futex) \
|
||||
: "0" (0), "2" (id), "m" (futex), "m" (timeout) \
|
||||
: "memory", "cx", "cc", "r10", "r11"); \
|
||||
result; })
|
||||
|
||||
|
||||
#define lll_mutex_unlock(futex) \
|
||||
(void) ({ int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "decl %0\n\t" \
|
||||
@ -194,6 +262,34 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
|
||||
: "ax", "cx", "r11", "cc", "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_unlock(futex) \
|
||||
(void) ({ int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "andl %2, %0\n\t" \
|
||||
"jne 1f\n\t" \
|
||||
".subsection 1\n" \
|
||||
"1:\tleaq %0, %%rdi\n\t" \
|
||||
"subq $128, %%rsp\n\t" \
|
||||
"callq __lll_mutex_unlock_wake\n\t" \
|
||||
"addq $128, %%rsp\n\t" \
|
||||
"jmp 2f\n\t" \
|
||||
".previous\n" \
|
||||
"2:" \
|
||||
: "=m" (futex), "=&D" (ignore) \
|
||||
: "i" (FUTEX_TID_MASK), "m" (futex) \
|
||||
: "ax", "cx", "r11", "cc", "memory"); })
|
||||
|
||||
|
||||
#define lll_robust_mutex_dead(futex) \
|
||||
(void) ({ int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "orl %3, (%2)\n\t" \
|
||||
"syscall" \
|
||||
: "=m" (futex), "=a" (ignore) \
|
||||
: "D" (&(futex)), "i" (FUTEX_OWNER_DIED), \
|
||||
"S" (FUTEX_WAKE), "1" (__NR_futex), \
|
||||
"d" (1) \
|
||||
: "cx", "r11", "cc", "memory"); })
|
||||
|
||||
|
||||
#define lll_mutex_islocked(futex) \
|
||||
(futex != LLL_MUTEX_LOCK_INITIALIZER)
|
||||
|
||||
|
192
nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
Normal file
192
nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
Normal file
@ -0,0 +1,192 @@
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <pthread-errnos.h>
|
||||
#include <lowlevelrobustlock.h>
|
||||
|
||||
.text
|
||||
|
||||
#ifndef LOCK
|
||||
# ifdef UP
|
||||
# define LOCK
|
||||
# else
|
||||
# define LOCK lock
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define SYS_futex 202
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
#define FUTEX_WAITERS 0x80000000
|
||||
#define FUTEX_OWNER_DIED 0x40000000
|
||||
|
||||
/* For the calculation see asm/vsyscall.h. */
|
||||
#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
|
||||
|
||||
|
||||
.globl __lll_robust_mutex_lock_wait
|
||||
.type __lll_robust_mutex_lock_wait,@function
|
||||
.hidden __lll_robust_mutex_lock_wait
|
||||
.align 16
|
||||
__lll_robust_mutex_lock_wait:
|
||||
pushq %r10
|
||||
pushq %rdx
|
||||
|
||||
xorq %r10, %r10 /* No timeout. */
|
||||
#if FUTEX_WAIT == 0
|
||||
xorl %esi, %esi
|
||||
#else
|
||||
movl $FUTEX_WAIT, %esi
|
||||
#endif
|
||||
|
||||
4: movl %eax, %edx
|
||||
orl $FUTEX_WAITERS, %edx
|
||||
|
||||
testl $FUTEX_OWNER_DIED, %eax
|
||||
jnz 3f
|
||||
|
||||
cmpl %edx, %eax
|
||||
je 1f
|
||||
|
||||
LOCK
|
||||
cmpxchgl %edx, (%rdi)
|
||||
jnz 2f
|
||||
|
||||
1: movl $SYS_futex, %eax
|
||||
syscall
|
||||
|
||||
movl (%rdi), %eax
|
||||
|
||||
2: testl %eax, %eax
|
||||
jne 4b
|
||||
|
||||
movl %fs:TID, %edx
|
||||
LOCK
|
||||
cmpxchgl %edx, (%rdi)
|
||||
jnz 4b
|
||||
/* NB: %rax == 0 */
|
||||
|
||||
3: popq %rdx
|
||||
popq %r10
|
||||
retq
|
||||
.size __lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
|
||||
|
||||
|
||||
.globl __lll_robust_mutex_timedlock_wait
|
||||
.type __lll_robust_mutex_timedlock_wait,@function
|
||||
.hidden __lll_robust_mutex_timedlock_wait
|
||||
.align 16
|
||||
__lll_robust_mutex_timedlock_wait:
|
||||
/* Check for a valid timeout value. */
|
||||
cmpq $1000000000, 8(%rdx)
|
||||
jae 3f
|
||||
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
|
||||
/* Stack frame for the timespec and timeval structs. */
|
||||
subq $24, %rsp
|
||||
|
||||
movq %rdi, %r12
|
||||
movq %rdx, %r13
|
||||
|
||||
1: movq %rax, 16(%rsp)
|
||||
|
||||
/* Get current time. */
|
||||
movq %rsp, %rdi
|
||||
xorl %esi, %esi
|
||||
movq $VSYSCALL_ADDR_vgettimeofday, %rax
|
||||
/* This is a regular function call, all caller-save registers
|
||||
might be clobbered. */
|
||||
callq *%rax
|
||||
|
||||
/* Compute relative timeout. */
|
||||
movq 8(%rsp), %rax
|
||||
movl $1000, %edi
|
||||
mul %rdi /* Milli seconds to nano seconds. */
|
||||
movq (%r13), %rdi
|
||||
movq 8(%r13), %rsi
|
||||
subq (%rsp), %rdi
|
||||
subq %rax, %rsi
|
||||
jns 4f
|
||||
addq $1000000000, %rsi
|
||||
decq %rdi
|
||||
4: testq %rdi, %rdi
|
||||
js 8f /* Time is already up. */
|
||||
|
||||
/* Futex call. */
|
||||
movq %rdi, (%rsp) /* Store relative timeout. */
|
||||
movq %rsi, 8(%rsp)
|
||||
|
||||
movq 16(%rsp), %rdx
|
||||
movl %edx, %eax
|
||||
orl $FUTEX_WAITERS, %edx
|
||||
|
||||
testl $FUTEX_OWNER_DIED, %eax
|
||||
jnz 6f
|
||||
|
||||
cmpl %eax, %edx
|
||||
je 2f
|
||||
|
||||
LOCK
|
||||
cmpxchgl %edx, (%r12)
|
||||
movq $0, %rcx /* Must use mov to avoid changing cc. */
|
||||
jnz 5f
|
||||
|
||||
2: movq %rsp, %r10
|
||||
#if FUTEX_WAIT == 0
|
||||
xorl %esi, %esi
|
||||
#else
|
||||
movl $FUTEX_WAIT, %esi
|
||||
#endif
|
||||
movq %r12, %rdi
|
||||
movl $SYS_futex, %eax
|
||||
syscall
|
||||
movq %rax, %rcx
|
||||
|
||||
movl (%r12), %eax
|
||||
|
||||
5: testl %eax, %eax
|
||||
jne 7f
|
||||
|
||||
movl %fs:TID, %edx
|
||||
LOCK
|
||||
cmpxchgl %edx, (%r12)
|
||||
jnz 7f
|
||||
|
||||
6: addq $24, %rsp
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r9
|
||||
popq %r8
|
||||
retq
|
||||
|
||||
/* Check whether the time expired. */
|
||||
7: cmpq $-ETIMEDOUT, %rcx
|
||||
jne 1b
|
||||
|
||||
8: movl $ETIMEDOUT, %eax
|
||||
jmp 6b
|
||||
|
||||
3: movl $EINVAL, %eax
|
||||
retq
|
||||
.size __lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
|
@ -28,18 +28,26 @@
|
||||
INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
|
||||
|
||||
/* Uncancelable openat. */
|
||||
extern int __openat_not_cancel (int fd, const char *fname, int oflag,
|
||||
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
|
||||
extern int __openat_nocancel (int fd, const char *fname, int oflag,
|
||||
mode_t mode) attribute_hidden;
|
||||
extern int __openat64_nocancel (int fd, const char *fname, int oflag,
|
||||
mode_t mode) attribute_hidden;
|
||||
#else
|
||||
# define __openat_nocancel(fd, fname, oflag, mode) \
|
||||
openat (fd, fname, oflag, mode)
|
||||
# define __openat64_nocancel(fd, fname, oflag, mode) \
|
||||
openat64 (fd, fname, oflag, mode)
|
||||
#endif
|
||||
|
||||
#define openat_not_cancel(fd, fname, oflag, mode) \
|
||||
__openat_not_cancel (fd, fname, oflag, mode)
|
||||
__openat_nocancel (fd, fname, oflag, mode)
|
||||
#define openat_not_cancel_3(fd, fname, oflag) \
|
||||
__openat_not_cancel (fd, fname, oflag, 0)
|
||||
extern int __openat64_not_cancel (int fd, const char *fname, int oflag,
|
||||
mode_t mode) attribute_hidden;
|
||||
__openat_nocancel (fd, fname, oflag, 0)
|
||||
#define openat64_not_cancel(fd, fname, oflag, mode) \
|
||||
__openat64_not_cancel (fd, fname, oflag, mode)
|
||||
__openat64_nocancel (fd, fname, oflag, mode)
|
||||
#define openat64_not_cancel_3(fd, fname, oflag) \
|
||||
__openat64_not_cancel (fd, fname, oflag, 0)
|
||||
__openat64_nocancel (fd, fname, oflag, 0)
|
||||
|
||||
/* Uncancelable close. */
|
||||
#define close_not_cancel(fd) \
|
||||
|
Loading…
Reference in New Issue
Block a user