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.
exec 3>lib/symfiles.tmp 4<lib/symfiles.tmp
rm -f lib/symfiles.tmp
exec 3>lib/symfiles.tmp 4<lib/symfiles.tmp
rm -f lib/symfiles.tmp
+ 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`
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`
Depends-on:
gnulib-local
threadlib
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;
configure.ac-early:
dnl AC_REQUIRE has the effect of making the macro expansion unconditional;
#include "cdecl.h"
#include "cdecl-internal.h"
#include "cdecl.h"
#include "cdecl-internal.h"
-
-#include <glthread/lock.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;
/* This pre-initialized error is reserved for dire out-of-memory conditions. */
static struct cdecl_error err_no_mem;
err->str = _(&errmsgs[code]);
}
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);
{
#if ENABLE_NLS
bindtextdomain(PACKAGE, LOCALEDIR);
bindtextdomain("bison-runtime", BISON_LOCALEDIR);
#endif
set_err(CDECL__ENOMEM, &err_no_mem);
+#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;
static void *alloc_err_state(void *old, size_t buf_size)
{
struct err_state *state;
- gl_once_define(static, tls_initialized)
- if (glthread_once(&tls_initialized, initialize_cb) || !tls_key_valid)
return NULL;
if (!(state = tls_get()))
return NULL;
if (!(state = tls_get()))
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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
* 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
+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
#if USE_POSIX_THREADS_WEAK
# pragma weak pthread_key_create
# pragma weak pthread_getspecific
} tls_key;
#define tls_key_valid (tls_key.valid != 0)
} 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)
{
static void *tls_get(void)
{
#endif
return !pthread_setspecific(tls_key.u.mt, 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;
+}
static tss_t tls_key;
static bool tls_key_valid;
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)
{
static void *tls_get(void)
{
{
return tss_set(tls_key, p) == thrd_success;
}
{
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;
+}
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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 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)
{
static void *tls_get(void)
{
{
return TlsSetValue(tls_key, 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;
+}