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`
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;
#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;
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;
{
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()))
* 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
} 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)
{
#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 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)
{
{
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>
+#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)
{
{
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;
+}