From ab5823b4b6e760345d347b98830ccc75aa81bff6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 29 Jul 2006 23:12:43 +0000 Subject: Updated to fedora-glibc-20060729T2255 --- ChangeLog | 42 ++++++ NEWS | 5 +- dlfcn/Makefile | 13 +- dlfcn/bug-atexit3-lib.cc | 23 ++++ dlfcn/bug-atexit3.c | 18 +++ dlfcn/dlmopen.c | 17 ++- fedora/branch.mk | 4 +- fedora/glibc.spec.in | 6 +- include/time.h | 2 + include/unistd.h | 2 + nptl/ChangeLog | 66 +++++++++ nptl/Makefile | 5 + nptl/descr.h | 40 ++++-- nptl/pthreadP.h | 21 ++- nptl/pthread_create.c | 8 +- nptl/pthread_mutex_destroy.c | 1 - nptl/pthread_mutex_init.c | 28 +++- nptl/pthread_mutex_lock.c | 129 ++++++++++++++++++ nptl/pthread_mutex_setprioceiling.c | 2 +- nptl/pthread_mutex_timedlock.c | 150 ++++++++++++++++++++- nptl/pthread_mutex_trylock.c | 124 ++++++++++++++++- nptl/pthread_mutex_unlock.c | 83 ++++++++++++ nptl/sysdeps/pthread/pthread_cond_broadcast.c | 8 +- nptl/sysdeps/unix/sysv/linux/Makefile | 2 +- nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h | 3 + nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h | 8 +- .../sysv/linux/i386/i486/pthread_cond_broadcast.S | 7 +- nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h | 3 + nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h | 3 + .../sysdeps/unix/sysv/linux/powerpc/lowlevellock.h | 3 + .../sysdeps/unix/sysv/linux/pthread-pi-defines.sym | 6 + nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h | 3 + nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h | 3 + nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h | 3 + nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h | 3 + .../sysv/linux/x86_64/pthread_cond_broadcast.S | 7 +- nptl/tst-mutex1.c | 22 ++- nptl/tst-mutex2.c | 67 +++++---- nptl/tst-mutex3.c | 23 +++- nptl/tst-mutex4.c | 99 +++++++++++++- nptl/tst-mutex5.c | 20 ++- nptl/tst-mutex6.c | 22 ++- nptl/tst-mutex7.c | 52 ++++++- nptl/tst-mutex7a.c | 2 +- nptl/tst-mutex9.c | 22 ++- nptl/tst-mutexpi1.c | 27 ++++ nptl/tst-mutexpi2.c | 2 + nptl/tst-mutexpi3.c | 2 + nptl/tst-mutexpi4.c | 2 + nptl/tst-mutexpi5.c | 2 + nptl/tst-mutexpi5a.c | 2 + nptl/tst-mutexpi6.c | 27 ++++ nptl/tst-mutexpi7.c | 2 + nptl/tst-mutexpi7a.c | 2 + nptl/tst-mutexpi8.c | 2 + nptl/tst-mutexpi9.c | 2 + nptl/tst-robust1.c | 28 +++- nptl/tst-robust7.c | 25 +++- nptl/tst-robust8.c | 13 +- nptl/tst-robustpi1.c | 2 + nptl/tst-robustpi2.c | 2 + nptl/tst-robustpi3.c | 2 + nptl/tst-robustpi4.c | 2 + nptl/tst-robustpi5.c | 2 + nptl/tst-robustpi6.c | 2 + nptl/tst-robustpi7.c | 2 + nptl/tst-robustpi8.c | 2 + stdlib/cxa_atexit.c | 8 +- stdlib/cxa_finalize.c | 34 +++-- stdlib/exit.h | 5 +- sysdeps/unix/sysv/linux/alpha/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/i386/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/ia64/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/kernel-features.h | 17 +-- sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/s390/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/sh/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/sparc/bits/fcntl.h | 2 +- sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h | 2 +- 79 files changed, 1284 insertions(+), 130 deletions(-) create mode 100644 dlfcn/bug-atexit3-lib.cc create mode 100644 dlfcn/bug-atexit3.c create mode 100644 nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym create mode 100644 nptl/tst-mutexpi1.c create mode 100644 nptl/tst-mutexpi2.c create mode 100644 nptl/tst-mutexpi3.c create mode 100644 nptl/tst-mutexpi4.c create mode 100644 nptl/tst-mutexpi5.c create mode 100644 nptl/tst-mutexpi5a.c create mode 100644 nptl/tst-mutexpi6.c create mode 100644 nptl/tst-mutexpi7.c create mode 100644 nptl/tst-mutexpi7a.c create mode 100644 nptl/tst-mutexpi8.c create mode 100644 nptl/tst-mutexpi9.c create mode 100644 nptl/tst-robustpi1.c create mode 100644 nptl/tst-robustpi2.c create mode 100644 nptl/tst-robustpi3.c create mode 100644 nptl/tst-robustpi4.c create mode 100644 nptl/tst-robustpi5.c create mode 100644 nptl/tst-robustpi6.c create mode 100644 nptl/tst-robustpi7.c create mode 100644 nptl/tst-robustpi8.c diff --git a/ChangeLog b/ChangeLog index 7a97b2fabe..dfca3fceb3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2006-07-28 Ulrich Drepper + + * sysdeps/unix/sysv/linux/kernel-features.h: Define + __ASSUME_FUTEX_LOCK_PI. + * include/time.h: Declare __nanosleep_nocancel. + * include/unistd.h: Declare __pause_nocancel. + + * dlfcn/Makefile (LDLIBS-bug-atexit3-lib.so): Use this instead of + LDFLAGS. Add -lgcc_eh and libc_nonshared (again) to make sure we + get the __stack_chk_fail_local definition when it's needed. + +2006-07-26 Ulrich Drepper + + * dlfcn/Makefile: Add rules to build and run bug-atexit3. + * dlfcn/bug-atexit3.c: New file. + * dlfcn/bug-atexit3-lib.cc: New file. + + * dlfcn/dlmopen.c (dlmopen_doit): Don't allow RTLD_GLOBAL to be + used when the namespace is not the base namespace. + +2006-07-26 Gavin Romig-Koch + + * stdlib/cxa_atexit.c (__new_exitfn_called): New variable. + (__new_exitfn): Bump it in every successful call. + * stdlib/cxa_finalize.c (__cxa_finalize): If destructor registered + more exit handlers, call them right away. + * stdlib/exit.h: Declare __new_exitfn_called. + +2006-07-25 Ulrich Drepper + + * stdlib/cxa_finalize.c (__cxa_finalize): Fix race condition when + calling registered handler. + + * sysdeps/unix/sysv/linux/sparc/bits/fcntl.h: Fix comment. + * sysdeps/unix/sysv/linux/ia64/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h: Likewise. + 2006-07-10 Ulrich Drepper * elf/dl-lookup.c (dl_new_hash): New functions. diff --git a/NEWS b/NEWS index 0f73029978..55855ad81a 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 2006-07-10 +GNU C Library NEWS -- history of user-visible changes. 2006-07-28 Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc. See the end for copying conditions. @@ -33,6 +33,9 @@ Version 2.5 * Support for the new ELF hash table format was added by Ulrich Drepper. +* Support for priority inheritance mutexes added by Jakub Jelinek and + Ulrich Drepper. + Version 2.4 diff --git a/dlfcn/Makefile b/dlfcn/Makefile index bfa181528b..649f61de63 100644 --- a/dlfcn/Makefile +++ b/dlfcn/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 1995-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ endif ifeq (yes,$(build-shared)) tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ - bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 + bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ + bug-atexit3 ifeq (yes,$(have-protected)) tests += tstatexit endif @@ -48,7 +49,7 @@ endif modules-names = glreflib1 glreflib2 failtestmod defaultmod1 defaultmod2 \ errmsg1mod modatexit modcxaatexit \ bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ - bug-atexit2-lib + bug-atexit2-lib bug-atexit3-lib failtestmod.so-no-z-defs = yes glreflib2.so-no-z-defs = yes @@ -135,6 +136,12 @@ $(objpfx)bug-atexit2.out: $(objpfx)bug-atexit2-lib.so $(objpfx)bug-atexit2-lib.so: $(common-objpfx)libc.so \ $(common-objpfx)libc_nonshared.a +LDLIBS-bug-atexit3-lib.so = -lstdc++ -lgcc_eh $(common-objpfx)libc_nonshared.a +$(objpfx)bug-atexit3: $(libdl) +$(objpfx)bug-atexit3.out: $(objpfx)bug-atexit3-lib.so +$(objpfx)bug-atexit3-lib.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a + # Depend on libc.so so a DT_NEEDED is generated in the shared objects. # This ensures they will load libc.so for needed symbols if loaded by diff --git a/dlfcn/bug-atexit3-lib.cc b/dlfcn/bug-atexit3-lib.cc new file mode 100644 index 0000000000..3d01ea81d2 --- /dev/null +++ b/dlfcn/bug-atexit3-lib.cc @@ -0,0 +1,23 @@ +#include + +struct statclass +{ + statclass() + { + write (1, "statclass\n", 10); + } + ~statclass() + { + write (1, "~statclass\n", 11); + } +}; + +struct extclass +{ + ~extclass() + { + static statclass var; + } +}; + +extclass globvar; diff --git a/dlfcn/bug-atexit3.c b/dlfcn/bug-atexit3.c new file mode 100644 index 0000000000..897eca8a86 --- /dev/null +++ b/dlfcn/bug-atexit3.c @@ -0,0 +1,18 @@ +#include +#include + +static int +do_test (void) +{ + void *handle = dlopen ("$ORIGIN/bug-atexit3-lib.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("dlopen failed: %s\n", dlerror ()); + return 1; + } + dlclose (handle); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c index 0a6d47ea2e..0c6915493b 100644 --- a/dlfcn/dlmopen.c +++ b/dlfcn/dlmopen.c @@ -1,5 +1,5 @@ /* Load a shared object at run time. - Copyright (C) 1995,96,97,98,99,2000,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2003,2004,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -55,12 +55,19 @@ dlmopen_doit (void *a) /* Non-shared code has no support for multiple namespaces. */ if (args->nsid != LM_ID_BASE) + { # ifdef SHARED - /* If trying to open the link map for the main executable the namespace - must be the main one. */ - if (args->file == NULL) + /* If trying to open the link map for the main executable the namespace + must be the main one. */ + if (args->file == NULL) # endif - GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace")); + GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace")); + + /* It makes no sense to use RTLD_GLOBAL when loading a DSO into + a namespace other than the base namespace. */ + if (__builtin_expect (args->mode & RTLD_GLOBAL, 0)) + GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid mode")); + } args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, args->caller, diff --git a/fedora/branch.mk b/fedora/branch.mk index 124031f0ac..cd60348072 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-fc4 -fedora-sync-date := 2006-07-10 22:06 UTC -fedora-sync-tag := fedora-glibc-20060710T2206 +fedora-sync-date := 2006-07-29 22:55 UTC +fedora-sync-tag := fedora-glibc-20060729T2255 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 59df1b9005..7bb140e570 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 13 +%define glibcrelease 14 %define auxarches i586 i686 athlon sparcv9 alphaev6 %define xenarches i686 athlon %ifarch %{xenarches} @@ -1433,6 +1433,10 @@ rm -f *.filelist* %endif %changelog +* Sat Jul 29 2006 Roland McGrath - 2.4.90-14 +- fix missing destructor calls in dlclose (#197932) +- PI mutex support + * Tue Jul 10 2006 Jakub Jelinek 2.4.90-13 - DT_GNU_HASH support diff --git a/include/time.h b/include/time.h index 224736540b..f2a6489efd 100644 --- a/include/time.h +++ b/include/time.h @@ -81,6 +81,8 @@ extern long int __tzname_max (void); extern int __nanosleep (__const struct timespec *__requested_time, struct timespec *__remaining); +extern int __nanosleep_nocancel (__const struct timespec *__requested_time, + struct timespec *__remaining); libc_hidden_proto(__nanosleep) extern int __getdate_r (__const char *__string, struct tm *__resbufp); diff --git a/include/unistd.h b/include/unistd.h index f8f15ed019..fb7a044b57 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -162,5 +162,7 @@ extern __pid_t __libc_fork (void); /* Suspend the process until a signal arrives. This always returns -1 and sets `errno' to EINTR. */ extern int __libc_pause (void); +/* Not cancelable variant. */ +extern int __pause_nocancel (void); #endif diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 02b4c2f191..b9705ee065 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,69 @@ +2006-07-28 Ulrich Drepper + Jakub Jelinek + + * descr.h: Change ENQUEUE_MUTEX and DEQUEUE_MUTEX for bit 0 + notification of PI mutex. Add ENQUEUE_MUTEX_PI. + * pthreadP.h: Define PTHREAD_MUTEX_PI_* macros for PI mutex types. + * pthread_mutex_setprioceilining.c: Adjust for mutex type name change. + * pthread_mutex_init.c: Add support for priority inheritance mutex. + * pthread_mutex_lock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/pthread/pthread_cond_broadcast.c: For PI mutexes wake + all mutexes. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: New file. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-header): Add + pthread-pi-defines.sym. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_LOCK_PI, + FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_PRIO_INHERIT to 200112L. + * tst-mutex1.c: Adjust to allow use in PI mutex test. + * tst-mutex2.c: Likewise. + * tst-mutex3.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-mutex5.c: Likewise. + * tst-mutex6.c: Likewise. + * tst-mutex7.c: Likewise. + * tst-mutex7a.c: Likewise. + * tst-mutex8.c: Likewise. + * tst-mutex9.c: Likewise. + * tst-robust1.c: Likewise. + * tst-robust7.c: Likewise. + * tst-robust8.c: Likewise. + * tst-mutexpi1.c: New file. + * tst-mutexpi2.c: New file. + * tst-mutexpi3.c: New file. + * tst-mutexpi4.c: New file. + * tst-mutexpi5.c: New file. + * tst-mutexpi6.c: New file. + * tst-mutexpi7.c: New file. + * tst-mutexpi7a.c: New file. + * tst-mutexpi8.c: New file. + * tst-mutexpi9.c: New file. + * 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. + * tst-robust8.c: New file. + * Makefile (tests): Add the new tests. + + * pthread_create.c (start_thread): Add some casts to avoid warnings. + * pthread_mutex_destroy.c: Remove unneeded label. + 2006-07-01 Ulrich Drepper * pthread_mutex_init.c (__pthread_mutex_init): Move some diff --git a/nptl/Makefile b/nptl/Makefile index e430b8d6cb..6a80bc1183 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -200,6 +200,9 @@ 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-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ + tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \ + tst-mutexpi9 \ tst-spin1 tst-spin2 tst-spin3 \ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ @@ -207,6 +210,8 @@ tests = tst-typesizes \ tst-cond20 tst-cond21 \ tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ tst-robust6 tst-robust7 tst-robust8 \ + tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 \ + tst-robustpi5 tst-robustpi6 tst-robustpi7 tst-robustpi8 \ 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/descr.h b/nptl/descr.h index f89d3240da..607aa9fcdb 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -155,23 +155,28 @@ struct pthread first. */ # define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next)) -# define ENQUEUE_MUTEX(mutex) \ +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ do { \ - __pthread_list_t *next = (THREAD_GETMEM (THREAD_SELF, robust_head.list) \ - - QUEUE_PTR_ADJUST); \ + __pthread_list_t *next = (__pthread_list_t *) \ + ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ next->__prev = (void *) &mutex->__data.__list.__next; \ - mutex->__data.__list.__next = (void *) &next->__next; \ + mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \ + robust_head.list); \ mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \ THREAD_SETMEM (THREAD_SELF, robust_head.list, \ - &mutex->__data.__list.__next); \ + (void *) (((uintptr_t) &mutex->__data.__list.__next) \ + | val)); \ } while (0) # define DEQUEUE_MUTEX(mutex) \ do { \ __pthread_list_t *next = (__pthread_list_t *) \ - ((char *) mutex->__data.__list.__next - QUEUE_PTR_ADJUST); \ + ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ next->__prev = mutex->__data.__list.__prev; \ __pthread_list_t *prev = (__pthread_list_t *) \ - ((char *) mutex->__data.__list.__prev - QUEUE_PTR_ADJUST); \ + ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ prev->__next = mutex->__data.__list.__next; \ mutex->__data.__list.__prev = NULL; \ mutex->__data.__list.__next = NULL; \ @@ -183,27 +188,36 @@ struct pthread struct robust_list_head robust_head; }; -# define ENQUEUE_MUTEX(mutex) \ +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ do { \ mutex->__data.__list.__next \ = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \ - THREAD_SETMEM (THREAD_SELF, robust_list.__next, &mutex->__data.__list); \ + THREAD_SETMEM (THREAD_SELF, robust_list.__next, \ + ((uintptr_t) &mutex->__data.__list) | val); \ } while (0) # define DEQUEUE_MUTEX(mutex) \ do { \ - __pthread_slist_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list.__next);\ + __pthread_slist_t *runp = (__pthread_slist_t *) \ + (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \ if (runp == &mutex->__data.__list) \ THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \ else \ { \ - while (runp->__next != &mutex->__data.__list) \ - runp = runp->__next; \ + __pthread_slist_t *next = (__pthread_slist_t *) \ + (((uintptr_t) runp->__next) & ~1ul); \ + while (next != &mutex->__data.__list) \ + { \ + runp = next; \ + next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \ + } \ \ - runp->__next = runp->__next->__next; \ + runp->__next = next->__next; \ mutex->__data.__list.__next = NULL; \ } \ } while (0) #endif +#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0) +#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1) /* List of cleanup buffers. */ struct _pthread_cleanup_buffer *cleanup; diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index c7f57e235a..dc98bb19c0 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -61,6 +61,7 @@ /* Internal mutex type value. */ enum { + PTHREAD_MUTEX_KIND_MASK_NP = 3, PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16, PTHREAD_MUTEX_ROBUST_RECURSIVE_NP = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP, @@ -68,8 +69,24 @@ enum = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP, PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP, - PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP = 32, - PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP = 64 + PTHREAD_MUTEX_PRIO_INHERIT_NP = 32, + PTHREAD_MUTEX_PI_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_PI_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP, + PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP, + PTHREAD_MUTEX_PRIO_PROTECT_NP = 64 }; #define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 16 #define PTHREAD_MUTEX_PRIO_CEILING_MASK 0x00ff0000 diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 71365a17e8..c1ac199bb9 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -330,9 +330,11 @@ start_thread (void *arg) # else __pthread_slist_t *robust = pd->robust_list.__next; # endif -/* We let the kernel do the notification if it is able to do so. */ + /* We let the kernel do the notification if it is able to do so. + If we have to do it here there for sure are no PI mutexes involved + since the kernel support for them is even more recent. */ if (__set_robust_list_avail < 0 - && __builtin_expect (robust != &pd->robust_head, 0)) + && __builtin_expect (robust != (void *) &pd->robust_head, 0)) { do { @@ -348,7 +350,7 @@ start_thread (void *arg) lll_robust_mutex_dead (this->__lock); } - while (robust != &pd->robust_head); + while (robust != (void *) &pd->robust_head); } #endif diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c index 7829979f35..e2c9f8a39f 100644 --- a/nptl/pthread_mutex_destroy.c +++ b/nptl/pthread_mutex_destroy.c @@ -30,7 +30,6 @@ __pthread_mutex_destroy (mutex) return EBUSY; /* Set to an invalid value. */ - dead_robust_mutex: mutex->__data.__kind = -1; return 0; diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c index c3f9c2d1c0..6ceca86052 100644 --- a/nptl/pthread_mutex_init.c +++ b/nptl/pthread_mutex_init.c @@ -29,6 +29,11 @@ static const struct pthread_mutexattr default_attr = }; +#ifndef __ASSUME_FUTEX_LOCK_PI +static int tpi_supported; +#endif + + int __pthread_mutex_init (mutex, mutexattr) pthread_mutex_t *mutex; @@ -41,8 +46,7 @@ __pthread_mutex_init (mutex, mutexattr) imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr; /* Sanity checks. */ - // XXX For now we don't support priority inherited or priority protected - // XXX mutexes. + // XXX For now we don't support priority protected mutexes. switch (__builtin_expect (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK, PTHREAD_PRIO_NONE @@ -51,6 +55,22 @@ __pthread_mutex_init (mutex, mutexattr) case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: break; + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: +#ifndef __ASSUME_FUTEX_LOCK_PI + if (__builtin_expect (tpi_supported == 0, 0)) + { + int lock = 0; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI, + 0, 0); + assert (INTERNAL_SYSCALL_ERROR_P (ret, err)); + tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1; + } + if (__builtin_expect (tpi_supported < 0, 0)) + return ENOTSUP; +#endif + break; + default: return ENOTSUP; } @@ -75,11 +95,11 @@ __pthread_mutex_init (mutex, mutexattr) switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) { case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: - mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP; + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; break; case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: - mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP; + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; if (PTHREAD_MUTEX_PRIO_CEILING_MASK == PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) mutex->__data.__kind |= (imutexattr->mutexkind diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index 06eef49c71..5345766883 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "pthreadP.h" #include @@ -205,6 +206,134 @@ __pthread_mutex_lock (mutex) THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); break; + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#endif + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. */ + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_LOCK_PI, 1, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); + + /* Delay the thread indefinitely. */ + while (1) + __pause_nocancel (); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. If we are not supposed to + increment __nusers we actually have to decrement it here. */ +#ifdef NO_INCR + --mutex->__data.__nusers; +#endif + + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_UNLOCK_PI, 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + default: /* Correct code cannot set any other type. */ return EINVAL; diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c index 999b635ac1..3271f8833a 100644 --- a/nptl/pthread_mutex_setprioceiling.c +++ b/nptl/pthread_mutex_setprioceiling.c @@ -30,7 +30,7 @@ pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling) { /* The low bits of __kind aren't ever changed after pthread_mutex_init, so we don't need a lock yet. */ - if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP) == 0) + if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) return EINVAL; if (prioceiling < 0 || __builtin_expect (prioceiling > 255, 0)) diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index 7c48c7ce6b..12f6c997bb 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -35,7 +35,7 @@ pthread_mutex_timedlock (mutex, abstime) /* We must not check ABSTIME here. If the thread does not block abstime must not be checked for a valid value. */ - switch (mutex->__data.__kind) + switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP)) { /* Recursive mutex. */ case PTHREAD_MUTEX_RECURSIVE_NP: @@ -65,7 +65,7 @@ pthread_mutex_timedlock (mutex, abstime) /* 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 */ @@ -134,7 +134,7 @@ pthread_mutex_timedlock (mutex, abstime) ENQUEUE_MUTEX (mutex); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - /* Note that we deliberately exist here. If we fall + /* Note that we deliberately exit here. If we fall through to the end of the function __nusers would be incremented which is not correct because the old owner has to be discounted. */ @@ -194,6 +194,150 @@ pthread_mutex_timedlock (mutex, abstime) THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); break; + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. The timeout value must be a relative value. + Convert it. */ + INTERNAL_SYSCALL_DECL (__err); + + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_LOCK_PI, 1, abstime); + if (INTERNAL_SYSCALL_ERROR_P (e, __err)) + { + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT) + return ETIMEDOUT; + + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH + || !robust); + + /* Delay the thread until the timeout is reached. + Then return ETIMEDOUT. */ + struct timespec reltime; + struct timespec now; + + INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_REALTIME, + &now); + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec; + if (reltime.tv_nsec < 0) + { + reltime.tv_nsec += 1000000000; + --reltime.tv_sec; + } + if (reltime.tv_sec >= 0) + while (__nanosleep_nocancel (&reltime, &reltime) != 0) + continue; + + return ETIMEDOUT; + } + + return INTERNAL_SYSCALL_ERRNO (e, __err); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_UNLOCK_PI, 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + 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 148a6e919f..f3a18569a1 100644 --- a/nptl/pthread_mutex_trylock.c +++ b/nptl/pthread_mutex_trylock.c @@ -152,7 +152,6 @@ __pthread_mutex_trylock (mutex) return EBUSY; } - robust: if (__builtin_expect (mutex->__data.__owner == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) { @@ -175,6 +174,129 @@ __pthread_mutex_trylock (mutex) return 0; + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + if ((oldval & FUTEX_OWNER_DIED) == 0) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + assert (robust); + + /* The mutex owner died. The kernel will now take care of + everything. */ + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_TRYLOCK_PI, 0, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + oldval = mutex->__data.__lock; + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + FUTEX_UNLOCK_PI, 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + } + 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 bf9aa7625f..2b5064fbac 100644 --- a/nptl/pthread_mutex_unlock.c +++ b/nptl/pthread_mutex_unlock.c @@ -119,6 +119,89 @@ __pthread_mutex_unlock_usercnt (mutex, decr) THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); break; + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto continue_pi; + + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + /* Recursive mutex. */ + if ((mutex->__data.__lock & FUTEX_TID_MASK) + == THREAD_GETMEM (THREAD_SELF, tid) + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + { + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return ENOTRECOVERABLE; + + goto pi_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 continue_pi; + + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + if ((mutex->__data.__lock & FUTEX_TID_MASK) + != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_mutex_islocked (mutex->__data.__lock)) + return EPERM; + + /* 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 ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + pi_notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + + continue_pi: + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) + { + /* Remove mutex from the list. + Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + DEQUEUE_MUTEX (mutex); + } + + mutex->__data.__owner = newowner; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + if ((mutex->__data.__lock & FUTEX_WAITERS) != 0 + || atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, 0, + THREAD_GETMEM (THREAD_SELF, + tid))) + { + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, + FUTEX_UNLOCK_PI); + } + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + default: /* Correct code cannot set any other type. */ return EINVAL; diff --git a/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/nptl/sysdeps/pthread/pthread_cond_broadcast.c index 1eac8ecf83..2b8b5460f4 100644 --- a/nptl/sysdeps/pthread/pthread_cond_broadcast.c +++ b/nptl/sysdeps/pthread/pthread_cond_broadcast.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky , 2003. @@ -55,6 +55,12 @@ __pthread_cond_broadcast (cond) /* Wake everybody. */ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; + + /* XXX: Kernel so far doesn't support requeue to PI futex. */ + if (__builtin_expect (mut->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP, + 0)) + goto wake_all; + /* lll_futex_requeue returns 0 for success and non-zero for errors. */ if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile index 88dce1a886..cfcdb6d97f 100644 --- a/nptl/sysdeps/unix/sysv/linux/Makefile +++ b/nptl/sysdeps/unix/sysv/linux/Makefile @@ -25,7 +25,7 @@ libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \ lowlevelbarrier.sym unwindbuf.sym \ - lowlevelrobustlock.sym + lowlevelrobustlock.sym pthread-pi-defines.sym endif ifeq ($(subdir),posix) diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h index 1a2e8cbb07..58b4806eb2 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -33,6 +33,9 @@ #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h index 92c2d32827..d8eced1f22 100644 --- a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -1,5 +1,5 @@ /* Define POSIX options for Linux. - Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1996-2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -79,6 +79,9 @@ /* We support user-defined stacks. */ #define _POSIX_THREAD_ATTR_STACKADDR 200112L +/* We support priority inheritence. */ +#define _POSIX_THREAD_PRIO_INHERIT 200112L + /* We support POSIX.1b semaphores. */ #define _POSIX_SEMAPHORES 200112L @@ -171,8 +174,7 @@ /* Typed memory objects are not available. */ #define _POSIX_TYPED_MEMORY_OBJECTS -1 -/* No support for priority inheritance or protection so far. */ -#define _POSIX_THREAD_PRIO_INHERIT -1 +/* No support for priority protection so far. */ #define _POSIX_THREAD_PRIO_PROTECT -1 #endif /* posix_opt.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S index 5471c1c927..56f7be8246 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef UP # define LOCK @@ -94,6 +95,10 @@ __pthread_cond_broadcast: 8: cmpl $-1, %edi je 9f + /* XXX: The kernel so far doesn't support requeue to PI futex. */ + testl $PI_BIT, MUTEX_KIND(%edi) + jne 9f + /* Wake up all threads. */ movl $FUTEX_CMP_REQUEUE, %ecx movl $SYS_futex, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index e405f84f25..64088ef732 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -35,6 +35,9 @@ #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h index ece9a7fc72..8df997a262 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h @@ -33,6 +33,9 @@ #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Delay in spinlock loop. */ #define BUSY_WAIT_NOP asm ("hint @pause") diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h index abd019df47..0136b97595 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -35,6 +35,9 @@ #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) diff --git a/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym b/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym new file mode 100644 index 0000000000..a1b6794260 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym @@ -0,0 +1,6 @@ +#include + +-- These PI macros are used by assembly code. + +MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind) +PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h index 6baab90f56..38d9f2ac41 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h @@ -32,6 +32,9 @@ #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h index 92f93cd5f5..0eb1f0114c 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -26,6 +26,9 @@ #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 77eefc546c..5013922a2f 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -32,6 +32,9 @@ #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 5047e4fe4d..7da2f12231 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -35,6 +35,9 @@ #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S index 72e7bc5b24..006de2696e 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef UP # define LOCK @@ -80,6 +81,10 @@ __pthread_cond_broadcast: 8: cmpq $-1, %r8 je 9f + /* XXX: The kernel so far doesn't support requeue to PI futex. */ + testl $PI_BIT, MUTEX_KIND(%r8) + jne 9f + /* Wake up all threads. */ movl $FUTEX_CMP_REQUEUE, %esi movl $SYS_futex, %eax diff --git a/nptl/tst-mutex1.c b/nptl/tst-mutex1.c index 50b5ccaf0e..c3ef5b2b51 100644 --- a/nptl/tst-mutex1.c +++ b/nptl/tst-mutex1.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -19,6 +19,12 @@ #include #include +#include + + +#ifndef ATTR +# define ATTR NULL +#endif static int @@ -26,12 +32,24 @@ do_test (void) { pthread_mutex_t m; - if (pthread_mutex_init (&m, NULL) != 0) + int e = pthread_mutex_init (&m, ATTR); + if (ATTR != NULL && e == ENOTSUP) + { + puts ("cannot support selected type of mutexes"); + return 0; + } + else if (e != 0) { puts ("mutex_init failed"); return 1; } + if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + if (pthread_mutex_lock (&m) != 0) { puts ("mutex_lock failed"); diff --git a/nptl/tst-mutex2.c b/nptl/tst-mutex2.c index f589a1ea17..b09f569a5a 100644 --- a/nptl/tst-mutex2.c +++ b/nptl/tst-mutex2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -105,115 +105,134 @@ do_test (void) if (pthread_mutexattr_init (&a) != 0) { puts ("mutexattr_init failed"); - exit (1); + return 1; } if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0) { puts ("mutexattr_settype failed"); - exit (1); + return 1; } - if (pthread_mutex_init (&m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + e = pthread_mutex_init (&m, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif puts ("mutex_init failed"); - exit (1); + return 1; } if (pthread_barrier_init (&b, NULL, 2) != 0) { puts ("barrier_init failed"); - exit (1); + return 1; } - if ((e = pthread_mutex_unlock (&m)) == 0) + e = pthread_mutex_unlock (&m); + if (e == 0) { puts ("1st mutex_unlock succeeded"); - exit (1); + return 1; } else if (e != EPERM) { puts ("1st mutex_unlock error != EPERM"); - exit (1); + return 1; } if (pthread_mutex_lock (&m) != 0) { puts ("mutex_lock failed"); - exit (1); + return 1; } - if ((e = pthread_mutex_lock (&m)) == 0) + e = pthread_mutex_lock (&m); + if (e == 0) { puts ("2nd mutex_lock succeeded"); - exit (1); + return 1; } else if (e != EDEADLK) { puts ("2nd mutex_lock error != EDEADLK"); - exit (1); + return 1; } pthread_t th; if (pthread_create (&th, NULL, tf, NULL) != 0) { puts ("create failed"); - exit (1); + return 1; } e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("1st barrier_wait failed"); - exit (1); + return 1; } if (pthread_mutex_unlock (&m) != 0) { puts ("2nd mutex_unlock failed"); - exit (1); + return 1; } - if ((e = pthread_mutex_unlock (&m)) == 0) + e = pthread_mutex_unlock (&m); + if (e == 0) { puts ("3rd mutex_unlock succeeded"); - exit (1); + return 1; } else if (e != EPERM) { puts ("3rd mutex_unlock error != EPERM"); - exit (1); + return 1; } e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("2nd barrier_wait failed"); - exit (1); + return 1; } if (pthread_join (th, NULL) != 0) { puts ("join failed"); - exit (1); + return 1; } if (pthread_mutex_destroy (&m) != 0) { puts ("mutex_destroy failed"); - exit (1); + return 1; } if (pthread_barrier_destroy (&b) != 0) { puts ("barrier_destroy failed"); - exit (1); + return 1; } if (pthread_mutexattr_destroy (&a) != 0) { puts ("mutexattr_destroy failed"); - exit (1); + return 1; } return 0; diff --git a/nptl/tst-mutex3.c b/nptl/tst-mutex3.c index 8e57924ba6..2848096538 100644 --- a/nptl/tst-mutex3.c +++ b/nptl/tst-mutex3.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -113,8 +113,25 @@ do_test (void) return 1; } - if (pthread_mutex_init (&m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + int e; + e = pthread_mutex_init (&m, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } @@ -162,7 +179,7 @@ do_test (void) return 1; } - int e = pthread_barrier_wait (&b); + e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); diff --git a/nptl/tst-mutex4.c b/nptl/tst-mutex4.c index 0ce7313caf..9699c2db45 100644 --- a/nptl/tst-mutex4.c +++ b/nptl/tst-mutex4.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -42,6 +42,8 @@ do_test (void) char *p; int err; int s; + pthread_barrier_t *b; + pthread_barrierattr_t ba; fd = mkstemp (tmpfname); if (fd == -1) @@ -70,9 +72,12 @@ do_test (void) return 1; } - m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t)) + m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t) - 1) & ~(__alignof (pthread_mutex_t) - 1)); - p = (char *) (m + 1); + b = (pthread_barrier_t *) (((uintptr_t) (m + 1) + + __alignof (pthread_barrier_t) - 1) + & ~(__alignof (pthread_barrier_t) - 1)); + p = (char *) (b + 1); if (pthread_mutexattr_init (&a) != 0) { @@ -110,8 +115,23 @@ do_test (void) return 1; } - if (pthread_mutex_init (m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + if ((err = pthread_mutex_init (m, &a)) != 0) + { +#ifdef ENABLE_PI + if (err == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } @@ -128,6 +148,30 @@ do_test (void) return 1; } + if (pthread_barrierattr_init (&ba) != 0) + { + puts ("barrierattr_init failed"); + return 1; + } + + if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0) + { + puts ("barrierattr_setpshared failed"); + return 1; + } + + if (pthread_barrier_init (b, &ba, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } + + if (pthread_barrierattr_destroy (&ba) != 0) + { + puts ("barrierattr_destroy failed"); + return 1; + } + err = pthread_mutex_trylock (m); if (err == 0) { @@ -142,6 +186,12 @@ do_test (void) *p = 0; + if (pthread_mutex_unlock (m) != 0) + { + puts ("parent: 1st mutex_unlock failed"); + return 1; + } + puts ("going to fork now"); pid = fork (); if (pid == -1) @@ -151,7 +201,19 @@ do_test (void) } else if (pid == 0) { - /* Play some lock ping-pong. It's our turn to unlock first. */ + if (pthread_mutex_lock (m) != 0) + { + puts ("child: mutex_lock failed"); + return 1; + } + + int e = pthread_barrier_wait (b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: barrier_wait failed"); + return 1; + } + if ((*p)++ != 0) { puts ("child: *p != 0"); @@ -160,7 +222,7 @@ do_test (void) if (pthread_mutex_unlock (m) != 0) { - puts ("child: 1st mutex_unlock failed"); + puts ("child: mutex_unlock failed"); return 1; } @@ -168,6 +230,13 @@ do_test (void) } else { + int e = pthread_barrier_wait (b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("parent: barrier_wait failed"); + return 1; + } + if (pthread_mutex_lock (m) != 0) { puts ("parent: 2nd mutex_lock failed"); @@ -180,6 +249,24 @@ do_test (void) return 1; } + if (pthread_mutex_unlock (m) != 0) + { + puts ("parent: 2nd mutex_unlock failed"); + return 1; + } + + if (pthread_mutex_destroy (m) != 0) + { + puts ("mutex_destroy failed"); + return 1; + } + + if (pthread_barrier_destroy (b) != 0) + { + puts ("barrier_destroy failed"); + return 1; + } + puts ("parent done"); } diff --git a/nptl/tst-mutex5.c b/nptl/tst-mutex5.c index eb35b78d36..291274fee5 100644 --- a/nptl/tst-mutex5.c +++ b/nptl/tst-mutex5.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -52,8 +52,24 @@ do_test (void) return 1; } - if (pthread_mutex_init (&m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + err = pthread_mutex_init (&m, &a); + if (err != 0) + { +#ifdef ENABLE_PI + if (err == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } diff --git a/nptl/tst-mutex6.c b/nptl/tst-mutex6.c index f066c62edc..e5698c3eb0 100644 --- a/nptl/tst-mutex6.c +++ b/nptl/tst-mutex6.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -21,6 +21,12 @@ #include #include #include +#include + + +#ifndef ATTR +# define ATTR NULL +#endif static int @@ -28,12 +34,24 @@ do_test (void) { pthread_mutex_t m; - if (pthread_mutex_init (&m, NULL) != 0) + int e = pthread_mutex_init (&m, ATTR); + if (ATTR != NULL && e == ENOTSUP) + { + puts ("cannot support selected type of mutexes"); + e = pthread_mutex_init (&m, NULL); + } + if (e != 0) { puts ("mutex_init failed"); return 1; } + if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + if (pthread_mutex_lock (&m) != 0) { puts ("1st mutex_lock failed"); diff --git a/nptl/tst-mutex7.c b/nptl/tst-mutex7.c index a9b9f318cb..27e5d8eb28 100644 --- a/nptl/tst-mutex7.c +++ b/nptl/tst-mutex7.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -17,17 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include +#include #include -#ifndef INIT -# define INIT PTHREAD_MUTEX_INITIALIZER +#ifndef TYPE +# define TYPE PTHREAD_MUTEX_DEFAULT #endif -static pthread_mutex_t lock = INIT; +static pthread_mutex_t lock; #define ROUNDS 1000 @@ -65,6 +67,48 @@ tf (void *arg) static int do_test (void) { + pthread_mutexattr_t a; + + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + exit (1); + } + + if (pthread_mutexattr_settype (&a, TYPE) != 0) + { + puts ("mutexattr_settype failed"); + exit (1); + } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + int e = pthread_mutex_init (&lock, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif + puts ("mutex_init failed"); + return 1; + } + + if (pthread_mutexattr_destroy (&a) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + pthread_attr_t at; pthread_t th[N]; int cnt; diff --git a/nptl/tst-mutex7a.c b/nptl/tst-mutex7a.c index f08799ae79..30d46b81af 100644 --- a/nptl/tst-mutex7a.c +++ b/nptl/tst-mutex7a.c @@ -1,2 +1,2 @@ -#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP #include "tst-mutex7.c" diff --git a/nptl/tst-mutex9.c b/nptl/tst-mutex9.c index 5ea2f0ac99..f9d379343d 100644 --- a/nptl/tst-mutex9.c +++ b/nptl/tst-mutex9.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -88,8 +88,24 @@ do_test (void) return 1; } - if (pthread_mutex_init (m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + int e; + if ((e = pthread_mutex_init (m, &a)) != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } @@ -138,7 +154,7 @@ do_test (void) ts.tv_nsec -= 1000000000; } - int e = pthread_mutex_timedlock (m, &ts); + e = pthread_mutex_timedlock (m, &ts); if (e == 0) { puts ("child: mutex_timedlock succeeded"); diff --git a/nptl/tst-mutexpi1.c b/nptl/tst-mutexpi1.c new file mode 100644 index 0000000000..623ede9fa5 --- /dev/null +++ b/nptl/tst-mutexpi1.c @@ -0,0 +1,27 @@ +#include +#include +#include + + +static pthread_mutexattr_t a; + +static void +prepare (void) +{ + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + exit (1); + } + + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("mutexattr_setprotocol failed"); + exit (1); + } +} +#define PREPARE(argc, argv) prepare () + + +#define ATTR &a +#include "tst-mutex1.c" diff --git a/nptl/tst-mutexpi2.c b/nptl/tst-mutexpi2.c new file mode 100644 index 0000000000..fbe48716fd --- /dev/null +++ b/nptl/tst-mutexpi2.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex2.c" diff --git a/nptl/tst-mutexpi3.c b/nptl/tst-mutexpi3.c new file mode 100644 index 0000000000..e338ebfff9 --- /dev/null +++ b/nptl/tst-mutexpi3.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex3.c" diff --git a/nptl/tst-mutexpi4.c b/nptl/tst-mutexpi4.c new file mode 100644 index 0000000000..177b17b475 --- /dev/null +++ b/nptl/tst-mutexpi4.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex4.c" diff --git a/nptl/tst-mutexpi5.c b/nptl/tst-mutexpi5.c new file mode 100644 index 0000000000..287465c23f --- /dev/null +++ b/nptl/tst-mutexpi5.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex5.c" diff --git a/nptl/tst-mutexpi5a.c b/nptl/tst-mutexpi5a.c new file mode 100644 index 0000000000..2f85c94ff3 --- /dev/null +++ b/nptl/tst-mutexpi5a.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex5a.c" diff --git a/nptl/tst-mutexpi6.c b/nptl/tst-mutexpi6.c new file mode 100644 index 0000000000..42cda377d1 --- /dev/null +++ b/nptl/tst-mutexpi6.c @@ -0,0 +1,27 @@ +#include +#include +#include + + +static pthread_mutexattr_t a; + +static void +prepare (void) +{ + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + exit (1); + } + + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("mutexattr_setprotocol failed"); + exit (1); + } +} +#define PREPARE(argc, argv) prepare () + + +#define ATTR &a +#include "tst-mutex6.c" diff --git a/nptl/tst-mutexpi7.c b/nptl/tst-mutexpi7.c new file mode 100644 index 0000000000..1e7e929380 --- /dev/null +++ b/nptl/tst-mutexpi7.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex7.c" diff --git a/nptl/tst-mutexpi7a.c b/nptl/tst-mutexpi7a.c new file mode 100644 index 0000000000..c59083cf6e --- /dev/null +++ b/nptl/tst-mutexpi7a.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex7a.c" diff --git a/nptl/tst-mutexpi8.c b/nptl/tst-mutexpi8.c new file mode 100644 index 0000000000..cea60309a8 --- /dev/null +++ b/nptl/tst-mutexpi8.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex8.c" diff --git a/nptl/tst-mutexpi9.c b/nptl/tst-mutexpi9.c new file mode 100644 index 0000000000..3710d9e080 --- /dev/null +++ b/nptl/tst-mutexpi9.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-mutex9.c" diff --git a/nptl/tst-robust1.c b/nptl/tst-robust1.c index 9806ca467a..bc48700e4a 100644 --- a/nptl/tst-robust1.c +++ b/nptl/tst-robust1.c @@ -97,6 +97,30 @@ do_test (void) puts ("mutexattr_setrobust failed"); return 1; } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } + else + { + int e = pthread_mutex_init (&m1, &a); + if (e == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } + else if (e != 0) + { + puts ("mutex_init m1 failed"); + return 1; + } + pthread_mutex_destroy (&m1); + } +#endif + #ifndef NOT_CONSISTENT if (pthread_mutex_init (&m1, &a) != 0) { @@ -236,14 +260,14 @@ do_test (void) e = pthread_mutex_unlock (&m1); if (e != 0) { - printf ("%ld: mutex_unlock m1 failed\n", round); + printf ("%ld: mutex_unlock m1 failed with %d\n", round, e); return 1; } e = pthread_mutex_unlock (&m2); if (e != 0) { - printf ("%ld: mutex_unlock m2 failed\n", round); + printf ("%ld: mutex_unlock m2 failed with %d\n", round, e); return 1; } diff --git a/nptl/tst-robust7.c b/nptl/tst-robust7.c index 2c5acb44ce..d0bc91cc8e 100644 --- a/nptl/tst-robust7.c +++ b/nptl/tst-robust7.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2005. @@ -95,8 +95,25 @@ do_test (void) return 1; } - if (pthread_mutex_init (&m, &a) != 0) +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + int e; + e = pthread_mutex_init (&m, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } +#endif puts ("mutex_init failed"); return 1; } @@ -123,7 +140,7 @@ do_test (void) return 1; } - int e = pthread_barrier_wait (&b); + e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { printf ("parent: barrier_wait failed in round %ld\n", n + 1); @@ -164,7 +181,7 @@ do_test (void) } } - int e = pthread_mutex_lock (&m); + e = pthread_mutex_lock (&m); if (e == 0) { puts ("parent: 2nd mutex_lock succeeded"); diff --git a/nptl/tst-robust8.c b/nptl/tst-robust8.c index 19682e594f..9c636250d4 100644 --- a/nptl/tst-robust8.c +++ b/nptl/tst-robust8.c @@ -15,7 +15,7 @@ static void prepare (void); #define PREPARE(argc, argv) prepare () static int do_test (void); #define TEST_FUNCTION do_test () -#define TIMEOUT 3 +#define TIMEOUT 5 #include "../test-skeleton.c" @@ -173,6 +173,13 @@ do_test (void) puts ("mutexattr_setpshared failed"); return 1; } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif for (int round = 1; round <= ROUNDS; ++round) { @@ -181,7 +188,11 @@ do_test (void) int e = pthread_mutex_init (&map[n], &ma); if (e == ENOTSUP) { +#ifdef ENABLE_PI + puts ("cannot support pshared robust PI mutexes"); +#else puts ("cannot support pshared robust mutexes"); +#endif return 0; } if (e != 0) diff --git a/nptl/tst-robustpi1.c b/nptl/tst-robustpi1.c new file mode 100644 index 0000000000..031291b296 --- /dev/null +++ b/nptl/tst-robustpi1.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust1.c" diff --git a/nptl/tst-robustpi2.c b/nptl/tst-robustpi2.c new file mode 100644 index 0000000000..ac411c7736 --- /dev/null +++ b/nptl/tst-robustpi2.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust2.c" diff --git a/nptl/tst-robustpi3.c b/nptl/tst-robustpi3.c new file mode 100644 index 0000000000..7dcf691e82 --- /dev/null +++ b/nptl/tst-robustpi3.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust3.c" diff --git a/nptl/tst-robustpi4.c b/nptl/tst-robustpi4.c new file mode 100644 index 0000000000..6c7b0aa7be --- /dev/null +++ b/nptl/tst-robustpi4.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust4.c" diff --git a/nptl/tst-robustpi5.c b/nptl/tst-robustpi5.c new file mode 100644 index 0000000000..a494c332f1 --- /dev/null +++ b/nptl/tst-robustpi5.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust5.c" diff --git a/nptl/tst-robustpi6.c b/nptl/tst-robustpi6.c new file mode 100644 index 0000000000..3b1482fc22 --- /dev/null +++ b/nptl/tst-robustpi6.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust6.c" diff --git a/nptl/tst-robustpi7.c b/nptl/tst-robustpi7.c new file mode 100644 index 0000000000..f8892f3521 --- /dev/null +++ b/nptl/tst-robustpi7.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust7.c" diff --git a/nptl/tst-robustpi8.c b/nptl/tst-robustpi8.c new file mode 100644 index 0000000000..cbea3d6d77 --- /dev/null +++ b/nptl/tst-robustpi8.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust8.c" diff --git a/stdlib/cxa_atexit.c b/stdlib/cxa_atexit.c index 9b7a932b85..3bdf871e53 100644 --- a/stdlib/cxa_atexit.c +++ b/stdlib/cxa_atexit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2001, 2002, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -56,6 +56,7 @@ __libc_lock_define_initialized (static, lock) static struct exit_function_list initial; struct exit_function_list *__exit_funcs = &initial; +uint64_t __new_exitfn_called; struct exit_function * __new_exitfn (void) @@ -111,7 +112,10 @@ __new_exitfn (void) /* Mark entry as used, but we don't know the flavor now. */ if (r != NULL) - r->flavor = ef_us; + { + r->flavor = ef_us; + ++__new_exitfn_called; + } __libc_lock_unlock (lock); diff --git a/stdlib/cxa_finalize.c b/stdlib/cxa_finalize.c index 43fcbc484f..bb49f36ddd 100644 --- a/stdlib/cxa_finalize.c +++ b/stdlib/cxa_finalize.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1999,2001,2002,2003,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -31,22 +31,36 @@ __cxa_finalize (void *d) { struct exit_function_list *funcs; + restart: for (funcs = __exit_funcs; funcs; funcs = funcs->next) { struct exit_function *f; for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f) - if ((d == NULL || d == f->func.cxa.dso_handle) - /* We don't want to run this cleanup more than once. */ - && ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free, - ef_cxa)) - { - void (*cxafn) (void *arg, int status) = f->func.cxa.fn; + { + void (*cxafn) (void *arg, int status); + void *cxaarg; + + if ((d == NULL || d == f->func.cxa.dso_handle) + /* We don't want to run this cleanup more than once. */ + && (cxafn = f->func.cxa.fn, + cxaarg = f->func.cxa.arg, + ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free, + ef_cxa))) + { + uint64_t check = __new_exitfn_called; + #ifdef PTR_DEMANGLE - PTR_DEMANGLE (cxafn); + PTR_DEMANGLE (cxafn); #endif - cxafn (f->func.cxa.arg, 0); - } + cxafn (cxaarg, 0); + + /* It is possible that that last exit function registered + more exit functions. Start the loop over. */ + if (__builtin_expect (check != __new_exitfn_called, 0)) + goto restart; + } + } } /* Remove the registered fork handlers. We do not have to diff --git a/stdlib/exit.h b/stdlib/exit.h index 055506f04e..779675d134 100644 --- a/stdlib/exit.h +++ b/stdlib/exit.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,1996,1997,1999,2001,2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,1996,1997,1999,2001,2002,2006 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,6 +20,7 @@ #ifndef _EXIT_H #define _EXIT_H 1 +#include enum { @@ -59,5 +61,6 @@ struct exit_function_list extern struct exit_function_list *__exit_funcs attribute_hidden; extern struct exit_function *__new_exitfn (void); +extern uint64_t __new_exitfn_called attribute_hidden; #endif /* exit.h */ diff --git a/sysdeps/unix/sysv/linux/alpha/bits/fcntl.h b/sysdeps/unix/sysv/linux/alpha/bits/fcntl.h index 9b2e635d60..6084c38c91 100644 --- a/sysdeps/unix/sysv/linux/alpha/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/alpha/bits/fcntl.h @@ -94,7 +94,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* for F_[GET|SET]FL */ +/* for F_[GET|SET]FD */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf() */ diff --git a/sysdeps/unix/sysv/linux/i386/bits/fcntl.h b/sysdeps/unix/sysv/linux/i386/bits/fcntl.h index 81d9932675..1f7ac0f25a 100644 --- a/sysdeps/unix/sysv/linux/i386/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/i386/bits/fcntl.h @@ -99,7 +99,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h index 4695d92618..1ddb4e349f 100644 --- a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h @@ -95,7 +95,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 139e3d5a72..e54f675dbe 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -431,29 +431,30 @@ /* pselect was introduced just after 2.6.16-rc1. Due to the way the kernel versions are advertised we can only rely on 2.6.17 to have the code. */ -#if __LINUX_KERNEL_VERSION >= 0x020611 \ - && (defined __i386__ || defined __powerpc__) +#if __LINUX_KERNEL_VERSION >= 0x020611 && !defined __x86_64__ # define __ASSUME_PSELECT 1 #endif /* ppoll was introduced just after 2.6.16-rc1. Due to the way the kernel versions are advertised we can only rely on 2.6.17 to have the code. */ -#if __LINUX_KERNEL_VERSION >= 0x020611 \ - && (defined __i386__ || defined __powerpc__) +#if __LINUX_KERNEL_VERSION >= 0x020611 && !defined __x86_64__ # define __ASSUME_PPOLL 1 #endif /* The *at syscalls were introduced just after 2.6.16-rc1. Due to the way the kernel versions are advertised we can only rely on 2.6.17 to have the code. */ -#if __LINUX_KERNEL_VERSION >= 0x020611 \ - && (defined __i386__ || defined __x86_64__) +#if __LINUX_KERNEL_VERSION >= 0x020611 # define __ASSUME_ATFCTS 1 #endif /* Support for inter-process robust mutexes was added in 2.6.17. */ -#if __LINUX_KERNEL_VERSION >= 0x020611 \ - && (defined __i386__ || defined __x86_64__) +#if __LINUX_KERNEL_VERSION >= 0x020611 # define __ASSUME_SET_ROBUST_LIST 1 #endif + +/* Support for PI futexes was added in 2.6.18. */ +#if __LINUX_KERNEL_VERSION >= 0x020612 +# define __ASSUME_FUTEX_LOCK_PI 1 +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h index 5d6bb6fe44..57fc7bd987 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h @@ -99,7 +99,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/s390/bits/fcntl.h b/sysdeps/unix/sysv/linux/s390/bits/fcntl.h index 166bae59bf..e5a917dbfa 100644 --- a/sysdeps/unix/sysv/linux/s390/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/s390/bits/fcntl.h @@ -114,7 +114,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/sh/bits/fcntl.h b/sysdeps/unix/sysv/linux/sh/bits/fcntl.h index 81d9932675..1f7ac0f25a 100644 --- a/sysdeps/unix/sysv/linux/sh/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/sh/bits/fcntl.h @@ -99,7 +99,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h index 022f24ac17..a965d31654 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h @@ -116,7 +116,7 @@ # define F_SETLKW64 14 /* Set record locking info (blocking). */ #endif -/* for F_[GET|SET]FL */ +/* for F_[GET|SET]FD */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ diff --git a/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h b/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h index 771de60711..4f10f22224 100644 --- a/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h @@ -113,7 +113,7 @@ # define F_NOTIFY 1026 /* Request notfications on a directory. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ -- cgit v1.2.3