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