* Versions.def: Add GLIBC_2.4 for libpthread.
authorUlrich Drepper <drepper@redhat.com>
Tue, 27 Dec 2005 01:04:06 +0000 (01:04 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 27 Dec 2005 01:04:06 +0000 (01:04 +0000)
31 files changed:
ChangeLog
Versions.def
nptl/ChangeLog
nptl/Makefile
nptl/Versions
nptl/descr.h
nptl/pthreadP.h
nptl/pthread_create.c
nptl/pthread_mutex_consistent.c [new file with mode: 0644]
nptl/pthread_mutex_init.c
nptl/pthread_mutex_lock.c
nptl/pthread_mutex_timedlock.c
nptl/pthread_mutex_trylock.c
nptl/pthread_mutex_unlock.c
nptl/pthread_mutexattr_getpshared.c
nptl/pthread_mutexattr_getrobust.c [new file with mode: 0644]
nptl/pthread_mutexattr_gettype.c
nptl/pthread_mutexattr_setpshared.c
nptl/pthread_mutexattr_setrobust.c [new file with mode: 0644]
nptl/pthread_mutexattr_settype.c
nptl/sysdeps/pthread/pthread.h
nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
nptl/tst-once3.c
nptl/tst-robust1.c [new file with mode: 0644]
nptl/tst-robust2.c [new file with mode: 0644]
nptl/tst-robust3.c [new file with mode: 0644]
nptl/tst-robust4.c [new file with mode: 0644]
nptl/tst-robust5.c [new file with mode: 0644]
nptl/tst-robust6.c [new file with mode: 0644]
nptl/tst-typesizes.c [new file with mode: 0644]

index ce5d953..36091ff 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-12-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * Versions.def: Add GLIBC_2.4 for libpthread.
+
 2005-12-25  Ulrich Drepper  <drepper@redhat.com>
 
        * stdlib/Makefile ($(objpfx)isomac.out): Move -I.. to the end so
index 09cef14..d7be703 100644 (file)
@@ -80,6 +80,7 @@ libpthread {
   GLIBC_2.3.2
   GLIBC_2.3.3
   GLIBC_2.3.4
+  GLIBC_2.4
   GLIBC_PRIVATE
 }
 libresolv {
index 877c858..acb6cd2 100644 (file)
@@ -1,3 +1,56 @@
+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
index c061b9d..ec3d00d 100644 (file)
@@ -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 \
index 79bf190..2b4dd01 100644 (file)
@@ -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;
index aaef9bc..a9f830e 100644 (file)
@@ -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;
 
index 2416814..61b7176 100644 (file)
@@ -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.
 
 #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.  */
 
 
index 729b76b..2dbe58d 100644 (file)
@@ -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_mutex_consistent.c b/nptl/pthread_mutex_consistent.c
new file mode 100644 (file)
index 0000000..2edfe8a
--- /dev/null
@@ -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;
+}
index 074941d..17d1c99 100644 (file)
@@ -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;
 }
index a2d0afb..420711a 100644 (file)
@@ -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,13 +59,14 @@ __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 */
@@ -72,6 +75,7 @@ __pthread_mutex_lock (mutex)
     simple:
       /* Normal mutex.  */
       LLL_MUTEX_LOCK (mutex->__data.__lock);
+      assert (mutex->__data.__owner == 0);
       break;
 
     case PTHREAD_MUTEX_ADAPTIVE_NP:
@@ -99,6 +103,65 @@ __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:
@@ -107,13 +170,12 @@ __pthread_mutex_lock (mutex)
     }
 
   /* 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)
index 06bdf9d..bc4ead7 100644 (file)
@@ -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.  */
@@ -103,6 +102,71 @@ pthread_mutex_timedlock (mutex, abstime)
        }
       break;
 
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (abs (mutex->__data.__owner) == id)
+       {
+         /* Just bump the counter.  */
+         if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+           /* Overflow of the counter.  */
+           return EAGAIN;
+
+         ++mutex->__data.__count;
+
+         goto out;
+       }
+
+      /* We have to get the mutex.  */
+      result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
+
+      if (result != 0)
+       goto out;
+
+      /* Only locked once so far.  */
+      mutex->__data.__count = 1;
+      goto robust;
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
+       return EDEADLK;
+
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
+    case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
+      result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
+
+      if (result != 0)
+       goto out;
+
+    robust:
+      if (__builtin_expect (mutex->__data.__owner
+                           == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+       {
+         /* 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;
index 8213f90..ae73ecc 100644 (file)
@@ -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,93 @@ __pthread_mutex_trylock (mutex)
       break;
 
     case PTHREAD_MUTEX_ERRORCHECK_NP:
-      /* Error checking mutex.  We do not check for deadlocks.  */
+      /* 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;
index 5f097a5..babce51 100644 (file)
@@ -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:
@@ -52,13 +55,58 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
       /* 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;
index 4bd4ea1..6454125 100644 (file)
@@ -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 (file)
index 0000000..5ec43d1
--- /dev/null
@@ -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;
+}
index 5c32b2c..7303703 100644 (file)
@@ -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;
 }
index 5f2cf41..8e08b9e 100644 (file)
@@ -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 (file)
index 0000000..cf95e35
--- /dev/null
@@ -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;
+}
index c77fe79..fe6b5c2 100644 (file)
@@ -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;
 }
index badadae..5413661 100644 (file)
@@ -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.  */
index ddb3574..3bd1019 100644 (file)
@@ -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;
index 7f1ace6..3eb33a8 100644 (file)
@@ -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;
index 43b354a..1a74abb 100644 (file)
@@ -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 (file)
index 0000000..13267a5
--- /dev/null
@@ -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 (file)
index 0000000..cf603fe
--- /dev/null
@@ -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 (file)
index 0000000..e56f276
--- /dev/null
@@ -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 (file)
index 0000000..b9c42b8
--- /dev/null
@@ -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 (file)
index 0000000..b83d3d6
--- /dev/null
@@ -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 (file)
index 0000000..6713396
--- /dev/null
@@ -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 (file)
index 0000000..db8936f
--- /dev/null
@@ -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"