about summary refs log tree commit diff
path: root/nptl
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-12-27 14:48:14 +0000
committerJakub Jelinek <jakub@redhat.com>2005-12-27 14:48:14 +0000
commit64cd3e83c9993f3c1a3c24ea3030a22ccf35e12d (patch)
tree8808fad08bb8677b0e0d2158c65096eae5484767 /nptl
parente3173d2c996d8e30dfe44e9bf530881da6df6aaa (diff)
downloadglibc-64cd3e83c9993f3c1a3c24ea3030a22ccf35e12d.tar.gz
glibc-64cd3e83c9993f3c1a3c24ea3030a22ccf35e12d.tar.xz
glibc-64cd3e83c9993f3c1a3c24ea3030a22ccf35e12d.zip
Updated to fedora-glibc-20051227T1426
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog95
-rw-r--r--nptl/Makefile11
-rw-r--r--nptl/Versions5
-rw-r--r--nptl/descr.h45
-rw-r--r--nptl/libc-cancellation.c4
-rw-r--r--nptl/pt-cleanup.c5
-rw-r--r--nptl/pthreadP.h28
-rw-r--r--nptl/pthread_create.c29
-rw-r--r--nptl/pthread_join.c4
-rw-r--r--nptl/pthread_mutex_consistent.c36
-rw-r--r--nptl/pthread_mutex_destroy.c5
-rw-r--r--nptl/pthread_mutex_init.c14
-rw-r--r--nptl/pthread_mutex_lock.c76
-rw-r--r--nptl/pthread_mutex_timedlock.c90
-rw-r--r--nptl/pthread_mutex_trylock.c97
-rw-r--r--nptl/pthread_mutex_unlock.c58
-rw-r--r--nptl/pthread_mutexattr_getpshared.c6
-rw-r--r--nptl/pthread_mutexattr_getrobust.c36
-rw-r--r--nptl/pthread_mutexattr_gettype.c6
-rw-r--r--nptl/pthread_mutexattr_setpshared.c8
-rw-r--r--nptl/pthread_mutexattr_setrobust.c43
-rw-r--r--nptl/pthread_mutexattr_settype.c6
-rw-r--r--nptl/pthread_timedjoin.c4
-rw-r--r--nptl/pthread_tryjoin.c4
-rw-r--r--nptl/sysdeps/pthread/pthread.h53
-rw-r--r--nptl/sysdeps/pthread/sigaction.c8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/register-atfork.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/unregister-atfork.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h15
-rw-r--r--nptl/tst-cancel24.cc113
-rw-r--r--nptl/tst-once3.c7
-rw-r--r--nptl/tst-robust1.c245
-rw-r--r--nptl/tst-robust2.c3
-rw-r--r--nptl/tst-robust3.c20
-rw-r--r--nptl/tst-robust4.c2
-rw-r--r--nptl/tst-robust5.c2
-rw-r--r--nptl/tst-robust6.c2
-rw-r--r--nptl/tst-typesizes.c68
-rw-r--r--nptl/unwind.c4
-rw-r--r--nptl/version.c4
43 files changed, 1187 insertions, 98 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index cc4fc0ec5d..7c0030cd09 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,98 @@
+2005-12-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthreadP.h: Define PTHREAD_MUTEX_ROBUST_PRIVATE_NP,
+	PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP,
+	PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP,
+	PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP,
+	PTHREAD_MUTEXATTR_FLAG_ROBUST, PTHREAD_MUTEXATTR_FLAG_PSHARED,
+	and PTHREAD_MUTEXATTR_FLAG_BITS.
+	* descr.h (struct pthread): Add robust_list field and define
+	ENQUEUE_MUTEX and DEQUEUE_MUTEX macros.
+	* pthread_mutexattr_getrobust.c: New file.
+	* pthread_mutexattr_setrobust.c: New file.
+	* pthread_mutex_consistent.c: New file.
+	* sysdeps/pthread/pthread.h: Declare pthread_mutexattr_getrobust,
+	pthread_mutexattr_setrobust, and pthread_mutex_consistent.
+	Define PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP.
+	Adjust pthread_mutex_t initializers.
+	* nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Add __next
+	field to pthread_mutex_t.
+	* nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Add __next
+	and __prev field to pthread_mutex_t.
+	* Versions [GLIBC_2.4]: Export pthread_mutexattr_getrobust_np,
+	pthread_mutexattr_setrobust_np, and pthread_mutex_consistent_np.
+	* pthread_mutexattr_getpshared.c: Use PTHREAD_MUTEXATTR_FLAG_PSHARED
+	and PTHREAD_MUTEXATTR_FLAG_BITS macros instead of magic numbers.
+	* pthread_mutexattr_gettype.c: Likewise.
+	* pthread_mutexattr_setpshared.c: Likewise.
+	* pthread_mutexattr_settype.c: Likewise.
+	* pthread_mutex_init.c: Reject robust+pshared attribute for now.
+	Initialize mutex kind according to robust flag.
+	* pthread_mutex_lock.c: Implement local robust mutex.
+	* pthread_mutex_timedlock.c: Likewise.
+	* pthread_mutex_trylock.c: Likewise.
+	* pthread_mutex_unlock.c: Likewise.
+	* pthread_create.c (start_thread): Mark robust mutexes which remained
+	locked as dead.
+	* 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.
+	* Makefile (libpthread-routines): Add pthread_mutexattr_getrobust,
+	pthread_mutexattr_setrobust, and pthread_mutex_consistent.
+	(tests): Add tst-robust1, tst-robust2, tst-robust3, tst-robust4,
+	tst-robust5, tst-robust6, and tst-robust7.
+
+	* tst-typesizes.c: New file.
+	* Makefile (tests): Add tst-typesizes.
+
+	* tst-once3.c: More debug output.
+
+2005-12-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread_mutex_trylock.c (__pthread_mutex_trylock): Add break
+	missing after last change.
+
+	* version.c: Update cpoyright year.
+
+2005-12-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread_mutex_destroy.c: Set mutex type to an invalid value.
+	* pthread_mutex_lock.c: Return EINVAL for invalid mutex type.
+	* pthread_mutex_trylock.c: Likewise.
+	* pthread_mutex_timedlock.c: Likewise.
+	* pthread_mutex_unlock.c: Likewise.
+
+2005-12-22  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/pthread/sigaction.c: Use "" instead of <> to include self,
+	so that #include_next's search location is not reset to the -I..
+	directory where <nptl/...> can be found.
+
+2005-12-22  Ulrich Drepper  <drepper@redhat.com>
+
+	[BZ #1913]
+	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait):
+	Fix unwind info.  Remove useless branch prediction prefix.
+	* tst-cancel24.cc: New file.
+	* Makefile: Add rules to build and run tst-cancel24.
+
+2005-12-21  Roland McGrath  <roland@redhat.com>
+
+	* libc-cancellation.c: Use <> rather than "" #includes.
+	* pt-cleanup.c: Likewise.
+	* pthread_create.c: Likewise.
+	* pthread_join.c: Likewise.
+	* pthread_timedjoin.c: Likewise.
+	* pthread_tryjoin.c: Likewise.
+	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Likewise.
+	* sysdeps/unix/sysv/linux/register-atfork.c: Likewise.
+	* sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise.
+	* unwind.c: Likewise.
+
 2005-12-19  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
 
 	* sysdeps/sh/tcb-offsets.sym: Add POINTER_GUARD.
