Patchwork [committed] Revise gthread active check on hppa-hpux11

login
register
mail settings
Submitter John David Anglin
Date Aug. 22, 2010, 4:51 p.m.
Message ID <20100822165135.GA1737@hiauly1.hia.nrc.ca>
Download mbox | patch
Permalink /patch/62392/
State New
Headers show

Comments

John David Anglin - Aug. 22, 2010, 4:51 p.m.
I recently changed the __gthread_active_p check on hppa-hpux11 to use
pthread_default_stacksize_np because the old method using pthread_create
creates a thread and breaks pthread_default_stacksize_np.  However,
Olivier pointed out that HP only added a stub for pthread_default_stacksize_np
to libc.sl in a fairly recent patch.  Further, I noticed that there
is still no stub in the archive variant of libc.  The same is true for
other pthread functions.  We had side stepped the lack of stubs in libc.a
by linking against libpthread.a when -static was specified.

The attached patch adds stubs for pthread_default_stacksize_np, pthread_lock
and pthread_unlock to our own stub library, libgcc_stub.a, and the SPEC
machinary to link against it when not building a shared library.  LIB_SPEC
is modified to only add -lpthread when -mt or -pthread is specified.
The build machinary is updated on the 32-bit targets to build the stub
library.

I simplified the __gthread_active_p check since as far as I can tell
there was no reason to take a lock around the check.

The downside of this approach is the additional complexity in linking
threaded applications, but this is difficult to avoid given the lack
of proper weak support.

Tested on hppa2.0w-hp-hpux11.11 and hppa64-hp-hpux11.11.  Committed to
trunk.

Dave

Patch

Index: gthr-posix.h
===================================================================
--- gthr-posix.h	(revision 163445)
+++ gthr-posix.h	(working copy)
@@ -260,47 +260,34 @@ 
    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
+   provided for checking whether an application is linked to a shared 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.  */
+   libpthread libraries.  We also need a test that works for archive
+   libraries.  We can't use pthread_once as some libc versions call the
+   init function.  We also can't use pthread_create or pthread_attr_init
+   as these create a thread and thereby prevent changing the default stack
+   size.  The function pthread_default_stacksize_np is available in both
+   the archive and shared versions of libpthread.   It can be used to
+   determine the default pthread stack size.  There is a stub in some
+   shared libc versions which returns a zero size if pthreads are not
+   active.  We provide an equivalent stub to handle cases where libc
+   doesn't provide one.  */
 
 #if defined(__hppa__) && defined(__hpux__)
 
-#include <errno.h>
-
 static volatile int __gthread_active = -1;
 
