diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2005-12-27 01:04:06 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2005-12-27 01:04:06 +0000 |
| commit | 1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93 (patch) | |
| tree | efa74fd1d0c2f6fccda616328a7b432ffdc6ba92 | |
| parent | 08f60b258ec9d9a24275831941a6f559eb26580e (diff) | |
| download | glibc-1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93.tar.xz glibc-1bcfb5a5eb1c25b64a329c1edf6bcfb440cdbc93.zip | |
* Versions.def: Add GLIBC_2.4 for libpthread.cvs/fedora-glibc-20051227T1426
31 files changed, 980 insertions, 58 deletions
@@ -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_un |