diff --git a/nptl/Makefile b/nptl/Makefile
index dbe84b1c4f..a3b11730a1 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -116,6 +116,8 @@ libpthread-routines = init vars events version \
 		      pthread_kill_other_threads \
 		      pthread_getaffinity pthread_setaffinity \
 		      pthread_attr_getaffinity pthread_attr_setaffinity \
+		      pthread_mutexattr_getrobust pthread_mutexattr_setrobust \
+		      pthread_mutex_consistent \
 		      cleanup_routine unwind-forcedunwind
 #		      pthread_setuid pthread_seteuid pthread_setreuid \
 #		      pthread_setresuid \
@@ -189,7 +191,8 @@ CFLAGS-pt-system.c = -fexceptions
 omit-deps = $(unix-syscalls:%=ptw-%)
 
 
-tests = tst-attr1 tst-attr2 tst-attr3 \
+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-spin1 tst-spin2 tst-spin3 \
@@ -197,6 +200,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
 	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
 	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
 	tst-cond20 tst-cond21 \
+	tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
+	tst-robust6 tst-robust7 \
 	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 \
@@ -220,7 +225,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
 	tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
-	tst-cancel21 tst-cancel22 tst-cancel23 \
+	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 \
 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
 	tst-flock1 tst-flock2 \
 	tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
@@ -479,6 +484,8 @@ $(objpfx)tst-clock2: $(common-objpfx)rt/librt.a
 $(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.a
 endif
 
+LDFLAGS-tst-cancel24 = -lstdc++
+
 extra-B-pthread.so = -B$(common-objpfx)nptl/
 $(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs))
 $(objpfx)libpthread.so: +preinit += $(addprefix $(objpfx),$(crti-objs))
diff --git a/nptl/Versions b/nptl/Versions
index 79bf190c3a..2b4dd01ab5 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -232,6 +232,11 @@ libpthread {
     pthread_setschedprio;
   }
 
+  GLIBC_2.4 {
+    pthread_mutexattr_getrobust_np; pthread_mutexattr_setrobust_np;
+    pthread_mutex_consistent_np;
+  };
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
     __pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/descr.h b/nptl/descr.h
index aaef9bc621..a9f830ef0b 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -134,6 +134,51 @@ struct pthread
   /* Process ID - thread group ID in kernel speak.  */
   pid_t pid;
 
+  /* List of robust mutexes the thread is holding.  */
+  pthread_mutex_t *robust_list;
+
+#ifdef __PTHREAD_MUTEX_HAVE_PREV
+# define ENQUEUE_MUTEX(mutex) \
+  do {									      \
+    mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list);	      \
+    THREAD_SETMEM (THREAD_SELF, robust_list, mutex);			      \
+    if (mutex->__data.__next != NULL)					      \
+      mutex->__data.__next->__data.__prev = mutex;			      \
+    mutex->__data.__prev = NULL;					      \
+  } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+  do {									      \
+    if (mutex->__data.__prev == NULL)					      \
+      THREAD_SETMEM (THREAD_SELF, robust_list, mutex->__data.__next);	      \
+    else								      \
+      mutex->__data.__prev->__data.__next = mutex->__data.__next;	      \
+    if (mutex->__data.__next != NULL)					      \
+      mutex->__data.__next->__data.__prev = mutex->__data.__prev;	      \
+    mutex->__data.__prev = NULL;					      \
+    mutex->__data.__next = NULL;					      \
+  } while (0)
+#else
+# define ENQUEUE_MUTEX(mutex) \
+  do {									      \
+    mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list);	      \
+    THREAD_SETMEM (THREAD_SELF, robust_list, mutex);			      \
+  } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+  do {									      \
+    pthread_mutex_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list);	      \
+    if (runp == mutex)							      \
+      THREAD_SETMEM (THREAD_SELF, robust_list, runp->__data.__next);	      \
+    else								      \
+      {									      \
+	while (runp->__data.__next != mutex)				      \
+	  runp = runp->__data.__next;					      \
+									      \
+	runp->__data.__next = runp->__data.__next->__data.__next;	      \
+	mutex->__data.__next = NULL;					      \
+      }									      \
+  } while (0)
+#endif
+
   /* List of cleanup buffers.  */
   struct _pthread_cleanup_buffer *cleanup;
 
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index c9237e0950..b88a32fefd 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <setjmp.h>
 #include <stdlib.h>
 #include "pthreadP.h"
-#include "atomic.h"
+#include <atomic.h>
 #include <bits/libc-lock.h>
 
 
diff --git a/nptl/pt-cleanup.c b/nptl/pt-cleanup.c
index 96836a14a1..f72ea26e96 100644
--- a/nptl/pt-cleanup.c
+++ b/nptl/pt-cleanup.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <setjmp.h>
 #include <stdlib.h>
 #include "pthreadP.h"
-#include "jmpbuf-unwind.h"
+#include <jmpbuf-unwind.h>
 
 void
 __pthread_cleanup_upto (__jmp_buf target, char *targetframe)
@@ -61,4 +61,3 @@ __pthread_cleanup_upto (__jmp_buf target, char *targetframe)
   THREAD_SETMEM (self, cleanup, cbuf);
 }
 hidden_def (__pthread_cleanup_upto)
-
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 24168146fa..61b7176159 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -51,6 +51,32 @@
 #endif
 
 
