diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec6b104d014..7d2b14ed717 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-09-07 John David Anglin + + PR target/33286 + * gthr-posix.h (__gthread_active_p): Add implementation for hppa-hpux. + (__gthread_active,__gthread_start, __gthread_active_init): New. + * gthr-posix95.h: Likewise. + 2007-09-07 Roman Zippel * function.h (struct function): Rename calls_unwind_init diff --git a/gcc/gthr-posix.h b/gcc/gthr-posix.h index 47d38a320ba..a290b6aab7c 100644 --- a/gcc/gthr-posix.h +++ b/gcc/gthr-posix.h @@ -211,12 +211,81 @@ __gthread_active_p (void) #else /* not SUPPORTS_WEAK */ +/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread + calls in shared flavors of the HP-UX C library. Most of the stubs + have no functionality. The details are described in the "libc cumulative + patch" for each subversion of HP-UX 11. There are two special interfaces + provided for checking whether an application is linked to a pthread + library or not. However, these interfaces aren't available in early + libc versions. We also can't use pthread_once as some libc versions + call the init function. So, we use pthread_create to check whether it + is possible to create a thread or not. The stub implementation returns + the error number ENOSYS. */ + +#if defined(__hppa__) && defined(__hpux__) + +#include + +static volatile int __gthread_active = -1; + +static void * +__gthread_start (void *arg __attribute__((unused))) +{ + return NULL; +} + +static void __gthread_active_init (void) __attribute__((noinline)); +static void +__gthread_active_init (void) +{ + static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_t t; + int result; + + __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); + if (__gthread_active < 0) + { + result = __gthrw_(pthread_create) (&t, NULL, __gthread_start, NULL); + if (result != ENOSYS) + { + __gthread_active = 1; + if (!result) + __gthrw_(pthread_join) (t, NULL); + } + else + __gthread_active = 0; + } + __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); +} + +static inline int +__gthread_active_p (void) +{ + /* Avoid reading __gthread_active twice on the main code path. */ + int __gthread_active_latest_value = __gthread_active; + + /* This test is not protected to avoid taking a lock on the main code + path so every update of __gthread_active in a threaded program must + be atomic with regard to the result of the test. */ + if (__builtin_expect (__gthread_active_latest_value < 0, 0)) + { + __gthread_active_init (); + __gthread_active_latest_value = __gthread_active; + } + + return __gthread_active_latest_value != 0; +} + +#else /* not hppa-hpux */ + static inline int __gthread_active_p (void) { return 1; } +#endif /* hppa-hpux */ + #endif /* SUPPORTS_WEAK */ #ifdef _LIBOBJC diff --git a/gcc/gthr-posix95.h b/gcc/gthr-posix95.h index fde264594f8..f0d1553193e 100644 --- a/gcc/gthr-posix95.h +++ b/gcc/gthr-posix95.h @@ -1,6 +1,6 @@ /* Threads compatibility routines for libgcc2 and libobjc. */ /* Compile this one with gcc. */ -/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -174,12 +174,81 @@ __gthread_active_p (void) #else /* not SUPPORTS_WEAK */ +/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread + calls in shared flavors of the HP-UX C library. Most of the stubs + have no functionality. The details are described in the "libc cumulative + patch" for each subversion of HP-UX 11. There are two special interfaces + provided for checking whether an application is linked to a pthread + library or not. However, these interfaces aren't available in early + libc versions. We also can't use pthread_once as some libc versions + call the init function. So, we use pthread_create to check whether it + is possible to create a thread or not. The stub implementation returns + the error number ENOSYS. */ + +#if defined(__hppa__) && defined(__hpux__) + +#include + +static volatile int __gthread_active = -1; + +static void * +__gthread_start (void *arg __attribute__((unused))) +{ + return NULL; +} + +static void __gthread_active_init (void) __attribute__((noinline)); +static void +__gthread_active_init (void) +{ + static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_t t; + int result; + + __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); + if (__gthread_active < 0) + { + result = __gthrw_(pthread_create) (&t, NULL, __gthread_start, NULL); + if (result != ENOSYS) + { + __gthread_active = 1; + if (!result) + __gthrw_(pthread_join) (t, NULL); + } + else + __gthread_active = 0; + } + __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); +} + +static inline int +__gthread_active_p (void) +{ + /* Avoid reading __gthread_active twice on the main code path. */ + int __gthread_active_latest_value = __gthread_active; + + /* This test is not protected to avoid taking a lock on the main code + path so every update of __gthread_active in a threaded program must + be atomic with regard to the result of the test. */ + if (__builtin_expect (__gthread_active_latest_value < 0, 0)) + { + __gthread_active_init (); + __gthread_active_latest_value = __gthread_active; + } + + return __gthread_active_latest_value != 0; +} + +#else /* not hppa-hpux */ + static inline int __gthread_active_p (void) { return 1; } +#endif /* hppa-hpux */ + #endif /* SUPPORTS_WEAK */ #ifdef _LIBOBJC