-static void __gthread_active_init (void) __attribute__((noinline));
-static void
-__gthread_active_init (void)
-{
-  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
-  size_t __s;
-
-  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
-  if (__gthread_active < 0)
-    {
-      pthread_default_stacksize_np (0, &__s);
-      __gthread_active = __s ? 1 : 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;
+  size_t __s;
 
-  /* 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 ();
+      pthread_default_stacksize_np (0, &__s);
+      __gthread_active = __s ? 1 : 0;
       __gthread_active_latest_value = __gthread_active;
     }
 
Index: gthr-posix95.h
===================================================================
--- gthr-posix95.h	(revision 163445)
+++ gthr-posix95.h	(working copy)
@@ -184,47 +184,34 @@ 
    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
+   provided for checking whether an application is linked to a shared 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.  */
+   pthread libraries.  We also need a test that works for archive
+   libraries.  We can't use pthread_once as some libc versions call the
+   init function.  We also can't use pthread_create or pthread_attr_init
+   as these create a thread and thereby prevent changing the default stack
+   size.  The function pthread_default_stacksize_np is available in both
+   the archive and shared versions of libpthread.   It can be used to
+   determine the default pthread stack size.  There is a stub in some
+   shared libc versions which returns a zero size if pthreads are not
+   active.  We provide an equivalent stub to handle cases where libc
+   doesn't provide one.  */
 
 #if defined(__hppa__) && defined(__hpux__)
 
-#include <errno.h>
-
 static volatile int __gthread_active = -1;
 
-static void __gthread_active_init (void) __attribute__((noinline));
-static void
-__gthread_active_init (void)
-{
-  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
-  size_t __s;
-
-  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
-  if (__gthread_active < 0)
-    {
-      pthread_default_stacksize_np (0, &__s);
-      __gthread_active = __s ? 1 : 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;
+  size_t __s;
 
-  /* 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 ();
+      pthread_default_stacksize_np (0, &__s);
+      __gthread_active = __s ? 1 : 0;
       __gthread_active_latest_value = __gthread_active;
     }
 
Index: config.gcc
===================================================================
--- config.gcc	(revision 163445)
+++ config.gcc	(working copy)
@@ -1106,6 +1106,7 @@ 
 	else
 	    tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
 	fi
+	extra_parts="libgcc_stub.a"
 	case x${enable_threads} in
 	x | xyes | xposix )
 		thread_file=posix
Index: config/pa/pa64-hpux.h
===================================================================
--- config/pa/pa64-hpux.h	(revision 163445)
+++ config/pa/pa64-hpux.h	(working copy)
@@ -59,35 +59,35 @@ 
 #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GNU_LD)
 #define LIB_SPEC \
   "%{!shared:\
-     %{!p:%{!pg:%{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-		  %{static:-a archive}} -lpthread} -lc\
+     %{!p:%{!pg:%{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+	    %{mt|pthread:-lpthread} -lc\
 	    %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
      %{p:%{!pg:%{static:%{!mhp-ld:-a shared}%{mhp-ld:-a archive_shared}}\
 	   -lprof %{static:-a archive}\
-	   %{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-	     %{static:-a archive}} -lpthread} -lc\
+	   %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+	   %{mt|pthread:-lpthread} -lc\
 	   %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
      %{pg:%{static:%{!mhp-ld:-a shared}%{mhp-ld:-a archive_shared}}\
        -lgprof %{static:-a archive}\
-       %{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-	 %{static:-a archive}} -lpthread} -lc\
+       %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+       %{mt|pthread:-lpthread} -lc\
        %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
    %{shared:%{mt|pthread:-lpthread}}"
 #else
 #define LIB_SPEC \
   "%{!shared:\
-     %{!p:%{!pg:%{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-		  %{static:-a archive}} -lpthread} -lc\
+     %{!p:%{!pg:%{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+	    %{mt|pthread:-lpthread} -lc\
 	    %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
      %{p:%{!pg:%{static:%{mgnu-ld:-a shared}%{!mgnu-ld:-a archive_shared}}\
 	   -lprof %{static:-a archive}\
-	   %{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-	     %{static:-a archive}} -lpthread} -lc\
+	   %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+	   %{mt|pthread:-lpthread} -lc\
 	   %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
      %{pg:%{static:%{mgnu-ld:-a shared}%{!mgnu-ld:-a archive_shared}}\
        -lgprof %{static:-a archive}\
-       %{static|mt|pthread:%{fopenmp:%{static:-a shared} -lrt\
-	 %{static:-a archive}} -lpthread} -lc\
+       %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+       %{mt|pthread:-lpthread} -lc\
        %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\
    %{shared:%{mt|pthread:-lpthread}}"
 #endif
Index: config/pa/t-pa-hpux11
===================================================================
--- config/pa/t-pa-hpux11	(revision 163445)
+++ config/pa/t-pa-hpux11	(working copy)
@@ -1,2 +1,26 @@ 
 TARGET_LIBGCC2_CFLAGS = -fPIC -frandom-seed=fixed-seed
 LIB2FUNCS_EXTRA=lib2funcs.asm quadlib.c
+LIBGCCSTUB_OBJS = pthread_default_stacksize_np-stub.o \
+	pthread_mutex_lock-stub.o \
+	pthread_mutex_unlock-stub.o
+
+stublib.c: $(srcdir)/config/pa/stublib.c
+	rm -f stublib.c
+	cp $(srcdir)/config/pa/stublib.c .
+
+pthread_default_stacksize_np-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_default_stacksize_np stublib.c \
+	  -o pthread_default_stacksize_np-stub.o
+
+pthread_mutex_lock-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_lock stublib.c \
+	  -o pthread_mutex_lock-stub.o
+
+pthread_mutex_unlock-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_unlock stublib.c \
+	  -o pthread_mutex_unlock-stub.o
+
+$(T)libgcc_stub.a: $(LIBGCCSTUB_OBJS)
+	-rm -rf $(T)libgcc_stub.a
+	$(AR) rc $(T)libgcc_stub.a $(LIBGCCSTUB_OBJS)
+	$(RANLIB) $(T)libgcc_stub.a
Index: config/pa/pa-hpux11.h
===================================================================
--- config/pa/pa-hpux11.h	(revision 163445)
+++ config/pa/pa-hpux11.h	(working copy)
@@ -121,11 +121,16 @@ 
 #undef LIB_SPEC
 #define LIB_SPEC \
   "%{!shared:\
-     %{static|mt|pthread:%{fopenmp:%{static:-a archive_shared} -lrt\
-       %{static:-a archive}} -lpthread} -lc\
+     %{fopenmp:%{static:-a archive_shared} -lrt %{static:-a archive}}\
+     %{mt|pthread:-lpthread} -lc\
      %{static:%{!nolibdld:-a archive_shared -ldld -a archive -lc}}}\
    %{shared:%{mt|pthread:-lpthread}}"
 
+/* The libgcc_stub.a library needs to come last.  */
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC \
+  "%G %L %G %{!nostdlib:%{!nodefaultlibs:%{!shared:-lgcc_stub}}}"
+
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC \
   "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}} \
Index: config/pa/t-pa64
===================================================================
--- config/pa/t-pa64	(revision 163445)
+++ config/pa/t-pa64	(working copy)
@@ -1,5 +1,5 @@ 
 # Copyright (C) 2000, 2001, 2002, 2004, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2010 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -19,7 +19,10 @@ 
 
 TARGET_LIBGCC2_CFLAGS = -fPIC -Dpa64=1 -DELF=1 -mlong-calls
 LIB2FUNCS_EXTRA = quadlib.c
-LIBGCCSTUB_OBJS = rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o
+LIBGCCSTUB_OBJS = rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o \
+	pthread_default_stacksize_np-stub.o \
+	pthread_mutex_lock-stub.o \
+	pthread_mutex_unlock-stub.o
 
 stublib.c: $(srcdir)/config/pa/stublib.c
 	rm -f stublib.c
@@ -41,6 +44,18 @@ 
 	$(GCC_FOR_TARGET) -c -O2 -DL_Jv_RegisterClasses stublib.c \
 	  -o jvrc-stub.o
 
+pthread_default_stacksize_np-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_default_stacksize_np stublib.c \
+	  -o pthread_default_stacksize_np-stub.o
+
+pthread_mutex_lock-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_lock stublib.c \
+	  -o pthread_mutex_lock-stub.o
+
+pthread_mutex_unlock-stub.o: stublib.c $(GCC_PASSES)
+	$(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_unlock stublib.c \
+	  -o pthread_mutex_unlock-stub.o
+
 $(T)libgcc_stub.a: $(LIBGCCSTUB_OBJS)
 	-rm -rf $(T)libgcc_stub.a
 	$(AR) rc $(T)libgcc_stub.a $(LIBGCCSTUB_OBJS)
Index: config/pa/stublib.c
===================================================================
--- config/pa/stublib.c	(revision 163445)
+++ config/pa/stublib.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* Stub functions.
-   Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -56,3 +56,33 @@ 
 {
 }
 #endif
+
+#ifdef L_pthread_default_stacksize_np
+int pthread_default_stacksize_np (unsigned long __attribute__((unused)),
+				  unsigned long *);
+int
+pthread_default_stacksize_np (unsigned long new, unsigned long *old)
+{
+  if (old)
+    *old = 0;
+  return 0;
+}
+#endif
+
+#ifdef L_pthread_mutex_lock
+int pthread_mutex_lock (void * __attribute__((unused)));
+int
+pthread_mutex_lock (void *p)
+{
+  return 0;
+}
+#endif
+
+#ifdef L_pthread_mutex_unlock
+int pthread_mutex_unlock (void * __attribute__((unused)));
+int
+pthread_mutex_unlock (void *p)
+{
+  return 0;
+}
+#endif