+/* Magic cookie representing robust mutex with dead owner.  */
+#define PTHREAD_MUTEX_OWNERDEAD		INT_MAX
+/* Magic cookie representing not recoverable robust mutex.  */
+#define PTHREAD_MUTEX_NOTRECOVERABLE	(INT_MAX - 1)
+
+
+/* Internal mutex type value.  */
+enum
+{
+  PTHREAD_MUTEX_ROBUST_PRIVATE_NP = 256,
+  PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP
+  = PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP
+  = PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP
+  = PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_ADAPTIVE_NP
+};
+
+
+/* Flags in mutex attr.  */
+#define PTHREAD_MUTEXATTR_FLAG_ROBUST	0x40000000
+#define PTHREAD_MUTEXATTR_FLAG_PSHARED	0x80000000
+#define PTHREAD_MUTEXATTR_FLAG_BITS \
+  (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED)
+
+
 /* Internal variables.  */
 
 
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index c11d972572..2dbe58dcd4 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -52,7 +52,7 @@ unsigned int __nptl_nthreads = 1;
 #include "allocatestack.c"
 
 /* Code to create the thread.  */
-#include "createthread.c"
+#include <createthread.c>
 
 
 struct pthread *
@@ -310,6 +310,33 @@ start_thread (void *arg)
      the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE.  */
   atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
 
+  /* If this thread has any robust mutexes locked, handle them now.  */
+  pthread_mutex_t *robust = THREAD_GETMEM (pd, robust_list);
+  if (__builtin_expect (robust != NULL, 0))
+    {
+      do
+	{
+	  pthread_mutex_t *this = robust;
+	  robust = robust->__data.__next;
+
+	  assert (lll_mutex_islocked (this->__data.__lock));
+	  this->__data.__count = 0;
+	  --this->__data.__nusers;
+	  assert (this->__data.__owner != PTHREAD_MUTEX_NOTRECOVERABLE);
+	  this->__data.__owner = PTHREAD_MUTEX_OWNERDEAD;
+	  this->__data.__next = NULL;
+#ifdef __PTHREAD_MUTEX_HAVE_PREV
+	  this->__data.__prev = NULL;
+#endif
+
+	  lll_mutex_unlock (this->__data.__lock);
+	}
+      while (robust != NULL);
+
+      /* Clean up so that the thread descriptor can be reused.  */
+      THREAD_SETMEM (pd, robust_list, NULL);
+    }
+
   /* If the thread is detached free the TCB.  */
   if (IS_DETACHED (pd))
     /* Free the TCB.  */
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index f94128dd96..70dc81a023 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "atomic.h"
+#include <atomic.h>
 #include "pthreadP.h"
 
 
diff --git a/nptl/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c
new file mode 100644
index 0000000000..2edfe8a5a6
--- /dev/null
+++ b/nptl/pthread_mutex_consistent.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthreadP.h>
+
+
+int
+pthread_mutex_consistent_np (mutex)
+     pthread_mutex_t *mutex;
+{
+  /* Test whether this is a robust mutex with a dead owner.  */
+  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_PRIVATE_NP) == 0
+      || mutex->__data.__owner != -THREAD_GETMEM (THREAD_SELF, tid))
+    return EINVAL;
+
+  mutex->__data.__owner = -mutex->__data.__owner;
+
+  return 0;
+}
diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
index 91ccfb0d29..2bf76a9da3 100644
--- a/nptl/pthread_mutex_destroy.c
+++ b/nptl/pthread_mutex_destroy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -28,6 +28,9 @@ __pthread_mutex_destroy (mutex)
   if (mutex->__data.__nusers != 0)
     return EBUSY;
 
+  /* Set to an invalid value.  */
+  mutex->__data.__kind = -1;
+
   return 0;
 }
 strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
index 074941daf3..17d1c99575 100644
--- a/nptl/pthread_mutex_init.c
+++ b/nptl/pthread_mutex_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -18,6 +18,7 @@
    02111-1307 USA.  */
 
 #include <assert.h>
+#include <errno.h>
 #include <string.h>
 #include "pthreadP.h"
 
@@ -40,17 +41,26 @@ __pthread_mutex_init (mutex, mutexattr)
 
   imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
 
+  /* Sanity checks.  */
+  // XXX For now we cannot implement robust mutexes if they are shared.
+  if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0
+      && (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0)
+    return ENOTSUP;
+
   /* Clear the whole variable.  */
   memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
 
   /* Copy the values from the attribute.  */
-  mutex->__data.__kind = imutexattr->mutexkind & ~0x80000000;
+  mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
+  if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
+    mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_PRIVATE_NP;
 
   /* Default values: mutex not used yet.  */
   // mutex->__count = 0;	already done by memset
   // mutex->__owner = 0;	already done by memset
   // mutex->__nusers = 0;	already done by memset
   // mutex->__spins = 0;	already done by memset
+  // mutex->__next = NULL;	already done by memset
 
   return 0;
 }
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
index ee39f20820..420711a4d4 100644
--- a/nptl/pthread_mutex_lock.c
+++ b/nptl/pthread_mutex_lock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,6 +19,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <stdlib.h>
 #include "pthreadP.h"
 #include <lowlevellock.h>
 
@@ -37,6 +38,7 @@ __pthread_mutex_lock (mutex)
 
   pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
 
+  int retval = 0;
   switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
     {
       /* Recursive mutex.  */
@@ -57,23 +59,23 @@ __pthread_mutex_lock (mutex)
       /* We have to get the mutex.  */
       LLL_MUTEX_LOCK (mutex->__data.__lock);
 
+      assert (mutex->__data.__owner == 0);
       mutex->__data.__count = 1;
       break;
 
       /* 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 */
 
-    default:
-      /* Correct code cannot set any other type.  */
     case PTHREAD_MUTEX_TIMED_NP:
     simple:
       /* Normal mutex.  */
       LLL_MUTEX_LOCK (mutex->__data.__lock);
+      assert (mutex->__data.__owner == 0);
       break;
 
     case PTHREAD_MUTEX_ADAPTIVE_NP:
@@ -101,17 +103,79 @@ __pthread_mutex_lock (mutex)
 
 	  mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
 	}
