Add run-time determination of whether thread support is available in the
authorKen Raeburn <raeburn@mit.edu>
Wed, 1 Jun 2005 00:56:01 +0000 (00:56 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 1 Jun 2005 00:56:01 +0000 (00:56 +0000)
support library.  Check lots of weak references, and call pthread_once a couple
of times, to distinguish a broken stub from the real thing.

* threads.c [HAVE_PRAGMA_WEAK_REF]: Declare pthread_{g,s}etspecific,
pthread_key_{create,delete}, pthread_{create,join} as weak references.
(krb5int_pthread_loaded, loaded_test_aux) [HAVE_PRAGMA_WEAK_REF]: New
functions.
(flag_pthread_loaded, loaded_test_once) [HAVE_PRAGMA_WEAK_REF]: New variables.
* libkrb5support.exports: Add krb5int_pthread_loaded.

ticket: 3084
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17223 dc483132-0cff-0310-8789-dd5450dbe970

src/util/support/ChangeLog
src/util/support/libkrb5support.exports
src/util/support/threads.c

index fa6147e924988157a45e15e82d51571f2c9fbd72..eae47fc66c42767f55e1d525cd0ab356beebf65b 100644 (file)
@@ -1,3 +1,14 @@
+2005-05-31  Ken Raeburn  <raeburn@mit.edu>
+
+       * threads.c [HAVE_PRAGMA_WEAK_REF]: Declare
+       pthread_{g,s}etspecific, pthread_key_{create,delete},
+       pthread_{create,join} as weak references.
+       (krb5int_pthread_loaded, loaded_test_aux) [HAVE_PRAGMA_WEAK_REF]:
+       New functions.
+       (flag_pthread_loaded, loaded_test_once) [HAVE_PRAGMA_WEAK_REF]:
+       New variables.
+       * libkrb5support.exports: Add krb5int_pthread_loaded.
+
 2005-05-17  Ken Raeburn  <raeburn@mit.edu>
 
        * fake-addrinfo.c (fai_add_hosts_by_name): Pass null pointer
index 2464c02d4884f539a00b044f724a73a3f31f8dd0..9607ef8226b094b3ecf03df0ed096ebf46c77afd 100644 (file)
@@ -10,3 +10,4 @@ krb5int_freeaddrinfo
 krb5int_gai_strerror
 krb5int_getnameinfo
 krb5int_in6addr_any
+krb5int_pthread_loaded
index e1e56e20da7eaf1982aa26b522363bbabf92a168..d07b6ffff324530c350f79831e701f5670f8571b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * util/support/threads.c
  *
- * Copyright 2004 by the Massachusetts Institute of Technology.
+ * Copyright 2004,2005 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -106,6 +106,61 @@ struct tsd_block {
 # pragma weak pthread_setspecific
 # pragma weak pthread_key_create
 # pragma weak pthread_key_delete
+# pragma weak pthread_create
+# pragma weak pthread_join
+static volatile int flag_pthread_loaded = -1;
+static void loaded_test_aux(void)
+{
+    if (flag_pthread_loaded == -1)
+       flag_pthread_loaded = 1;
+    else
+       /* Could we have been called twice?  */
+       flag_pthread_loaded = 0;
+}
+static pthread_once_t loaded_test_once = PTHREAD_ONCE_INIT;
+int krb5int_pthread_loaded (void)
+{
+    int x = flag_pthread_loaded;
+    if (x != -1)
+       return x;
+    if (&pthread_getspecific == 0
+       || &pthread_setspecific == 0
+       || &pthread_key_create == 0
+       || &pthread_key_delete == 0
+       || &pthread_once == 0
+       || &pthread_mutex_lock == 0
+       || &pthread_mutex_unlock == 0
+       || &pthread_mutex_destroy == 0
+       || &pthread_mutex_init == 0
+       || &pthread_self == 0
+       || &pthread_equal == 0
+       /* This catches Solaris 9.  May be redundant with the above
+          tests now.  */
+# ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP_IN_THREAD_LIB
+       || &pthread_mutexattr_setrobust_np == 0
+# endif
+       /* Any program that's really multithreaded will have to be
+          able to create threads.  */
+       || &pthread_create == 0
+       || &pthread_join == 0
+       /* Okay, all the interesting functions -- or stubs for them --
+          seem to be present.  If we call pthread_once, does it
+          actually seem to cause the indicated function to get called
+          exactly one time?  */
+       || pthread_once(&loaded_test_once, loaded_test_aux) != 0
+       || pthread_once(&loaded_test_once, loaded_test_aux) != 0
+       /* This catches cases where pthread_once does nothing, and
+          never causes the function to get called.  That's a pretty
+          clear violation of the POSIX spec, but hey, it happens.  */
+       || flag_pthread_loaded < 0) {
+       flag_pthread_loaded = 0;
+       return 0;
+    }
+    /* If we wanted to be super-paranoid, we could try testing whether
+       pthread_get/setspecific work, too.  I don't know -- so far --
+       of any system with non-functional stubs for those.  */
+    return flag_pthread_loaded;
+}
 static struct tsd_block tsd_if_single;
 # define GET_NO_PTHREAD_TSD()  (&tsd_if_single)
 #else