--- libc/nptl/tst-mutex7.c.jj 2004-03-24 12:16:55.000000000 +0100 +++ libc/nptl/tst-mutex7.c 2006-04-05 14:10:55.000000000 +0200 @@ -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 , 2002. @@ -17,17 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include +#include #include -#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; + if ((e = pthread_mutex_init (&lock, &a)) != 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; --- libc/nptl/tst-mutex2.c.jj 2003-03-17 03:48:28.000000000 +0100 +++ libc/nptl/tst-mutex2.c 2006-04-05 13:39:39.000000000 +0200 @@ -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 , 2002. @@ -105,115 +105,130 @@ 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; + } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; } +#endif - if (pthread_mutex_init (&m, &a) != 0) + 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"); - 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) { 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) { 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) { 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; --- libc/nptl/Makefile.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/Makefile 2006-04-05 15:07:27.000000000 +0200 @@ -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 \ --- libc/nptl/tst-mutex8.c.jj 2003-06-23 01:43:35.000000000 +0200 +++ libc/nptl/tst-mutex8.c 2006-04-05 14:04:23.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -320,10 +320,41 @@ do_test (void) return 1; } + pthread_mutexattr_t ma; + if (pthread_mutexattr_init (&ma) != 0) + { + puts ("1st mutexattr_init failed"); + return 1; + } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } + + pthread_mutex_t pim; + int e = pthread_mutex_init (&pim, &ma); + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } + if (e != 0) + { + puts ("mutex_init failed"); + return 1; + } + pthread_mutex_destroy (&pim); +#endif puts ("check normal mutex"); - int res = check_type ("normal", NULL); + int res = check_type ("normal", &ma); + if (pthread_mutexattr_destroy (&ma) != 0) + { + puts ("1st mutexattr_destroy failed"); + return 1; + } - pthread_mutexattr_t ma; if (pthread_mutexattr_init (&ma) != 0) { puts ("1st mutexattr_init failed"); @@ -334,6 +365,13 @@ do_test (void) puts ("1st mutexattr_settype failed"); return 1; } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif puts ("check recursive mutex"); res |= check_type ("recursive", &ma); if (pthread_mutexattr_destroy (&ma) != 0) @@ -352,6 +390,13 @@ do_test (void) puts ("2nd mutexattr_settype failed"); return 1; } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif puts ("check error-checking mutex"); res |= check_type ("error-checking", &ma); if (pthread_mutexattr_destroy (&ma) != 0) --- libc/nptl/tst-mutexpi9.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi9.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex9.c" --- libc/nptl/tst-robust8.c.jj 2006-03-28 06:12:46.000000000 +0200 +++ libc/nptl/tst-robust8.c 2006-04-05 15:12:00.000000000 +0200 @@ -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) --- libc/nptl/tst-robustpi5.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi5.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust5.c" --- libc/nptl/pthread_mutex_init.c.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthread_mutex_init.c 2006-04-05 10:19:38.000000000 +0200 @@ -41,11 +41,21 @@ __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. - if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) - != (PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)) - return ENOTSUP; + // XXX For now we don't support priority protected mutexes. + switch ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + >> PTHREAD_MUTEXATTR_PROTOCOL_SHIFT) + { + case PTHREAD_PRIO_NONE: + break; + case PTHREAD_PRIO_INHERIT: +#ifndef __ASSUME_SET_ROBUST_LIST + if (__set_robust_list_avail < 0) + return ENOTSUP; +#endif + break; + default: + return ENOTSUP; + } /* Clear the whole variable. */ memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); @@ -68,10 +78,10 @@ __pthread_mutex_init (mutex, mutexattr) >> PTHREAD_MUTEXATTR_PROTOCOL_SHIFT) { case PTHREAD_PRIO_INHERIT: - mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP; + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; break; case PTHREAD_PRIO_PROTECT: - 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 --- libc/nptl/tst-mutex1.c.jj 2002-11-26 23:49:18.000000000 +0100 +++ libc/nptl/tst-mutex1.c 2006-04-05 13:35:52.000000000 +0200 @@ -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 , 2002. @@ -19,6 +19,12 @@ #include #include +#include + + +#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"); --- libc/nptl/tst-mutexpi5.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi5.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex5.c" --- libc/nptl/tst-mutexpi4.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi4.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex4.c" --- libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h.jj 2006-03-17 08:55:20.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h 2006-04-05 11:20:54.000000000 +0200 @@ -35,6 +35,9 @@ #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ --- libc/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h.jj 2005-03-01 10:34:41.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h 2006-04-05 10:05:01.000000000 +0200 @@ -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 @@ -172,7 +175,6 @@ #define _POSIX_TYPED_MEMORY_OBJECTS -1 /* No support for priority inheritance or protection so far. */ -#define _POSIX_THREAD_PRIO_INHERIT -1 #define _POSIX_THREAD_PRIO_PROTECT -1 #endif /* posix_opt.h */ --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h.jj 2006-03-06 11:12:11.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h 2006-04-05 11:21:12.000000000 +0200 @@ -35,6 +35,9 @@ #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ --- libc/nptl/tst-mutex6.c.jj 2002-11-26 23:49:38.000000000 +0100 +++ libc/nptl/tst-mutex6.c 2006-04-05 14:13:36.000000000 +0200 @@ -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 , 2002. @@ -21,6 +21,12 @@ #include #include #include +#include + + +#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"); --- libc/nptl/tst-robustpi7.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi7.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust7.c" --- libc/nptl/pthread_mutex_timedlock.c.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthread_mutex_timedlock.c 2006-04-05 11:12:08.000000000 +0200 @@ -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,148 @@ 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) + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + 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 (&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 (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 (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + default: /* Correct code cannot set any other type. */ return EINVAL; --- libc/nptl/pthread_mutex_lock.c.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthread_mutex_lock.c 2006-04-05 10:41:06.000000000 +0200 @@ -20,6 +20,7 @@ #include #include #include +#include #include "pthreadP.h" #include @@ -205,6 +206,132 @@ __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) + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + 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 (); + } + + 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 (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 (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + default: /* Correct code cannot set any other type. */ return EINVAL; --- libc/nptl/tst-mutexpi6.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi6.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,27 @@ +#include +#include +#include + + +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" --- libc/nptl/tst-mutex7a.c.jj 2004-03-24 07:22:38.000000000 +0100 +++ libc/nptl/tst-mutex7a.c 2006-04-05 10:05:01.000000000 +0200 @@ -1,2 +1,2 @@ -#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP #include "tst-mutex7.c" --- libc/nptl/tst-mutex4.c.jj 2004-10-05 09:04:45.000000000 +0200 +++ libc/nptl/tst-mutex4.c 2006-04-05 13:51:14.000000000 +0200 @@ -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 , 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"); } --- libc/nptl/tst-mutexpi3.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi3.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex3.c" --- libc/nptl/tst-robust1.c.jj 2006-02-20 19:09:19.000000000 +0100 +++ libc/nptl/tst-robust1.c 2006-04-05 14:41:01.000000000 +0200 @@ -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 + { + puts ("mutex_init m1 failed"); + return 1; + } + pthread_mutex_destroy (&m1); + } +#endif + #ifndef NOT_CONSISTENT if (pthread_mutex_init (&m1, &a) != 0) { --- libc/nptl/pthreadP.h.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthreadP.h 2006-04-05 10:20:10.000000000 +0200 @@ -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 --- libc/nptl/tst-mutexpi7a.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi7a.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex7a.c" --- libc/nptl/tst-robustpi6.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi6.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust6.c" --- libc/nptl/tst-mutexpi7.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi7.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex7.c" --- libc/nptl/pthread_mutex_unlock.c.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthread_mutex_unlock.c 2006-04-05 12:33:36.000000000 +0200 @@ -119,6 +119,87 @@ __pthread_mutex_unlock_usercnt (mutex, d 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. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + 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; --- libc/nptl/tst-mutex9.c.jj 2004-10-05 09:04:45.000000000 +0200 +++ libc/nptl/tst-mutex9.c 2006-04-05 14:05:18.000000000 +0200 @@ -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 , 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"); --- libc/nptl/pthread_mutex_trylock.c.jj 2006-03-28 09:13:36.000000000 +0200 +++ libc/nptl/pthread_mutex_trylock.c 2006-04-05 11:52:53.000000000 +0200 @@ -175,6 +175,127 @@ __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) + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + 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 (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; --- libc/nptl/tst-robustpi8.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi8.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust8.c" --- libc/nptl/tst-robustpi4.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi4.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust4.c" --- libc/nptl/tst-robust7.c.jj 2005-12-27 20:42:21.000000000 +0100 +++ libc/nptl/tst-robust7.c 2006-04-05 15:11:50.000000000 +0200 @@ -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 , 2005. @@ -95,8 +95,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 robust mutexes not supported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } @@ -123,7 +139,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 +180,7 @@ do_test (void) } } - int e = pthread_mutex_lock (&m); + e = pthread_mutex_lock (&m); if (e == 0) { puts ("parent: 2nd mutex_lock succeeded"); --- libc/nptl/tst-mutexpi2.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi2.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex2.c" --- libc/nptl/pthread_mutex_setprioceiling.c.jj 2006-02-28 10:36:05.000000000 +0100 +++ libc/nptl/pthread_mutex_setprioceiling.c 2006-04-05 12:24:07.000000000 +0200 @@ -30,7 +30,7 @@ pthread_mutex_setprioceiling (mutex, pri { /* 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)) --- libc/nptl/tst-robustpi3.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi3.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust3.c" --- libc/nptl/tst-mutex3.c.jj 2003-02-15 20:21:53.000000000 +0100 +++ libc/nptl/tst-mutex3.c 2006-04-05 13:40:24.000000000 +0200 @@ -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 , 2002. @@ -113,8 +113,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; } @@ -162,7 +178,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"); --- libc/nptl/tst-mutex5.c.jj 2004-03-24 12:16:54.000000000 +0100 +++ libc/nptl/tst-mutex5.c 2006-04-05 14:10:37.000000000 +0200 @@ -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 , 2002. @@ -52,8 +52,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; } --- libc/nptl/tst-robustpi2.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi2.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust2.c" --- libc/nptl/tst-mutexpi5a.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi5a.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex5a.c" --- libc/nptl/tst-mutexpi8.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi8.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex8.c" --- libc/nptl/tst-mutexpi1.c.jj 2006-04-05 10:05:01.000000000 +0200 +++ libc/nptl/tst-mutexpi1.c 2006-04-05 10:05:01.000000000 +0200 @@ -0,0 +1,27 @@ +#include +#include +#include + + +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" --- libc/nptl/tst-robustpi1.c.jj 2006-04-05 15:06:35.000000000 +0200 +++ libc/nptl/tst-robustpi1.c 2006-04-05 15:06:35.000000000 +0200 @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust1.c" Jakub