+      assert (mutex->__data.__owner == 0);
+      break;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (abs (mutex->__data.__owner) == id)
+	{
+	  /* Just bump the counter.  */
+	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+	    /* Overflow of the counter.  */
+	    return EAGAIN;
+
+	  ++mutex->__data.__count;
+
+	  return 0;
+	}
+
+      /* We have to get the mutex.  */
+      LLL_MUTEX_LOCK (mutex->__data.__lock);
+
+      mutex->__data.__count = 1;
+
+      goto robust;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
+	return EDEADLK;
+
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
+      LLL_MUTEX_LOCK (mutex->__data.__lock);
+
+    robust:
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+	{
+	  /* This mutex is now not recoverable.  */
+	  mutex->__data.__count = 0;
+	  lll_mutex_unlock (mutex->__data.__lock);
+	  return ENOTRECOVERABLE;
+	}
+
+      /* This mutex is either healthy or we can try to recover it.  */
+      assert (mutex->__data.__owner == 0
+	      || mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
+
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_OWNERDEAD, 0))
+	{
+	  retval = EOWNERDEAD;
+	  /* We signal ownership of a not yet recovered robust mutex
+	     by storing the negative thread ID.  */
+	  id = -id;
+	}
+
+      ENQUEUE_MUTEX (mutex);
       break;
+
+    default:
+      /* Correct code cannot set any other type.  */
+      return EINVAL;
     }
 
   /* Record the ownership.  */
-  assert (mutex->__data.__owner == 0);
   mutex->__data.__owner = id;
 #ifndef NO_INCR
   ++mutex->__data.__nusers;
 #endif
 
-  return 0;
+  return retval;
 }
 #ifndef __pthread_mutex_lock
 strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 1cd2c7e606..bc4ead765d 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -17,6 +17,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <assert.h>
 #include <errno.h>
 #include "pthreadP.h"
 #include <lowlevellock.h>
@@ -49,17 +50,15 @@ pthread_mutex_timedlock (mutex, abstime)
 
 	  goto out;
 	}
-      else
-	{
-	  /* We have to get the mutex.  */
-	  result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
 
-	  if (result != 0)
-	    goto out;
+      /* We have to get the mutex.  */
+      result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
 
-	  /* Only locked once so far.  */
-	  mutex->__data.__count = 1;
-	}
+      if (result != 0)
+	goto out;
+
+      /* Only locked once so far.  */
+      mutex->__data.__count = 1;
       break;
 
       /* Error checking mutex.  */
@@ -70,8 +69,6 @@ pthread_mutex_timedlock (mutex, abstime)
 
       /* FALLTHROUGH */
 
-    default:
-      /* Correct code cannot set any other type.  */
     case PTHREAD_MUTEX_TIMED_NP:
     simple:
       /* Normal mutex.  */
@@ -104,6 +101,75 @@ pthread_mutex_timedlock (mutex, abstime)
 	  mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
 	}
       break;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (abs (mutex->__data.__owner) == id)
+	{
+	  /* Just bump the counter.  */
+	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+	    /* Overflow of the counter.  */
+	    return EAGAIN;
+
+	  ++mutex->__data.__count;
+
+	  goto out;
+	}
+
+      /* We have to get the mutex.  */
+      result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
+
+      if (result != 0)
+	goto out;
+
+      /* Only locked once so far.  */
+      mutex->__data.__count = 1;
+      goto robust;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
+	return EDEADLK;
+
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
+      result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
+
+      if (result != 0)
+	goto out;
+
+    robust:
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+	{
+	  /* This mutex is now not recoverable.  */
+	  mutex->__data.__count = 0;
+	  lll_mutex_unlock (mutex->__data.__lock);
+	  return ENOTRECOVERABLE;
+	}
+
+      /* This mutex is either healthy or we can try to recover it.  */
+      assert (mutex->__data.__owner == 0
+	      || mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
+
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_OWNERDEAD, 0))
+	{
+	  result = EOWNERDEAD;
+	  /* We signal ownership of a not yet recovered robust mutex
+	     by storing the negative thread ID.  */
+	  mutex->__data.__owner = -id;
+	  ++mutex->__data.__nusers;
+	}
+
+      ENQUEUE_MUTEX (mutex);
+      break;
+
+    default:
+      /* Correct code cannot set any other type.  */
+      return EINVAL;
     }
 
   if (result == 0)
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 7008af3d97..ae73ecc39b 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -17,7 +17,9 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <assert.h>
 #include <errno.h>
+#include <stdlib.h>
 #include "pthreadP.h"
 #include <lowlevellock.h>
 
@@ -26,13 +28,12 @@ int
 __pthread_mutex_trylock (mutex)
      pthread_mutex_t *mutex;
 {
-  pid_t id;
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
 
   switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
     {
       /* Recursive mutex.  */
     case PTHREAD_MUTEX_RECURSIVE_NP:
-      id = THREAD_GETMEM (THREAD_SELF, tid);
       /* Check whether we already hold the mutex.  */
       if (mutex->__data.__owner == id)
 	{
@@ -56,20 +57,96 @@ __pthread_mutex_trylock (mutex)
       break;
 
     case PTHREAD_MUTEX_ERRORCHECK_NP:
-      /* Error checking mutex.  We do not check for deadlocks.  */
-    default:
-      /* Correct code cannot set any other type.  */
+      /* Check whether we already hold the mutex.  */
+      if (__builtin_expect (mutex->__data.__owner == id, 0))
+	return EDEADLK;
+
+      /* FALLTHROUGH */
+
     case PTHREAD_MUTEX_TIMED_NP:
     case PTHREAD_MUTEX_ADAPTIVE_NP:
       /* Normal mutex.  */
-      if (lll_mutex_trylock (mutex->__data.__lock) == 0)
+      if (lll_mutex_trylock (mutex->__data.__lock) != 0)
+	break;
+
+      /* Record the ownership.  */
+      mutex->__data.__owner = id;
+      ++mutex->__data.__nusers;
+
+      return 0;
+
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (abs (mutex->__data.__owner) == id)
 	{
-	  /* Record the ownership.  */
-	  mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid);
-	  ++mutex->__data.__nusers;
+	  /* Just bump the counter.  */
+	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+	    /* Overflow of the counter.  */
+	    return EAGAIN;
+
+	  ++mutex->__data.__count;
 
 	  return 0;
 	}
+
+      /* We have to get the mutex.  */
+      if (lll_mutex_trylock (mutex->__data.__lock) == 0)
+	{
+	  mutex->__data.__count = 1;
+
+	  goto robust;
+	}
+
+      break;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
+	return EDEADLK;
+
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
+      if (lll_mutex_trylock (mutex->__data.__lock) != 0)
+	break;
+
+    robust:
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+	{
+	  /* This mutex is now not recoverable.  */
+	  mutex->__data.__count = 0;
+	  lll_mutex_unlock (mutex->__data.__lock);
+	  return ENOTRECOVERABLE;
+	}
+
+      /* This mutex is either healthy or we can try to recover it.  */
+      assert (mutex->__data.__owner == 0
+	      || mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
+
+      /* Record the ownership.  */
+      int retval = 0;
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_OWNERDEAD, 0))
+	{
+	  retval = EOWNERDEAD;
+	  /* We signal ownership of a not yet recovered robust
+	     mutex by storing the negative thread ID.  */
+	  id = -id;
+	}
+
+      ENQUEUE_MUTEX (mutex);
+
+      mutex->__data.__owner = id;
+      ++mutex->__data.__nusers;
+
+      return retval
+;
+    default:
+      /* Correct code cannot set any other type.  */
+      return EINVAL;
     }
 
   return EBUSY;
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
index 32bc2a4bc1..babce51a6f 100644
--- a/nptl/pthread_mutex_unlock.c
+++ b/nptl/pthread_mutex_unlock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -18,6 +18,7 @@
    02111-1307 USA.  */
 
 #include <errno.h>
