]> git.draconx.ca Git - cdecl99.git/blobdiff - src/thread-posix.h
libcdecl: Punt gnulib lock module.
[cdecl99.git] / src / thread-posix.h
index b1cd990c3f1034fa1e5464a89d72dc075d51bd00..22378ed9ef17f85762877a27bd8990daf94e6e24 100644 (file)
@@ -8,6 +8,16 @@
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
+ * The pthread_in_use detection is based on Gnulib code written by Bruno
+ * Haible, distributed with the following copyright and permission notice:
+ *
+ *      Copyright (C) 2005-2022 Free Software Foundation, Inc.
+ *
+ *      This file is free software: you can redistribute it and/or modify
+ *      it under the terms of the GNU Lesser General Public License as
+ *      published by the Free Software Foundation; either version 2.1 of
+ *      the License, or (at your option) any later version.
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 #include <pthread.h>
 
+extern int glthread_in_use();
+
+#if !defined c11_threads_in_use
+#  if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
+#    define c11_threads_in_use 1
+#  elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
+#    include <threads.h>
+#    pragma weak thrd_exit
+#    define c11_threads_in_use (thrd_exit != NULL)
+#  else
+#    define c11_threads_in_use 0
+#  endif
+#endif
+
+#if PTHREAD_IN_USE_DETECTION_HARD
+#  define pthread_in_use glthread_in_use()
+#elif USE_POSIX_THREADS_WEAK
+#  pragma weak pthread_mutexattr_gettype
+#  define pthread_in_use (pthread_mutexattr_gettype || c11_threads_in_use)
+#else
+#  define pthread_in_use 1
+#endif
+
 #if USE_POSIX_THREADS_WEAK
 #  pragma weak pthread_key_create
 #  pragma weak pthread_getspecific
@@ -41,13 +74,7 @@ static struct {
 } tls_key;
 #define tls_key_valid (tls_key.valid != 0)
 
-static void tls_key_init(void)
-{
-       if (pthread_in_use())
-               tls_key.valid = !pthread_key_create(&tls_key.u.mt, free);
-       else
-               tls_key.valid = -1;
-}
+static void init_once_cb(void);
 
 static void *tls_get(void)
 {
@@ -66,3 +93,22 @@ static int tls_set(void *p)
 #endif
        return !pthread_setspecific(tls_key.u.mt, p);
 }
+
+static void init_once_with_tls(void)
+{
+       tls_key.valid = !pthread_key_create(&tls_key.u.mt, free);
+       init_once_cb();
+}
+
+static int init_once(void)
+{
+       if (pthread_in_use) {
+               static pthread_once_t ctrl = PTHREAD_ONCE_INIT;
+               return !pthread_once(&ctrl, init_once_with_tls);
+       } else if (!tls_key_valid) {
+               tls_key.valid = -1;
+               init_once_cb();
+       }
+
+       return 1;
+}