aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-12-27 01:04:06 +0000
committerUlrich Drepper <drepper@redhat.com>2005-12-27 01:04:06 +0000
commit1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93 (patch)
treeefa74fd1d0c2f6fccda616328a7b432ffdc6ba92
parent* stdlib/Makefile ($(objpfx)isomac.out): Move -I.. to the end so (diff)
downloadglibc-1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93.tar.gz
glibc-1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93.tar.bz2
glibc-1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93.zip
* Versions.def: Add GLIBC_2.4 for libpthread.cvs/fedora-glibc-20051227T1426
-rw-r--r--ChangeLog4
-rw-r--r--Versions.def1
-rw-r--r--nptl/ChangeLog53
-rw-r--r--nptl/Makefile7
-rw-r--r--nptl/Versions5
-rw-r--r--nptl/descr.h45
-rw-r--r--nptl/pthreadP.h28
-rw-r--r--nptl/pthread_create.c27
-rw-r--r--nptl/pthread_mutex_consistent.c36
-rw-r--r--nptl/pthread_mutex_init.c14
-rw-r--r--nptl/pthread_mutex_lock.c68
-rw-r--r--nptl/pthread_mutex_timedlock.c82
-rw-r--r--nptl/pthread_mutex_trylock.c88
-rw-r--r--nptl/pthread_mutex_unlock.c50
-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/sysdeps/pthread/pthread.h53
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h15
-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
31 files changed, 980 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index ce5d95355a..36091ffc22 100644
--- 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
diff --git a/Versions.def b/Versions.def
index 09cef140bf..d7be70386e 100644
--- a/Versions.def
+++ b/Versions.def
@@ -80,6 +80,7 @@ libpthread {
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
+ GLIBC_2.4
GLIBC_PRIVATE
}
libresolv {
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 877c858118..acb6cd2a53 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -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
diff --git a/nptl/Makefile b/nptl/Makefile
index c061b9d646..ec3d00d19e 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 \
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/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 729b76b838..2dbe58dcd4 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -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
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_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 a2d0afbe15..420711a4d4 100644
--- a/nptl/pthread_mutex_lock.c
+++ b/nptl/pthread_mutex_lock.c
@@ -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)
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 06bdf9d1cc..bc4ead765d 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -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;
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 8213f90da9..ae73ecc39b 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -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;
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
index 5f097a596d..babce51a6f 100644
--- a/nptl/pthread_mutex_unlock.c
+++ b/nptl/pthread_mutex_unlock.c
@@ -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;
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/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/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/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-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"