+#include <stdlib.h>
 #include "pthreadP.h"
 #include <lowlevellock.h>
 
@@ -28,6 +29,8 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
      pthread_mutex_t *mutex;
      int decr;
 {
+  int newowner = 0;
+
   switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
     {
     case PTHREAD_MUTEX_RECURSIVE_NP:
@@ -47,16 +50,63 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
 	return EPERM;
       break;
 
-    default:
-      /* Correct code cannot set any other type.  */
     case PTHREAD_MUTEX_TIMED_NP:
     case PTHREAD_MUTEX_ADAPTIVE_NP:
       /* Normal mutex.  Nothing special to do.  */
       break;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
+      /* Recursive mutex.  */
+      if (mutex->__data.__owner == -THREAD_GETMEM (THREAD_SELF, tid))
+	{
+	  if (--mutex->__data.__count != 0)
+	    /* We still hold the mutex.  */
+	    return ENOTRECOVERABLE;
+
+	  goto 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 robust;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
+      /* Error checking mutex.  */
+      if (abs (mutex->__data.__owner) != THREAD_GETMEM (THREAD_SELF, tid)
+	  || ! lll_mutex_islocked (mutex->__data.__lock))
+	return EPERM;
+
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
+      /* 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 (__builtin_expect (mutex->__data.__owner
+			    == -THREAD_GETMEM (THREAD_SELF, tid)
+			    || (mutex->__data.__owner
+				== PTHREAD_MUTEX_NOTRECOVERABLE), 0))
+      notrecoverable:
+	newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
+
+    robust:
+      /* Remove mutex from the list.  */
+      DEQUEUE_MUTEX (mutex);
+      break;
+
+    default:
+      /* Correct code cannot set any other type.  */
+      return EINVAL;
     }
 
   /* Always reset the owner field.  */
-  mutex->__data.__owner = 0;
+  mutex->__data.__owner = newowner;
   if (decr)
     /* One less user.  */
     --mutex->__data.__nusers;
diff --git a/nptl/pthread_mutexattr_getpshared.c b/nptl/pthread_mutexattr_getpshared.c
index 4bd4ea18db..6454125db2 100644
--- a/nptl/pthread_mutexattr_getpshared.c
+++ b/nptl/pthread_mutexattr_getpshared.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -29,9 +29,7 @@ pthread_mutexattr_getpshared (attr, pshared)
 
   iattr = (const struct pthread_mutexattr *) attr;
 
-  /* We use bit 31 to signal whether the mutex is going to be
-     process-shared or not.  */
-  *pshared = ((iattr->mutexkind & 0x80000000) != 0
+  *pshared = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0
 	      ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);
 
   return 0;
diff --git a/nptl/pthread_mutexattr_getrobust.c b/nptl/pthread_mutexattr_getrobust.c
new file mode 100644
index 0000000000..5ec43d1f7c
--- /dev/null
+++ b/nptl/pthread_mutexattr_getrobust.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthreadP.h>
+
+
+int
+pthread_mutexattr_getrobust_np (attr, robustness)
+     const pthread_mutexattr_t *attr;
+     int *robustness;
+{
+  const struct pthread_mutexattr *iattr;
+
+  iattr = (const struct pthread_mutexattr *) attr;
+
+  *robustness = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0
+		 ? PTHREAD_MUTEX_ROBUST_NP : PTHREAD_MUTEX_STALLED_NP);
+
+  return 0;
+}
diff --git a/nptl/pthread_mutexattr_gettype.c b/nptl/pthread_mutexattr_gettype.c
index 5c32b2c6f1..7303703bf4 100644
--- a/nptl/pthread_mutexattr_gettype.c
+++ b/nptl/pthread_mutexattr_gettype.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -29,9 +29,7 @@ pthread_mutexattr_gettype (attr, kind)
 
   iattr = (const struct pthread_mutexattr *) attr;
 
-  /* We use bit 31 to signal whether the mutex is going to be
-     process-shared or not.  */
-  *kind = iattr->mutexkind & ~0x80000000;
+  *kind = iattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
 
   return 0;
 }
diff --git a/nptl/pthread_mutexattr_setpshared.c b/nptl/pthread_mutexattr_setpshared.c
index 5f2cf417e3..8e08b9e161 100644
--- a/nptl/pthread_mutexattr_setpshared.c
+++ b/nptl/pthread_mutexattr_setpshared.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -34,12 +34,10 @@ pthread_mutexattr_setpshared (attr, pshared)
 
   iattr = (struct pthread_mutexattr *) attr;
 
-  /* We use bit 31 to signal whether the mutex is going to be
-     process-shared or not.  */
   if (pshared == PTHREAD_PROCESS_PRIVATE)
-    iattr->mutexkind &= ~0x80000000;
+    iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_PSHARED;
   else
-    iattr->mutexkind |= 0x80000000;
+    iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_PSHARED;
 
   return 0;
 }
