mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
2006-07-28 Ulrich Drepper <drepper@redhat.com>
Jakub Jelinek <jakub@redhat.com> * descr.h: Change ENQUEUE_MUTEX and DEQUEUE_MUTEX for bit 0 notification of PI mutex. Add ENQUEUE_MUTEX_PI. * pthreadP.h: Define PTHREAD_MUTEX_PI_* macros for PI mutex types. * pthread_mutex_setprioceilining.c: Adjust for mutex type name change. * pthread_mutex_init.c: Add support for priority inheritance mutex. * pthread_mutex_lock.c: Likewise. * pthread_mutex_timedlock.c: Likewise. * pthread_mutex_trylock.c: Likewise. * pthread_mutex_unlock.c: Likewise. * sysdeps/pthread/pthread_cond_broadcast.c: For PI mutexes wake all mutexes. * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.c: Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.c: Likewise. * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: New file. * sysdeps/unix/sysv/linux/Makefile (gen-as-const-header): Add pthread-pi-defines.sym. * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_LOCK_PI, FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI. * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _POSIX_THREAD_PRIO_INHERIT to 200112L. * tst-mutex1.c: Adjust to allow use in PI mutex test. * tst-mutex2.c: Likewise. * tst-mutex3.c: Likewise. * tst-mutex4.c: Likewise. * tst-mutex5.c: Likewise. * tst-mutex6.c: Likewise. * tst-mutex7.c: Likewise. * tst-mutex7a.c: Likewise. * tst-mutex8.c: Likewise. * tst-mutex9.c: Likewise. * tst-robust1.c: Likewise. * tst-robust7.c: Likewise. * tst-robust8.c: Likewise. * tst-mutexpi1.c: New file. * tst-mutexpi2.c: New file. * tst-mutexpi3.c: New file. * tst-mutexpi4.c: New file. * tst-mutexpi5.c: New file. * tst-mutexpi6.c: New file. * tst-mutexpi7.c: New file. * tst-mutexpi7a.c: New file. * tst-mutexpi8.c: New file. * tst-mutexpi9.c: New file. * tst-robust1.c: New file. * tst-robust2.c: New file. * tst-robust3.c: New file. * tst-robust4.c: New file. * tst-robust5.c: New file. * tst-robust6.c: New file. * tst-robust7.c: New file. * tst-robust8.c: New file. * Makefile (tests): Add the new tests. * pthread_create.c (start_thread): Add some casts to avoid warnings. * pthread_mutex_destroy.c: Remove unneeded label.
This commit is contained in:
parent
6822f05652
commit
df47504c78
49 changed files with 1083 additions and 89 deletions
|
@ -1,3 +1,63 @@
|
|||
2006-07-28 Ulrich Drepper <drepper@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* descr.h: Change ENQUEUE_MUTEX and DEQUEUE_MUTEX for bit 0
|
||||
notification of PI mutex. Add ENQUEUE_MUTEX_PI.
|
||||
* pthreadP.h: Define PTHREAD_MUTEX_PI_* macros for PI mutex types.
|
||||
* pthread_mutex_setprioceilining.c: Adjust for mutex type name change.
|
||||
* pthread_mutex_init.c: Add support for priority inheritance mutex.
|
||||
* pthread_mutex_lock.c: Likewise.
|
||||
* pthread_mutex_timedlock.c: Likewise.
|
||||
* pthread_mutex_trylock.c: Likewise.
|
||||
* pthread_mutex_unlock.c: Likewise.
|
||||
* sysdeps/pthread/pthread_cond_broadcast.c: For PI mutexes wake
|
||||
all mutexes.
|
||||
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/pthread-pi-defines.sym: New file.
|
||||
* sysdeps/unix/sysv/linux/Makefile (gen-as-const-header): Add
|
||||
pthread-pi-defines.sym.
|
||||
* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_LOCK_PI,
|
||||
FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI.
|
||||
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
|
||||
* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
|
||||
_POSIX_THREAD_PRIO_INHERIT to 200112L.
|
||||
* tst-mutex1.c: Adjust to allow use in PI mutex test.
|
||||
* tst-mutex2.c: Likewise.
|
||||
* tst-mutex3.c: Likewise.
|
||||
* tst-mutex4.c: Likewise.
|
||||
* tst-mutex5.c: Likewise.
|
||||
* tst-mutex6.c: Likewise.
|
||||
* tst-mutex7.c: Likewise.
|
||||
* tst-mutex7a.c: Likewise.
|
||||
* tst-mutex8.c: Likewise.
|
||||
* tst-mutex9.c: Likewise.
|
||||
* tst-robust1.c: Likewise.
|
||||
* tst-robust7.c: Likewise.
|
||||
* tst-robust8.c: Likewise.
|
||||
* tst-mutexpi1.c: New file.
|
||||
* tst-mutexpi2.c: New file.
|
||||
* tst-mutexpi3.c: New file.
|
||||
* tst-mutexpi4.c: New file.
|
||||
* tst-mutexpi5.c: New file.
|
||||
* tst-mutexpi6.c: New file.
|
||||
* tst-mutexpi7.c: New file.
|
||||
* tst-mutexpi7a.c: New file.
|
||||
* tst-mutexpi8.c: New file.
|
||||
* tst-mutexpi9.c: New file.
|
||||
* tst-robust1.c: New file.
|
||||
* tst-robust2.c: New file.
|
||||
* tst-robust3.c: New file.
|
||||
* tst-robust4.c: New file.
|
||||
* tst-robust5.c: New file.
|
||||
* tst-robust6.c: New file.
|
||||
* tst-robust7.c: New file.
|
||||
* tst-robust8.c: New file.
|
||||
* Makefile (tests): Add the new tests.
|
||||
|
||||
* pthread_create.c (start_thread): Add some casts to avoid warnings.
|
||||
* pthread_mutex_destroy.c: Remove unneeded label.
|
||||
|
||||
2006-07-01 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* pthread_mutex_init.c (__pthread_mutex_init): Move some
|
||||
|
|
|
@ -200,6 +200,9 @@ tests = tst-typesizes \
|
|||
tst-attr1 tst-attr2 tst-attr3 \
|
||||
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
||||
tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \
|
||||
tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
|
||||
tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
|
||||
tst-mutexpi9 \
|
||||
tst-spin1 tst-spin2 tst-spin3 \
|
||||
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
|
||||
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
|
||||
|
@ -207,6 +210,8 @@ tests = tst-typesizes \
|
|||
tst-cond20 tst-cond21 \
|
||||
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
|
||||
tst-robust6 tst-robust7 tst-robust8 \
|
||||
tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 \
|
||||
tst-robustpi5 tst-robustpi6 tst-robustpi7 tst-robustpi8 \
|
||||
tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
|
||||
tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
|
||||
tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
|
||||
|
|
40
nptl/descr.h
40
nptl/descr.h
|
@ -155,23 +155,28 @@ struct pthread
|
|||
first. */
|
||||
# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next))
|
||||
|
||||
# define ENQUEUE_MUTEX(mutex) \
|
||||
# define ENQUEUE_MUTEX_BOTH(mutex, val) \
|
||||
do { \
|
||||
__pthread_list_t *next = (THREAD_GETMEM (THREAD_SELF, robust_head.list) \
|
||||
- QUEUE_PTR_ADJUST); \
|
||||
__pthread_list_t *next = (__pthread_list_t *) \
|
||||
((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \
|
||||
- QUEUE_PTR_ADJUST); \
|
||||
next->__prev = (void *) &mutex->__data.__list.__next; \
|
||||
mutex->__data.__list.__next = (void *) &next->__next; \
|
||||
mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \
|
||||
robust_head.list); \
|
||||
mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list, \
|
||||
&mutex->__data.__list.__next); \
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next) \
|
||||
| val)); \
|
||||
} while (0)
|
||||
# define DEQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
__pthread_list_t *next = (__pthread_list_t *) \
|
||||
((char *) mutex->__data.__list.__next - QUEUE_PTR_ADJUST); \
|
||||
((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \
|
||||
- QUEUE_PTR_ADJUST); \
|
||||
next->__prev = mutex->__data.__list.__prev; \
|
||||
__pthread_list_t *prev = (__pthread_list_t *) \
|
||||
((char *) mutex->__data.__list.__prev - QUEUE_PTR_ADJUST); \
|
||||
((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \
|
||||
- QUEUE_PTR_ADJUST); \
|
||||
prev->__next = mutex->__data.__list.__next; \
|
||||
mutex->__data.__list.__prev = NULL; \
|
||||
mutex->__data.__list.__next = NULL; \
|
||||
|
@ -183,27 +188,36 @@ struct pthread
|
|||
struct robust_list_head robust_head;
|
||||
};
|
||||
|
||||
# define ENQUEUE_MUTEX(mutex) \
|
||||
# define ENQUEUE_MUTEX_BOTH(mutex, val) \
|
||||
do { \
|
||||
mutex->__data.__list.__next \
|
||||
= THREAD_GETMEM (THREAD_SELF, robust_list.__next); \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list.__next, &mutex->__data.__list); \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list.__next, \
|
||||
((uintptr_t) &mutex->__data.__list) | val); \
|
||||
} while (0)
|
||||
# define DEQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
__pthread_slist_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list.__next);\
|
||||
__pthread_slist_t *runp = (__pthread_slist_t *) \
|
||||
(((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \
|
||||
if (runp == &mutex->__data.__list) \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \
|
||||
else \
|
||||
{ \
|
||||
while (runp->__next != &mutex->__data.__list) \
|
||||
runp = runp->__next; \
|
||||
__pthread_slist_t *next = (__pthread_slist_t *) \
|
||||
(((uintptr_t) runp->__next) & ~1ul); \
|
||||
while (next != &mutex->__data.__list) \
|
||||
{ \
|
||||
runp = next; \
|
||||
next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \
|
||||
} \
|
||||
\
|
||||
runp->__next = runp->__next->__next; \
|
||||
runp->__next = next->__next; \
|
||||
mutex->__data.__list.__next = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0)
|
||||
#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1)
|
||||
|
||||
/* List of cleanup buffers. */
|
||||
struct _pthread_cleanup_buffer *cleanup;
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
/* Internal mutex type value. */
|
||||
enum
|
||||
{
|
||||
PTHREAD_MUTEX_KIND_MASK_NP = 3,
|
||||
PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16,
|
||||
PTHREAD_MUTEX_ROBUST_RECURSIVE_NP
|
||||
= PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
|
@ -68,8 +69,24 @@ enum
|
|||
= PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP
|
||||
= PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
|
||||
PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP = 32,
|
||||
PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP = 64
|
||||
PTHREAD_MUTEX_PRIO_INHERIT_NP = 32,
|
||||
PTHREAD_MUTEX_PI_NORMAL_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL,
|
||||
PTHREAD_MUTEX_PI_RECURSIVE_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_PI_ERRORCHECK_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_PI_ADAPTIVE_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
|
||||
PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP,
|
||||
PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
|
||||
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
|
||||
PTHREAD_MUTEX_PRIO_PROTECT_NP = 64
|
||||
};
|
||||
#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 16
|
||||
#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0x00ff0000
|
||||
|
|
|
@ -330,9 +330,11 @@ start_thread (void *arg)
|
|||
# else
|
||||
__pthread_slist_t *robust = pd->robust_list.__next;
|
||||
# endif
|
||||
/* We let the kernel do the notification if it is able to do so. */
|
||||
/* We let the kernel do the notification if it is able to do so.
|
||||
If we have to do it here there for sure are no PI mutexes involved
|
||||
since the kernel support for them is even more recent. */
|
||||
if (__set_robust_list_avail < 0
|
||||
&& __builtin_expect (robust != &pd->robust_head, 0))
|
||||
&& __builtin_expect (robust != (void *) &pd->robust_head, 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
|
@ -348,7 +350,7 @@ start_thread (void *arg)
|
|||
|
||||
lll_robust_mutex_dead (this->__lock);
|
||||
}
|
||||
while (robust != &pd->robust_head);
|
||||
while (robust != (void *) &pd->robust_head);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ __pthread_mutex_destroy (mutex)
|
|||
return EBUSY;
|
||||
|
||||
/* Set to an invalid value. */
|
||||
dead_robust_mutex:
|
||||
mutex->__data.__kind = -1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,6 +29,11 @@ static const struct pthread_mutexattr default_attr =
|
|||
};
|
||||
|
||||
|
||||
#ifndef __ASSUME_FUTEX_LOCK_PI
|
||||
static int tpi_supported;
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
__pthread_mutex_init (mutex, mutexattr)
|
||||
pthread_mutex_t *mutex;
|
||||
|
@ -41,8 +46,7 @@ __pthread_mutex_init (mutex, mutexattr)
|
|||
imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
|
||||
|
||||
/* Sanity checks. */
|
||||
// XXX For now we don't support priority inherited or priority protected
|
||||
// XXX mutexes.
|
||||
// XXX For now we don't support priority protected mutexes.
|
||||
switch (__builtin_expect (imutexattr->mutexkind
|
||||
& PTHREAD_MUTEXATTR_PROTOCOL_MASK,
|
||||
PTHREAD_PRIO_NONE
|
||||
|
@ -51,6 +55,22 @@ __pthread_mutex_init (mutex, mutexattr)
|
|||
case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
break;
|
||||
|
||||
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
#ifndef __ASSUME_FUTEX_LOCK_PI
|
||||
if (__builtin_expect (tpi_supported == 0, 0))
|
||||
{
|
||||
int lock = 0;
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI,
|
||||
0, 0);
|
||||
assert (INTERNAL_SYSCALL_ERROR_P (ret, err));
|
||||
tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1;
|
||||
}
|
||||
if (__builtin_expect (tpi_supported < 0, 0))
|
||||
return ENOTSUP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
@ -75,11 +95,11 @@ __pthread_mutex_init (mutex, mutexattr)
|
|||
switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
|
||||
{
|
||||
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP;
|
||||
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
|
||||
break;
|
||||
|
||||
case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP;
|
||||
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
|
||||
if (PTHREAD_MUTEX_PRIO_CEILING_MASK
|
||||
== PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
|
||||
mutex->__data.__kind |= (imutexattr->mutexkind
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
|
@ -205,6 +206,134 @@ __pthread_mutex_lock (mutex)
|
|||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_PI_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
|
||||
if (robust)
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0))
|
||||
{
|
||||
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
|
||||
{
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
if (kind == PTHREAD_MUTEX_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. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int newval = id;
|
||||
#ifdef NO_INCR
|
||||
newval |= FUTEX_WAITERS;
|
||||
#endif
|
||||
oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
|
||||
newval, 0);
|
||||
|
||||
if (oldval != 0)
|
||||
{
|
||||
/* The mutex is locked. The kernel will now take care of
|
||||
everything. */
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_LOCK_PI, 1, 0);
|
||||
|
||||
if (INTERNAL_SYSCALL_ERROR_P (e, __err)
|
||||
&& (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
|
||||
|| INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK))
|
||||
{
|
||||
assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
|
||||
|| (kind != PTHREAD_MUTEX_ERRORCHECK_NP
|
||||
&& kind != PTHREAD_MUTEX_RECURSIVE_NP));
|
||||
/* ESRCH can happen only for non-robust PI mutexes where
|
||||
the owner of the lock died. */
|
||||
assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust);
|
||||
|
||||
/* Delay the thread indefinitely. */
|
||||
while (1)
|
||||
__pause_nocancel ();
|
||||
}
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
|
||||
}
|
||||
|
||||
if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0))
|
||||
{
|
||||
atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
|
||||
|
||||
/* We got the mutex. */
|
||||
mutex->__data.__count = 1;
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
||||
|
||||
ENQUEUE_MUTEX_PI (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
|
||||
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;
|
||||
}
|
||||
|
||||
if (robust
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_UNLOCK_PI, 0, 0);
|
||||
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
if (robust)
|
||||
{
|
||||
ENQUEUE_MUTEX_PI (mutex);
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
|
|
@ -30,7 +30,7 @@ pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling)
|
|||
{
|
||||
/* The low bits of __kind aren't ever changed after pthread_mutex_init,
|
||||
so we don't need a lock yet. */
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP) == 0)
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (prioceiling < 0 || __builtin_expect (prioceiling > 255, 0))
|
||||
|
|
|
@ -35,7 +35,7 @@ pthread_mutex_timedlock (mutex, abstime)
|
|||
/* We must not check ABSTIME here. If the thread does not block
|
||||
abstime must not be checked for a valid value. */
|
||||
|
||||
switch (mutex->__data.__kind)
|
||||
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
/* Recursive mutex. */
|
||||
case PTHREAD_MUTEX_RECURSIVE_NP:
|
||||
|
@ -65,7 +65,7 @@ pthread_mutex_timedlock (mutex, abstime)
|
|||
/* Error checking mutex. */
|
||||
case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (mutex->__data.__owner == id)
|
||||
if (__builtin_expect (mutex->__data.__owner == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
@ -134,7 +134,7 @@ pthread_mutex_timedlock (mutex, abstime)
|
|||
ENQUEUE_MUTEX (mutex);
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
/* Note that we deliberately exist here. If we fall
|
||||
/* 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. */
|
||||
|
@ -194,6 +194,150 @@ pthread_mutex_timedlock (mutex, abstime)
|
|||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_PI_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
|
||||
if (robust)
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0))
|
||||
{
|
||||
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
|
||||
{
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
if (kind == PTHREAD_MUTEX_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. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
|
||||
id, 0);
|
||||
|
||||
if (oldval != 0)
|
||||
{
|
||||
/* The mutex is locked. The kernel will now take care of
|
||||
everything. The timeout value must be a relative value.
|
||||
Convert it. */
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
|
||||
int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_LOCK_PI, 1, abstime);
|
||||
if (INTERNAL_SYSCALL_ERROR_P (e, __err))
|
||||
{
|
||||
if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT)
|
||||
return ETIMEDOUT;
|
||||
|
||||
if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
|
||||
|| INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)
|
||||
{
|
||||
assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
|
||||
|| (kind != PTHREAD_MUTEX_ERRORCHECK_NP
|
||||
&& kind != PTHREAD_MUTEX_RECURSIVE_NP));
|
||||
/* ESRCH can happen only for non-robust PI mutexes where
|
||||
the owner of the lock died. */
|
||||
assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH
|
||||
|| !robust);
|
||||
|
||||
/* Delay the thread until the timeout is reached.
|
||||
Then return ETIMEDOUT. */
|
||||
struct timespec reltime;
|
||||
struct timespec now;
|
||||
|
||||
INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_REALTIME,
|
||||
&now);
|
||||
reltime.tv_sec = abstime->tv_sec - now.tv_sec;
|
||||
reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec;
|
||||
if (reltime.tv_nsec < 0)
|
||||
{
|
||||
reltime.tv_nsec += 1000000000;
|
||||
--reltime.tv_sec;
|
||||
}
|
||||
if (reltime.tv_sec >= 0)
|
||||
while (__nanosleep_nocancel (&reltime, &reltime) != 0)
|
||||
continue;
|
||||
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
return INTERNAL_SYSCALL_ERRNO (e, __err);
|
||||
}
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
|
||||
}
|
||||
|
||||
if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0))
|
||||
{
|
||||
atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
|
||||
|
||||
/* We got the mutex. */
|
||||
mutex->__data.__count = 1;
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
||||
|
||||
ENQUEUE_MUTEX_PI (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
|
||||
incremented which is not correct because the old owner
|
||||
has to be discounted. */
|
||||
return EOWNERDEAD;
|
||||
}
|
||||
|
||||
if (robust
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_UNLOCK_PI, 0, 0);
|
||||
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
if (robust)
|
||||
{
|
||||
ENQUEUE_MUTEX_PI (mutex);
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
|
|
@ -152,7 +152,6 @@ __pthread_mutex_trylock (mutex)
|
|||
return EBUSY;
|
||||
}
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
|
@ -175,6 +174,129 @@ __pthread_mutex_trylock (mutex)
|
|||
|
||||
return 0;
|
||||
|
||||
case PTHREAD_MUTEX_PI_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
|
||||
if (robust)
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0))
|
||||
{
|
||||
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
|
||||
{
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
if (kind == PTHREAD_MUTEX_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. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
oldval
|
||||
= atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
|
||||
id, 0);
|
||||
|
||||
if (oldval != 0)
|
||||
{
|
||||
if ((oldval & FUTEX_OWNER_DIED) == 0)
|
||||
{
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
assert (robust);
|
||||
|
||||
/* The mutex owner died. The kernel will now take care of
|
||||
everything. */
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_TRYLOCK_PI, 0, 0);
|
||||
|
||||
if (INTERNAL_SYSCALL_ERROR_P (e, __err)
|
||||
&& INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
|
||||
{
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
}
|
||||
|
||||
if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0))
|
||||
{
|
||||
atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
|
||||
|
||||
/* We got the mutex. */
|
||||
mutex->__data.__count = 1;
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
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
|
||||
incremented which is not correct because the old owner
|
||||
has to be discounted. */
|
||||
return EOWNERDEAD;
|
||||
}
|
||||
|
||||
if (robust
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
|
||||
FUTEX_UNLOCK_PI, 0, 0);
|
||||
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
if (robust)
|
||||
{
|
||||
ENQUEUE_MUTEX_PI (mutex);
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
}
|
||||
|
||||
mutex->__data.__owner = id;
|
||||
++mutex->__data.__nusers;
|
||||
mutex->__data.__count = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
|
|
@ -119,6 +119,89 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
|||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_PI_RECURSIVE_NP:
|
||||
/* Recursive mutex. */
|
||||
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
|
||||
return EPERM;
|
||||
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return 0;
|
||||
goto continue_pi;
|
||||
|
||||
case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
|
||||
/* Recursive mutex. */
|
||||
if ((mutex->__data.__lock & FUTEX_TID_MASK)
|
||||
== THREAD_GETMEM (THREAD_SELF, tid)
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_INCONSISTENT, 0))
|
||||
{
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return ENOTRECOVERABLE;
|
||||
|
||||
goto pi_notrecoverable;
|
||||
}
|
||||
|
||||
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
|
||||
return EPERM;
|
||||
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return 0;
|
||||
|
||||
goto continue_pi;
|
||||
|
||||
case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
if ((mutex->__data.__lock & FUTEX_TID_MASK)
|
||||
!= THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
||||
return EPERM;
|
||||
|
||||
/* If the previous owner died and the caller did not succeed in
|
||||
making the state consistent, mark the mutex as unrecoverable
|
||||
and make all waiters. */
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_INCONSISTENT, 0))
|
||||
pi_notrecoverable:
|
||||
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
|
||||
|
||||
continue_pi:
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
|
||||
{
|
||||
/* Remove mutex from the list.
|
||||
Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
DEQUEUE_MUTEX (mutex);
|
||||
}
|
||||
|
||||
mutex->__data.__owner = newowner;
|
||||
if (decr)
|
||||
/* One less user. */
|
||||
--mutex->__data.__nusers;
|
||||
|
||||
/* Unlock. */
|
||||
if ((mutex->__data.__lock & FUTEX_WAITERS) != 0
|
||||
|| atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, 0,
|
||||
THREAD_GETMEM (THREAD_SELF,
|
||||
tid)))
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (__err);
|
||||
INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock,
|
||||
FUTEX_UNLOCK_PI);
|
||||
}
|
||||
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
|
@ -55,6 +55,12 @@ __pthread_cond_broadcast (cond)
|
|||
|
||||
/* Wake everybody. */
|
||||
pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
|
||||
|
||||
/* XXX: Kernel so far doesn't support requeue to PI futex. */
|
||||
if (__builtin_expect (mut->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP,
|
||||
0))
|
||||
goto wake_all;
|
||||
|
||||
/* lll_futex_requeue returns 0 for success and non-zero
|
||||
for errors. */
|
||||
if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1,
|
||||
|
|
|
@ -25,7 +25,7 @@ libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
|
|||
|
||||
gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \
|
||||
lowlevelbarrier.sym unwindbuf.sym \
|
||||
lowlevelrobustlock.sym
|
||||
lowlevelrobustlock.sym pthread-pi-defines.sym
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),posix)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Define POSIX options for Linux.
|
||||
Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2004, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
|
@ -79,6 +79,9 @@
|
|||
/* We support user-defined stacks. */
|
||||
#define _POSIX_THREAD_ATTR_STACKADDR 200112L
|
||||
|
||||
/* We support priority inheritence. */
|
||||
#define _POSIX_THREAD_PRIO_INHERIT 200112L
|
||||
|
||||
/* We support POSIX.1b semaphores. */
|
||||
#define _POSIX_SEMAPHORES 200112L
|
||||
|
||||
|
@ -171,8 +174,7 @@
|
|||
/* Typed memory objects are not available. */
|
||||
#define _POSIX_TYPED_MEMORY_OBJECTS -1
|
||||
|
||||
/* No support for priority inheritance or protection so far. */
|
||||
#define _POSIX_THREAD_PRIO_INHERIT -1
|
||||
/* No support for priority protection so far. */
|
||||
#define _POSIX_THREAD_PRIO_PROTECT -1
|
||||
|
||||
#endif /* posix_opt.h */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include <shlib-compat.h>
|
||||
#include <lowlevelcond.h>
|
||||
#include <kernel-features.h>
|
||||
#include <pthread-pi-defines.h>
|
||||
|
||||
#ifdef UP
|
||||
# define LOCK
|
||||
|
@ -94,6 +95,10 @@ __pthread_cond_broadcast:
|
|||
8: cmpl $-1, %edi
|
||||
je 9f
|
||||
|
||||
/* XXX: The kernel so far doesn't support requeue to PI futex. */
|
||||
testl $PI_BIT, MUTEX_KIND(%edi)
|
||||
jne 9f
|
||||
|
||||
/* Wake up all threads. */
|
||||
movl $FUTEX_CMP_REQUEUE, %ecx
|
||||
movl $SYS_futex, %eax
|
||||
|
|
6
nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym
Normal file
6
nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <pthreadP.h>
|
||||
|
||||
-- These PI macros are used by assembly code.
|
||||
|
||||
MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind)
|
||||
PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP
|
|
@ -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.
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include <shlib-compat.h>
|
||||
#include <lowlevelcond.h>
|
||||
#include <kernel-features.h>
|
||||
#include <pthread-pi-defines.h>
|
||||
|
||||
#ifdef UP
|
||||
# define LOCK
|
||||
|
@ -80,6 +81,10 @@ __pthread_cond_broadcast:
|
|||
8: cmpq $-1, %r8
|
||||
je 9f
|
||||
|
||||
/* XXX: The kernel so far doesn't support requeue to PI futex. */
|
||||
testl $PI_BIT, MUTEX_KIND(%r8)
|
||||
jne 9f
|
||||
|
||||
/* Wake up all threads. */
|
||||
movl $FUTEX_CMP_REQUEUE, %esi
|
||||
movl $SYS_futex, %eax
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
|
||||
|
@ -19,6 +19,12 @@
|
|||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifndef ATTR
|
||||
# define ATTR NULL
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
|
@ -26,12 +32,24 @@ do_test (void)
|
|||
{
|
||||
pthread_mutex_t m;
|
||||
|
||||
if (pthread_mutex_init (&m, NULL) != 0)
|
||||
int e = pthread_mutex_init (&m, ATTR);
|
||||
if (ATTR != NULL && e == ENOTSUP)
|
||||
{
|
||||
puts ("cannot support selected type of mutexes");
|
||||
return 0;
|
||||
}
|
||||
else if (e != 0)
|
||||
{
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0)
|
||||
{
|
||||
puts ("mutexattr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_lock failed");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
|
@ -105,115 +105,134 @@ do_test (void)
|
|||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_init failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0)
|
||||
{
|
||||
puts ("mutexattr_settype failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
e = pthread_mutex_init (&m, &a);
|
||||
if (e != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((e = pthread_mutex_unlock (&m)) == 0)
|
||||
e = pthread_mutex_unlock (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("1st mutex_unlock succeeded");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
else if (e != EPERM)
|
||||
{
|
||||
puts ("1st mutex_unlock error != EPERM");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_lock failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((e = pthread_mutex_lock (&m)) == 0)
|
||||
e = pthread_mutex_lock (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("2nd mutex_lock succeeded");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
else if (e != EDEADLK)
|
||||
{
|
||||
puts ("2nd mutex_lock error != EDEADLK");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("1st barrier_wait failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
puts ("2nd mutex_unlock failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((e = pthread_mutex_unlock (&m)) == 0)
|
||||
e = pthread_mutex_unlock (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("3rd mutex_unlock succeeded");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
else if (e != EPERM)
|
||||
{
|
||||
puts ("3rd mutex_unlock error != EPERM");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("2nd barrier_wait failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_join (th, NULL) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_destroy (&m) != 0)
|
||||
{
|
||||
puts ("mutex_destroy failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_destroy (&b) != 0)
|
||||
{
|
||||
puts ("barrier_destroy failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_destroy (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_destroy failed");
|
||||
exit (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
|
@ -113,8 +113,25 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int e;
|
||||
e = pthread_mutex_init (&m, &a);
|
||||
if (e != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
@ -162,7 +179,7 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
|
||||
|
@ -42,6 +42,8 @@ do_test (void)
|
|||
char *p;
|
||||
int err;
|
||||
int s;
|
||||
pthread_barrier_t *b;
|
||||
pthread_barrierattr_t ba;
|
||||
|
||||
fd = mkstemp (tmpfname);
|
||||
if (fd == -1)
|
||||
|
@ -70,9 +72,12 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
|
||||
m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t) - 1)
|
||||
& ~(__alignof (pthread_mutex_t) - 1));
|
||||
p = (char *) (m + 1);
|
||||
b = (pthread_barrier_t *) (((uintptr_t) (m + 1)
|
||||
+ __alignof (pthread_barrier_t) - 1)
|
||||
& ~(__alignof (pthread_barrier_t) - 1));
|
||||
p = (char *) (b + 1);
|
||||
|
||||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
|
@ -110,8 +115,23 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((err = pthread_mutex_init (m, &a)) != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (err == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
@ -128,6 +148,30 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrierattr_init (&ba) != 0)
|
||||
{
|
||||
puts ("barrierattr_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
|
||||
{
|
||||
puts ("barrierattr_setpshared failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_init (b, &ba, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrierattr_destroy (&ba) != 0)
|
||||
{
|
||||
puts ("barrierattr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = pthread_mutex_trylock (m);
|
||||
if (err == 0)
|
||||
{
|
||||
|
@ -142,6 +186,12 @@ do_test (void)
|
|||
|
||||
*p = 0;
|
||||
|
||||
if (pthread_mutex_unlock (m) != 0)
|
||||
{
|
||||
puts ("parent: 1st mutex_unlock failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("going to fork now");
|
||||
pid = fork ();
|
||||
if (pid == -1)
|
||||
|
@ -151,7 +201,19 @@ do_test (void)
|
|||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/* Play some lock ping-pong. It's our turn to unlock first. */
|
||||
if (pthread_mutex_lock (m) != 0)
|
||||
{
|
||||
puts ("child: mutex_lock failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("child: barrier_wait failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((*p)++ != 0)
|
||||
{
|
||||
puts ("child: *p != 0");
|
||||
|
@ -160,7 +222,7 @@ do_test (void)
|
|||
|
||||
if (pthread_mutex_unlock (m) != 0)
|
||||
{
|
||||
puts ("child: 1st mutex_unlock failed");
|
||||
puts ("child: mutex_unlock failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -168,6 +230,13 @@ do_test (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
int e = pthread_barrier_wait (b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("parent: barrier_wait failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (m) != 0)
|
||||
{
|
||||
puts ("parent: 2nd mutex_lock failed");
|
||||
|
@ -180,6 +249,24 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock (m) != 0)
|
||||
{
|
||||
puts ("parent: 2nd mutex_unlock failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_destroy (m) != 0)
|
||||
{
|
||||
puts ("mutex_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_destroy (b) != 0)
|
||||
{
|
||||
puts ("barrier_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("parent done");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
|
||||
|
@ -52,8 +52,24 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = pthread_mutex_init (&m, &a);
|
||||
if (err != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (err == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
|
||||
|
@ -21,6 +21,12 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifndef ATTR
|
||||
# define ATTR NULL
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
|
@ -28,12 +34,24 @@ do_test (void)
|
|||
{
|
||||
pthread_mutex_t m;
|
||||
|
||||
if (pthread_mutex_init (&m, NULL) != 0)
|
||||
int e = pthread_mutex_init (&m, ATTR);
|
||||
if (ATTR != NULL && e == ENOTSUP)
|
||||
{
|
||||
puts ("cannot support selected type of mutexes");
|
||||
e = pthread_mutex_init (&m, NULL);
|
||||
}
|
||||
if (e != 0)
|
||||
{
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0)
|
||||
{
|
||||
puts ("mutexattr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("1st mutex_lock failed");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
|
@ -17,17 +17,19 @@
|
|||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#ifndef INIT
|
||||
# define INIT PTHREAD_MUTEX_INITIALIZER
|
||||
#ifndef TYPE
|
||||
# define TYPE PTHREAD_MUTEX_DEFAULT
|
||||
#endif
|
||||
|
||||
|
||||
static pthread_mutex_t lock = INIT;
|
||||
static pthread_mutex_t lock;
|
||||
|
||||
|
||||
#define ROUNDS 1000
|
||||
|
@ -65,6 +67,48 @@ tf (void *arg)
|
|||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_mutexattr_t a;
|
||||
|
||||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_settype (&a, TYPE) != 0)
|
||||
{
|
||||
puts ("mutexattr_settype failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int e = pthread_mutex_init (&lock, &a);
|
||||
if (e != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_destroy (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_attr_t at;
|
||||
pthread_t th[N];
|
||||
int cnt;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP
|
||||
#include "tst-mutex7.c"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
||||
|
||||
|
@ -88,8 +88,24 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int e;
|
||||
if ((e = pthread_mutex_init (m, &a)) != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI mutexes unsupported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
@ -138,7 +154,7 @@ do_test (void)
|
|||
ts.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
int e = pthread_mutex_timedlock (m, &ts);
|
||||
e = pthread_mutex_timedlock (m, &ts);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("child: mutex_timedlock succeeded");
|
||||
|
|
27
nptl/tst-mutexpi1.c
Normal file
27
nptl/tst-mutexpi1.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_mutexattr_t a;
|
||||
|
||||
static void
|
||||
prepare (void)
|
||||
{
|
||||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("mutexattr_setprotocol failed");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#define PREPARE(argc, argv) prepare ()
|
||||
|
||||
|
||||
#define ATTR &a
|
||||
#include "tst-mutex1.c"
|
2
nptl/tst-mutexpi2.c
Normal file
2
nptl/tst-mutexpi2.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex2.c"
|
2
nptl/tst-mutexpi3.c
Normal file
2
nptl/tst-mutexpi3.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex3.c"
|
2
nptl/tst-mutexpi4.c
Normal file
2
nptl/tst-mutexpi4.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex4.c"
|
2
nptl/tst-mutexpi5.c
Normal file
2
nptl/tst-mutexpi5.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex5.c"
|
2
nptl/tst-mutexpi5a.c
Normal file
2
nptl/tst-mutexpi5a.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex5a.c"
|
27
nptl/tst-mutexpi6.c
Normal file
27
nptl/tst-mutexpi6.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_mutexattr_t a;
|
||||
|
||||
static void
|
||||
prepare (void)
|
||||
{
|
||||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("mutexattr_setprotocol failed");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#define PREPARE(argc, argv) prepare ()
|
||||
|
||||
|
||||
#define ATTR &a
|
||||
#include "tst-mutex6.c"
|
2
nptl/tst-mutexpi7.c
Normal file
2
nptl/tst-mutexpi7.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex7.c"
|
2
nptl/tst-mutexpi7a.c
Normal file
2
nptl/tst-mutexpi7a.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex7a.c"
|
2
nptl/tst-mutexpi8.c
Normal file
2
nptl/tst-mutexpi8.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex8.c"
|
2
nptl/tst-mutexpi9.c
Normal file
2
nptl/tst-mutexpi9.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-mutex9.c"
|
|
@ -97,6 +97,30 @@ do_test (void)
|
|||
puts ("mutexattr_setrobust failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int e = pthread_mutex_init (&m1, &a);
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI robust mutexes not supported");
|
||||
return 0;
|
||||
}
|
||||
else if (e != 0)
|
||||
{
|
||||
puts ("mutex_init m1 failed");
|
||||
return 1;
|
||||
}
|
||||
pthread_mutex_destroy (&m1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NOT_CONSISTENT
|
||||
if (pthread_mutex_init (&m1, &a) != 0)
|
||||
{
|
||||
|
@ -236,14 +260,14 @@ do_test (void)
|
|||
e = pthread_mutex_unlock (&m1);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("%ld: mutex_unlock m1 failed\n", round);
|
||||
printf ("%ld: mutex_unlock m1 failed with %d\n", round, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
e = pthread_mutex_unlock (&m2);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("%ld: mutex_unlock m2 failed\n", round);
|
||||
printf ("%ld: mutex_unlock m2 failed with %d\n", round, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
@ -95,8 +95,25 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int e;
|
||||
e = pthread_mutex_init (&m, &a);
|
||||
if (e != 0)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
puts ("PI robust mutexes not supported");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
@ -123,7 +140,7 @@ do_test (void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("parent: barrier_wait failed in round %ld\n", n + 1);
|
||||
|
@ -164,7 +181,7 @@ do_test (void)
|
|||
}
|
||||
}
|
||||
|
||||
int e = pthread_mutex_lock (&m);
|
||||
e = pthread_mutex_lock (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("parent: 2nd mutex_lock succeeded");
|
||||
|
|
|
@ -15,7 +15,7 @@ static void prepare (void);
|
|||
#define PREPARE(argc, argv) prepare ()
|
||||
static int do_test (void);
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#define TIMEOUT 3
|
||||
#define TIMEOUT 5
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
|
||||
|
@ -173,6 +173,13 @@ do_test (void)
|
|||
puts ("mutexattr_setpshared failed");
|
||||
return 1;
|
||||
}
|
||||
#ifdef ENABLE_PI
|
||||
if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0)
|
||||
{
|
||||
puts ("pthread_mutexattr_setprotocol failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int round = 1; round <= ROUNDS; ++round)
|
||||
{
|
||||
|
@ -181,7 +188,11 @@ do_test (void)
|
|||
int e = pthread_mutex_init (&map[n], &ma);
|
||||
if (e == ENOTSUP)
|
||||
{
|
||||
#ifdef ENABLE_PI
|
||||
puts ("cannot support pshared robust PI mutexes");
|
||||
#else
|
||||
puts ("cannot support pshared robust mutexes");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (e != 0)
|
||||
|
|
2
nptl/tst-robustpi1.c
Normal file
2
nptl/tst-robustpi1.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust1.c"
|
2
nptl/tst-robustpi2.c
Normal file
2
nptl/tst-robustpi2.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust2.c"
|
2
nptl/tst-robustpi3.c
Normal file
2
nptl/tst-robustpi3.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust3.c"
|
2
nptl/tst-robustpi4.c
Normal file
2
nptl/tst-robustpi4.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust4.c"
|
2
nptl/tst-robustpi5.c
Normal file
2
nptl/tst-robustpi5.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust5.c"
|
2
nptl/tst-robustpi6.c
Normal file
2
nptl/tst-robustpi6.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust6.c"
|
2
nptl/tst-robustpi7.c
Normal file
2
nptl/tst-robustpi7.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust7.c"
|
2
nptl/tst-robustpi8.c
Normal file
2
nptl/tst-robustpi8.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ENABLE_PI 1
|
||||
#include "tst-robust8.c"
|
Loading…
Add table
Reference in a new issue