]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Punt gnulib lock module.
authorNick Bowler <nbowler@draconx.ca>
Wed, 24 Jan 2024 06:19:59 +0000 (01:19 -0500)
committerNick Bowler <nbowler@draconx.ca>
Thu, 25 Jan 2024 05:34:32 +0000 (00:34 -0500)
This module is total overkill for what we need, which is to provide
one-time library initialization.  Except for the pthread_in_use
detection, this module does not appear to work around any particular
portability problem with POSIX pthread_once or standard C call_once.

On the other hand, on GNU/Linux the unused code this module links in
represents almost 5% of the size of the entire library (which includes
eight pointless PLT entries).

We have to make a local copy of the pthread_in_use macro definition,
as it is no longer imported into the project.  Further improvements
may be possible to specialize this test for our use case, but for
now stick with the Gnulib version which is known to work on a lot
of different systems.

bootstrap
lib/local/modules/dx-threadlib
src/error.c
src/thread-posix.h
src/thread-stdc.h
src/thread-w32.h

index 3f3f2a3054e5a0d73a52710814e127ebdf308a77..02ca644c68f9d410514e5a0eec813682c4602938 100755 (executable)
--- a/bootstrap
+++ b/bootstrap
@@ -33,7 +33,7 @@ if test -x $GNULIB/gnulib-tool; then
   exec 3>lib/symfiles.tmp 4<lib/symfiles.tmp
   rm -f lib/symfiles.tmp
 
-  shared_modules='lock'
+  shared_modules='threadlib windows-once'
   set x --extract-recursive-dependencies $shared_modules; shift
   (set -x; $GNULIB/gnulib-tool "$@" >&3 ) || die "gnulib-tool failed"
   shared_modules=`LC_ALL=C sort -u <&4`
index 85699e39b886394b6600637f9667dc9ced095711..9499e3b5cac112d68741d22f80656d8fb8c7f825 100644 (file)
@@ -7,7 +7,7 @@ Files:
 Depends-on:
 gnulib-local
 threadlib
-lock [test x"$glthreads_api" != x"none"]
+windows-once [test x"$gl_threads_api" = x"windows"]
 
 configure.ac-early:
 dnl AC_REQUIRE has the effect of making the macro expansion unconditional;
index 0ff31ee0a4f6871e5eaadac892aed76c4b2b7878..eb85b89c1bcbb4b015a0c36a9df33922da31d025 100644 (file)
 
 #include "cdecl.h"
 #include "cdecl-internal.h"
-
-#include <glthread/lock.h>
-
 #include "errmsg.h"
 
-#if USE_POSIX_THREADS
-#  include "thread-posix.h"
-#elif USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
-#  include "thread-stdc.h"
-#elif USE_WINDOWS_THREADS
-#  include "thread-w32.h"
-#else
-static void *tls_key;
-enum { tls_key_valid = 1 };
-
-#define tls_key_init() ((void)0)
-#define tls_get() tls_key
-#define tls_set(a) (tls_key = (a), 1)
-#endif
-
-struct err_state {
-       struct cdecl_error err;
-       size_t nstr;
-       char str[FLEXIBLE_ARRAY_MEMBER];
-};
-
 /* This pre-initialized error is reserved for dire out-of-memory conditions. */
 static struct cdecl_error err_no_mem;
 
@@ -69,16 +45,43 @@ static void set_err(unsigned code, struct cdecl_error *err)
        err->str = _(&errmsgs[code]);
 }
 
-static void initialize_cb(void)
+static void init_once_cb(void)
 {
 #if ENABLE_NLS
        bindtextdomain(PACKAGE, LOCALEDIR);
        bindtextdomain("bison-runtime", BISON_LOCALEDIR);
 #endif
        set_err(CDECL__ENOMEM, &err_no_mem);
-       tls_key_init();
 }
 
+#if USE_POSIX_THREADS
+#  include "thread-posix.h"
+#elif USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
+#  include "thread-stdc.h"
+#elif USE_WINDOWS_THREADS
+#  include "thread-w32.h"
+#else
+static void *tls_key;
+enum { tls_key_valid = 1 };
+
+#define tls_get() tls_key
+#define tls_set(a) ((tls_key = (a)), 1)
+
+static int init_once(void)
+{
+       if (!err_no_mem.code)
+               init_once_cb();
+       return 1;
+}
+
+#endif
+
+struct err_state {
+       struct cdecl_error err;
+       size_t nstr;
+       char str[FLEXIBLE_ARRAY_MEMBER];
+};
+
 static void *alloc_err_state(void *old, size_t buf_size)
 {
        struct err_state *state;
@@ -109,8 +112,7 @@ static struct err_state *get_err_state(void)
 {
        void *state;
 
-       gl_once_define(static, tls_initialized)
-       if (glthread_once(&tls_initialized, initialize_cb) || !tls_key_valid)
+       if (!init_once())
                return NULL;
 
        if (!(state = tls_get()))
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;
+}
index 46fe361b0bd74d3f63abbcf0046d9c236ef5a789..a29ec8c4d94c0fc81686a6b65b89073e9fbf1652 100644 (file)
 static tss_t tls_key;
 static bool tls_key_valid;
 
-static void tls_key_init(void)
-{
-       tls_key_valid = (tss_create(&tls_key, free) == thrd_success);
-}
+static void init_once_cb(void);
 
 static void *tls_get(void)
 {
@@ -36,3 +33,17 @@ static int tls_set(void *p)
 {
        return tss_set(tls_key, p) == thrd_success;
 }
+
+static void init_once_with_tls(void)
+{
+       tls_key_valid = (tss_create(&tls_key, free) == thrd_success);
+       init_once_cb();
+}
+
+static int init_once(void)
+{
+       static once_flag flag;
+
+       call_once(&flag, init_once_with_tls);
+       return 1;
+}
index 44282d87dd8d39a9a0c6848b8279697f4474c12b..fb3bdc40870e4ee005185215a429bfdafc3d856e 100644 (file)
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include "windows-once.h"
 
 static DWORD tls_key;
 #define tls_key_valid (tls_key != TLS_OUT_OF_INDEXES)
 
-static void tls_key_init(void)
-{
-       tls_key = TlsAlloc();
-}
+static void init_once_cb(void);
 
 static void *tls_get(void)
 {
@@ -37,3 +35,17 @@ static BOOL tls_set(void *p)
 {
        return TlsSetValue(tls_key, p);
 }
+
+static void init_once_with_tls(void)
+{
+       tls_key = TlsAlloc();
+       init_once_cb();
+}
+
+static int init_once(void)
+{
+       static glwthread_once_t ctrl = GLWTHREAD_ONCE_INIT;
+
+       glwthread_once(&ctrl, init_once_with_tls);
+       return 1;
+}