diff --git a/nptl/pthread_mutexattr_setrobust.c b/nptl/pthread_mutexattr_setrobust.c
new file mode 100644
index 0000000000..cf95e35b6f
--- /dev/null
+++ b/nptl/pthread_mutexattr_setrobust.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthreadP.h>
+
+
+int
+pthread_mutexattr_setrobust_np (attr, robustness)
+     pthread_mutexattr_t *attr;
+     int robustness;
+{
+  if (robustness != PTHREAD_MUTEX_STALLED_NP
+      && __builtin_expect (robustness != PTHREAD_MUTEX_ROBUST_NP, 0))
+    return EINVAL;
+
+  struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr;
+
+  /* We use bit 30 to signal whether the mutex is going to be
+     robust or not.  */
+  if (robustness == PTHREAD_MUTEX_STALLED_NP)
+    iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_ROBUST;
+  else
+    iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_ROBUST;
+
+  return 0;
+}
diff --git a/nptl/pthread_mutexattr_settype.c b/nptl/pthread_mutexattr_settype.c
index c77fe79df5..fe6b5c22cd 100644
--- a/nptl/pthread_mutexattr_settype.c
+++ b/nptl/pthread_mutexattr_settype.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -33,9 +33,7 @@ __pthread_mutexattr_settype (attr, kind)
 
   iattr = (struct pthread_mutexattr *) attr;
 
-  /* We use bit 31 to signal whether the mutex is going to be
-     process-shared or not.  */
-  iattr->mutexkind = (iattr->mutexkind & 0x80000000) | kind;
+  iattr->mutexkind = (iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_BITS) | kind;
 
   return 0;
 }
diff --git a/nptl/pthread_timedjoin.c b/nptl/pthread_timedjoin.c
index 1cc07213c8..5df6ab6a80 100644
--- a/nptl/pthread_timedjoin.c
+++ b/nptl/pthread_timedjoin.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,7 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
-#include "atomic.h"
+#include <atomic.h>
 #include "pthreadP.h"
 
 
diff --git a/nptl/pthread_tryjoin.c b/nptl/pthread_tryjoin.c
index 904cb5280b..fc363dd778 100644
--- a/nptl/pthread_tryjoin.c
+++ b/nptl/pthread_tryjoin.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "atomic.h"
+#include <atomic.h>
 #include "pthreadP.h"
 
 
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index badadae169..5413661eb3 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -60,24 +60,39 @@ enum
 #endif
 };
 
-/* Mutex initializers.  */
-#define PTHREAD_MUTEX_INITIALIZER \
-  { { 0, 0, 0, 0, 0, 0 } }
+
 #ifdef __USE_GNU
-# if __WORDSIZE == 64
+/* Robust mutex or not flags.  */
+enum
+{
+  PTHREAD_MUTEX_STALLED_NP,
+  PTHREAD_MUTEX_ROBUST_NP
+};
+#endif
+
+
+/* Mutex initializers.  */
+#if __WORDSIZE == 64
+# define PTHREAD_MUTEX_INITIALIZER \
+  { { 0, 0, 0, 0, 0, 0, (void *) 0, (void *) 0 } }
+# ifdef __USE_GNU
 #  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0 } }
+  { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, (void *) 0, (void *) 0 } }
 #  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0 } }
+  { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, (void *) 0, (void *) 0 } }
 #  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0 } }
-# else
+  { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, (void *) 0, (void *) 0 } }
+# endif
+#else
+# define PTHREAD_MUTEX_INITIALIZER \
+  { { 0, 0, 0, 0, 0, { 0 } } }
+# ifdef __USE_GNU
 #  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0 } }
+  { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0 } } }
 #  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, 0 } }
+  { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0 } } }
 #  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
-  { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, 0 } }
+  { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0 } } }
 # endif
 #endif
 
@@ -696,6 +711,12 @@ extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
 extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW;
 
 
+#ifdef __USE_GNU
+/* Declare the state protected by MUTEX as consistent.  */
+extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex) __THROW;
+#endif
+
+
 /* Functions for handling mutex attributes.  */
 
 /* Initialize mutex attribute object ATTR with default attributes
@@ -726,6 +747,16 @@ extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
      __THROW;
 #endif
 
+#ifdef __USE_GNU
+/* Get the robustness flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_getrobust_np (__const pthread_mutexattr_t *__attr,
+					   int *__robustness) __THROW;
+
+/* Set the robustness flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr,
+					   int __robustness) __THROW;
+#endif
+
 
 #if defined __USE_UNIX98 || defined __USE_XOPEN2K
 /* Functions for handling read-write locks.  */
diff --git a/nptl/sysdeps/pthread/sigaction.c b/nptl/sysdeps/pthread/sigaction.c
index 4d36150a90..445a2cb36f 100644
--- a/nptl/sysdeps/pthread/sigaction.c
+++ b/nptl/sysdeps/pthread/sigaction.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -28,7 +28,11 @@
    SIGCANCEL or SIGTIMER to be handled.  */
 # define LIBC_SIGACTION	1
 
-# include <nptl/sysdeps/pthread/sigaction.c>
+/* Note this include must be one that isn't found using a -I directory such
+   as -I. or -I.. for using an explicit <sysdeps/...> path, because that
+   would reset the search path starting position for the #include_next
+   below, to after that -I directory, and skip the search we want to do.  */
+# include "sigaction.c"
 
 int
 __sigaction (sig, act, oact)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
