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:
Ulrich Drepper 2006-07-29 04:42:09 +00:00
parent 6822f05652
commit df47504c78
49 changed files with 1083 additions and 89 deletions

View file

@ -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

View file

@ -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 \

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -30,7 +30,6 @@ __pthread_mutex_destroy (mutex)
return EBUSY;
/* Set to an invalid value. */
dead_robust_mutex:
mutex->__data.__kind = -1;
return 0;

View file

@ -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

View file

@ -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;

View file

@ -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))

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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)

View file

@ -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 */

View file

@ -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

View 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

View file

@ -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

View file

@ -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");

View file

@ -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;

View file

@ -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");

View file

@ -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");
}

View file

@ -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;
}

View file

@ -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");

View file

@ -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;

View file

@ -1,2 +1,2 @@
#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP
#include "tst-mutex7.c"

View file

@ -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
View 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
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex2.c"

2
nptl/tst-mutexpi3.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex3.c"

2
nptl/tst-mutexpi4.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex4.c"

2
nptl/tst-mutexpi5.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex5.c"

2
nptl/tst-mutexpi5a.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex5a.c"

27
nptl/tst-mutexpi6.c Normal file
View 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
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex7.c"

2
nptl/tst-mutexpi7a.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex7a.c"

2
nptl/tst-mutexpi8.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex8.c"

2
nptl/tst-mutexpi9.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-mutex9.c"

View file

@ -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;
}

View file

@ -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");

View file

@ -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
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust1.c"

2
nptl/tst-robustpi2.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust2.c"

2
nptl/tst-robustpi3.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust3.c"

2
nptl/tst-robustpi4.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust4.c"

2
nptl/tst-robustpi5.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust5.c"

2
nptl/tst-robustpi6.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust6.c"

2
nptl/tst-robustpi7.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust7.c"

2
nptl/tst-robustpi8.c Normal file
View file

@ -0,0 +1,2 @@
#define ENABLE_PI 1
#include "tst-robust8.c"