index ddb3574aaa..3bd1019995 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -45,7 +45,7 @@ typedef union
 
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
-typedef union
+typedef union __pthread_mutex_u
 {
   struct
   {
@@ -56,7 +56,11 @@ typedef union
        binary compatibility.  */
     int __kind;
     unsigned int __nusers;
-    int __spins;
+    union
+    {
+      int __spins;
+      union __pthread_mutex_u *__next;
+    };
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
index 1605b69b69..3e908aef9c 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
@@ -57,7 +57,7 @@ __new_sem_wait:
 	cfi_offset(6, -12)		/* %esi */
 3:	movl	(%ebx), %eax
 2:	testl	%eax, %eax
-	je,pn	1f
+	je	1f
 
 	leal	-1(%eax), %edx
 	LOCK
@@ -73,7 +73,7 @@ __new_sem_wait:
 	cfi_adjust_cfa_offset(-12)
 	ret
 
-	cfi_adjust_cfa_offset(8)
+	cfi_adjust_cfa_offset(12)
 	cfi_offset(3, -8)		/* %ebx */
 	cfi_offset(6, -12)		/* %esi */
 1:	call	__pthread_enable_asynccancel
diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
index 3d1c021819..4e60596f7d 100644
--- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,7 +19,7 @@
 
 #include <unistd.h>
 #include <list.h>
-#include "fork.h"
+#include <fork.h>
 #include <dl-sysdep.h>
 #include <tls.h>
 #include <string.h>
diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
index 9707e4663c..cb5b2b832f 100644
--- a/nptl/sysdeps/unix/sysv/linux/register-atfork.c
+++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include "fork.h"
+#include <fork.h>
 
 
 /* Lock to protect allocation and deallocation of fork handlers.  */
diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
index 72c8d615eb..964f5b7094 100644
--- a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
+++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,7 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
-#include "fork.h"
+#include <fork.h>
 #include <atomic.h>
 
 
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
index 7f1ace693c..3eb33a8646 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
@@ -59,7 +59,7 @@ typedef union
 
 /* Data structures for mutex handling.  The structure of the attribute
    type is not exposed on purpose.  */
-typedef union
+typedef union __pthread_mutex_u
 {
   struct
   {
@@ -72,10 +72,19 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
-#if __WORDSIZE != 64
+#if __WORDSIZE == 64
+    int __spins;
+    union __pthread_mutex_u *__next;
+    union __pthread_mutex_u *__prev;
+# define __PTHREAD_MUTEX_HAVE_PREV	1
+#else
     unsigned int __nusers;
+    union
+    {
+      int __spins;
+      union __pthread_mutex_u *__next;
+    };
 #endif
-    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/tst-cancel24.cc b/nptl/tst-cancel24.cc
new file mode 100644
index 0000000000..52cf079d5a
--- /dev/null
+++ b/nptl/tst-cancel24.cc
@@ -0,0 +1,113 @@
+#include <cstdlib>
+#include <cstdio>
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+
+
+static volatile bool destr_called;
+static volatile bool except_caught;
+
+static pthread_barrier_t b;
+
+
+struct monitor
+{
+  // gcc is broken and would generate a warning without this dummy
+  // constructor.
+  monitor () { }
+  ~monitor() { destr_called = true; }
+};
+
+
+static void *
+tf (void *arg)
+{
+  sem_t *s = static_cast<sem_t *> (arg);
+
+  try
+    {
+      monitor m;
+
+      pthread_barrier_wait (&b);
+
+      while (1)
+      sem_wait (s);
+    }
+  catch (...)
+    {
+      except_caught = true;
+      throw;
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test ()
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  sem_t s;
+  if (sem_init (&s, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &s) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  pthread_barrier_wait (&b);
+
+  /* There is unfortunately no better method to try to assure the
+     child thread reached the sem_wait call and is actually waiting
+     than to sleep here.  */
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != PTHREAD_CANCELED)
+    {
+      puts ("thread was not canceled");
+      return 1;
+    }
+
+  if (! except_caught)
+    {
+      puts ("exception not caught");
+      return 1;
+    }
+
+  if (! destr_called)
+    {
+      puts ("destructor not called");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 3
+#include "../test-skeleton.c"
diff --git a/nptl/tst-once3.c b/nptl/tst-once3.c
index 43b354a391..1a74abb530 100644
--- a/nptl/tst-once3.c
+++ b/nptl/tst-once3.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -52,6 +52,8 @@ once_handler1 (void)
       exit (1);
     }
 
+  puts ("once_handler1: going to wait on cond");
+
   pthread_cond_wait (&cond, &mut);
 
   /* We should never get here.  */
@@ -139,6 +141,9 @@ do_test (void)
       puts ("join didn't return PTHREAD_CANCELED");
       return 1;
     }
+  puts ("joined successfully");
+
+  printf ("once = %d\n", *(int *) &once);
 
   if (cl_called != 1)
     {
diff --git a/nptl/tst-robust1.c b/nptl/tst-robust1.c
new file mode 100644
index 0000000000..13267a5efd
--- /dev/null
+++ b/nptl/tst-robust1.c
@@ -0,0 +1,245 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m;
+static pthread_barrier_t b;
+
+
+#ifndef LOCK
+# define LOCK(m) pthread_mutex_lock (m)
+#endif
+
+
+static void *
+tf (void *arg)
+{
+  long int round = (long int) arg;
+
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+    {
+      printf ("%ld: setcancelstate failed\n", round);
+      exit (1);
+    }
+
+  int e = LOCK (&m);
+  if (e != 0)
+    {
+      printf ("%ld: child: mutex_lock failed with error %d\n", round, e);
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%ld: child: 1st barrier_wait failed\n", round);
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%ld: child: 2nd barrier_wait failed\n", round);
+      exit (1);
+    }
+
+  pthread_testcancel ();
+
+  printf ("%ld: testcancel returned\n", round);
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+#ifdef PREPARE_TMO
+  PREPARE_TMO;
+#endif
+
+  pthread_mutexattr_t a;
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
+    {
+      puts ("mutexattr_setrobust failed");
+      return 1;
+    }
+#ifndef NOT_CONSISTENT
+  if (pthread_mutex_init (&m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+#endif
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  for (long int round = 1; round < 5; ++round)
+    {
+#ifdef NOT_CONSISTENT
+      if (pthread_mutex_init (&m, &a) != 0)
+	{
+	  puts ("mutex_init failed");
+	  return 1;
+	}
+#endif
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, (void *) round) != 0)
+	{
+	  printf ("%ld: create failed\n", round);
+	  return 1;
+	}
+
+      int e = pthread_barrier_wait (&b);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%ld: parent: 1st barrier_wait failed\n", round);
+	  return 1;
+	}
+
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("%ld: cancel failed\n", round);
+	  return 1;
+	}
+
+      e = pthread_barrier_wait (&b);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%ld: parent: 2nd barrier_wait failed\n", round);
+	  return 1;
+	}
+
+#ifndef AFTER_JOIN
+      if (round & 1)
+#endif
+	{
+	  void *res;
+	  if (pthread_join (th, &res) != 0)
+	    {
+	      printf ("%ld: join failed\n", round);
+	      return 1;
+	    }
+	  if (res != PTHREAD_CANCELED)
+	    {
+	      printf ("%ld: thread not canceled\n", round);
+	      return 1;
+	    }
+	}
+
+      e = LOCK (&m);
+      if (e == 0)
+	{
+	  printf ("%ld: parent: mutex_lock succeeded\n", round);
+	  return 1;
+	}
+      if (e != EOWNERDEAD)
+	{
+	  printf ("%ld: parent: mutex_lock returned wrong code\n", round);
+	  return 1;
+	}
+
+#ifndef AFTER_JOIN
+      if ((round & 1) == 0)
+	{
+	  void *res;
+	  if (pthread_join (th, &res) != 0)
+	    {
+	      printf ("%ld: join failed\n", round);
+	      return 1;
+	    }
+	  if (res != PTHREAD_CANCELED)
+	    {
+	      printf ("%ld: thread not canceled\n", round);
+	      return 1;
+	    }
+	}
+#endif
+
+#ifndef NOT_CONSISTENT
+      e = pthread_mutex_consistent_np (&m);
+      if (e != 0)
+	{
+	  printf ("%ld: mutex_consistent failed with error %d\n", round, e);
+	  return 1;
+	}
+#endif
+
+      e = pthread_mutex_unlock (&m);
+      if (e != 0)
+	{
+	  printf ("%ld: mutex_unlocked failed\n", round);
+	  return 1;
+	}
+
+#ifdef NOT_CONSISTENT
+      e = LOCK (&m);
+      if (e == 0)
+	{
+	  printf ("%ld: locking inconsistent mutex succeeded\n", round);
+	  return 1;
+	}
+      if (e != ENOTRECOVERABLE)
+	{
+	  printf ("%ld: locking inconsistent mutex failed with error %d\n",
+		  round, e);
+	  return 1;
+	}
+
+      if (pthread_mutex_destroy (&m) != 0)
+	{
+	  puts ("mutex_destroy failed");
+	  return 1;
+	}
+#endif
+    }
+
+#ifndef NOT_CONSISTENT
+  if (pthread_mutex_destroy (&m) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+#endif
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/nptl/tst-robust2.c b/nptl/tst-robust2.c
new file mode 100644
index 0000000000..cf603feb4d
--- /dev/null
+++ b/nptl/tst-robust2.c
@@ -0,0 +1,3 @@
+#define AFTER_JOIN 1
+#define LOCK(m) pthread_mutex_trylock (m)
+#include "tst-robust1.c"
diff --git a/nptl/tst-robust3.c b/nptl/tst-robust3.c
new file mode 100644
index 0000000000..e56f2762c7
--- /dev/null
+++ b/nptl/tst-robust3.c
@@ -0,0 +1,20 @@
+#include <time.h>
+#include <sys/time.h>
+
+
+static struct timespec tmo;
+
+
+#define PREPARE_TMO \
+  do {									      \
+    struct timeval tv;							      \
+    gettimeofday (&tv, NULL);						      \
+									      \
+    /* Define the timeout as one hour in the future.  */		      \
+    tmo.tv_sec = tv.tv_sec + 3600;					      \
+    tmo.tv_nsec = 0;							      \
+  } while (0)
+
+
+#define LOCK(m) pthread_mutex_timedlock (m, &tmo)
+#include "tst-robust1.c"
diff --git a/nptl/tst-robust4.c b/nptl/tst-robust4.c
new file mode 100644
index 0000000000..b9c42b85b9
--- /dev/null
+++ b/nptl/tst-robust4.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust1.c"
diff --git a/nptl/tst-robust5.c b/nptl/tst-robust5.c
new file mode 100644
index 0000000000..b83d3d66cb
--- /dev/null
+++ b/nptl/tst-robust5.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust2.c"
diff --git a/nptl/tst-robust6.c b/nptl/tst-robust6.c
new file mode 100644
index 0000000000..6713396de1
--- /dev/null
+++ b/nptl/tst-robust6.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust3.c"
diff --git a/nptl/tst-typesizes.c b/nptl/tst-typesizes.c
new file mode 100644
index 0000000000..db8936f5f4
--- /dev/null
+++ b/nptl/tst-typesizes.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdio.h>
+#include <pthreadP.h>
+#include <semaphore.h>
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+#define TEST_TYPE(name) \
+  printf ("%s: ", #name);						      \
+  if (sizeof (name) != sizeof (((name *) 0)->__size))			      \
+    {									      \
+      printf ("expected %zu, is %zu\n",					      \
+	      sizeof (((name *) 0)->__size), sizeof (name));		      \
+      result = 1;							      \
+    }									      \
+  else									      \
+    puts ("OK")
+
+  TEST_TYPE (pthread_mutex_t);
+  TEST_TYPE (pthread_cond_t);
+  TEST_TYPE (pthread_rwlock_t);
+
+#define TEST_TYPE2(name, internal)					      \
+  printf ("%s: ", #name);						      \
+  if (sizeof (((name *) 0)->__size) < sizeof (internal))		      \
+    {									      \
+      printf ("expected %zu, is %zu\n",					      \
+	      sizeof (((name *) 0)->__size), sizeof (internal));	      \
+      result = 1;							      \
+    }									      \
+  else									      \
+    puts ("OK")
+
+  TEST_TYPE2 (pthread_attr_t, struct pthread_attr);
+  TEST_TYPE2 (pthread_mutexattr_t, struct pthread_mutexattr);
+  TEST_TYPE2 (pthread_condattr_t, struct pthread_condattr);
+  TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
+  TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
+  TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
+  TEST_TYPE2 (sem_t, struct sem);
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/nptl/unwind.c b/nptl/unwind.c
index 56a4238158..9a35695cb5 100644
--- a/nptl/unwind.c
+++ b/nptl/unwind.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>
    and Richard Henderson <rth@redhat.com>, 2003.
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include "pthreadP.h"
-#include "jmpbuf-unwind.h"
+#include <jmpbuf-unwind.h>
 
 #ifdef HAVE_FORCED_UNWIND
 
diff --git a/nptl/version.c b/nptl/version.c
index f2fd25fd6d..1be6b7f4a5 100644
--- a/nptl/version.c
+++ b/nptl/version.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -23,7 +23,7 @@
 
 static const char banner[] =
 #include "banner.h"
-"Copyright (C) 2003 Free Software Foundation, Inc.\n\
+"Copyright (C) 2005 Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.\n\
 There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
 PARTICULAR PURPOSE.\n"