The glibc 2.32 announcement says:

  Using weak references to libpthread functions such as pthread_create
  or pthread_key_create to detect the singled-threaded nature of a
  program is an obsolescent feature.  Future versions of glibc will
  define pthread_create within libc.so.6 itself, so such checks will
  always flag the program as multi-threaded.  Applications should check
  the __libc_single_threaded variable declared in
  <sys/single_threaded.h> instead.

See also
<https://www.gnu.org/software/libc/manual/html_node/Single_002dThreaded.html>.

So, this means, the pthread_in_use() macro will evaluate to 1 always
in some future versions of glibc.

The new __libc_single_threaded variable is not a full replacement for
this. In these future glibc versions,
  - It will not be possible to skip the initialization of locks,
    only the lock/unlock operations - because some part of the program
    may create a thread, and then __libc_single_threaded changes from 1 to 0.
  - Optimization of TLS (pthread_getspecific and pthread_setspecific
    functions) is hairy as well.

Let me add support for this technique to some gnulib modules.
'regex' could use the same technique as well. May I leave this to you, Paul?


2020-08-08  Bruno Haible  <[email protected]>

        localename: Use module 'thread-optim'.
        * lib/localename.c: Include thread-optim.h.
        (struniq): Use IF_MT macro.
        * modules/localename (Depends-on): Add thread-optim.

        clean-temp: Use module 'thread-optim'.
        * lib/clean-temp.c: Include thread-optim.h.
        (register_temporary_file, unregister_temporary_file, create_temp_dir,
        register_temp_file, unregister_temp_file, register_temp_subdir,
        unregister_temp_subdir, cleanup_temp_dir_contents, register_fd,
        close_temp, fclose_variant_temp): Use IF_MT macro.
        * modules/clean-temp (Depends-on): Add thread-optim.

        fatal-signal: Use module 'thread-optim'.
        * lib/fatal-signal.c: Include thread-optim.h.
        (at_fatal_signal, block_fatal_signals, unblock_fatal_signals): Use IF_MT
        macro.
        * modules/fatal-signal (Depends-on): Add thread-optim.

>From db6c51cb278392aee178a3e836f37e0f2a7b1990 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 8 Aug 2020 19:47:28 +0200
Subject: [PATCH 1/4] New module 'thread-optim'.

* lib/thread-optim.h: New file.
* modules/thread-optim: New file.
* doc/multithread.texi (Multithreading Optimizations): New section.
---
 ChangeLog            |  7 ++++++
 doc/multithread.texi | 47 ++++++++++++++++++++++++++++++++++++++++
 lib/thread-optim.h   | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 modules/thread-optim | 21 ++++++++++++++++++
 4 files changed, 135 insertions(+)
 create mode 100644 lib/thread-optim.h
 create mode 100644 modules/thread-optim

diff --git a/ChangeLog b/ChangeLog
index 73e2056..ee9b6ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2020-08-08  Bruno Haible  <[email protected]>
+
+	New module 'thread-optim'.
+	* lib/thread-optim.h: New file.
+	* modules/thread-optim: New file.
+	* doc/multithread.texi (Multithreading Optimizations): New section.
+
 2020-08-07  Paul Eggert  <[email protected]>
 
 	doc: more updates for glibc 2.32
diff --git a/doc/multithread.texi b/doc/multithread.texi
index b600517..022a6cb 100644
--- a/doc/multithread.texi
+++ b/doc/multithread.texi
@@ -60,6 +60,7 @@ Nevertheless, they need to use mutexes/locks in many cases.
 * POSIX multithreading::
 * ISO C multithreading::
 * Gnulib multithreading::
+* Multithreading Optimizations::
 @end menu
 
 @node Multithreading APIs
@@ -216,3 +217,49 @@ native Windows platforms (mingw and MSVC).
 ISO C multithreading API.  However, @code{--enable-threads=posix} is always
 a better choice.
 @end itemize
+
+@node Multithreading Optimizations
+@section Optimizations of multithreaded code
+
+Despite all the optimizations of multithreading primitives that have been
+implemented over the years --- from
+@url{https://en.wikipedia.org/wiki/Compare-and-swap,
+atomic operations in hardware},
+over @url{https://en.wikipedia.org/wiki/Futex, futexes} and
+@url{https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/,
+restartable sequences}
+in the Linux kernel, to lock elision
+@url{https://lwn.net/Articles/534758/, [1]}
+@url{https://www.gnu.org/software/libc/manual/html_node/Elision-Tunables.html,
+[2]})
+--- single-threaded programs can still profit performance-wise from the
+assertion that they are single-threaded.
+
+Gnulib defines four facilities that help optimizing for the single-threaded
+case.
+
+@itemize @bullet
+@item
+The Gnulib multithreading API, when used on glibc @leq{} 2.32 and *BSD systems,
+uses weak symbols to detect whether the program is linked with
+@code{libpthread}.  If not, the program has no way to create additional
+threads and must therefore be single-threaded.  This optimization applies
+to all the Gnulib multithreading API (locks, thread-local storage, and more).
+@item
+The @code{thread-optim} module, on glibc @geq{} 2.32 systems, allows your code
+to skip locking between threads (regardless which of the three multithreading
+APIs you use).  You need extra code for this: include the
+@code{"thread-optim.h"} header file, and use the macros @code{IF_MT_DECL}
+and @code{IF_MT}.
+@item
+The @code{unlocked-io} module is applicable only if all the programs in your
+package are single-threaded.  It optimizes the operations on @code{FILE}
+streams.  You need extra code for this: include the @code{"unlocked-io.h"}
+header file.  Some Gnulib modules that do operations on @code{FILE} streams
+have these preparations already included.
+@item
+You may define the C macro @code{GNULIB_WCHAR_SINGLE}, if all the programs in
+your package are single-threaded and won't change the locale after it has
+been initialized.  This macro optimizes the functions @code{mbrtowc} and
+@code{wcwidth}.
+@end itemize
diff --git a/lib/thread-optim.h b/lib/thread-optim.h
new file mode 100644
index 0000000..8040d53
--- /dev/null
+++ b/lib/thread-optim.h
@@ -0,0 +1,60 @@
+/* Optimization of multithreaded code.
+
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 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
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2020.  */
+
+#ifndef _THREAD_OPTIM_H
+#define _THREAD_OPTIM_H
+
+/* This file defines a way to optimize multithreaded code for the single-thread
+   case, based on the variable '__libc_single_threaded', defined in
+   glibc >= 2.32.  */
+
+/* Typical use: In a block or function, use
+
+     IF_MT_DECL;
+     ...
+     IF_MT
+       if (pthread_mutex_lock (&lock)) abort ();
+     ...
+     IF_MT
+       if (pthread_mutex_unlock (&lock)) abort ();
+
+   The macro IF_MT_DECL establishes local variables for use by IF_MT.
+
+   IF_MT STATEMENT executes STATEMENT in the multithreaded cases, and skips it
+   in the single-threaded case.
+
+   The code between IF_MT_DECL and IF_MT must not create threads or invoke
+   functions that may indirectly create threads (e.g. 'dlopen' may, indirectly
+   through C++ initializers of global variables in the shared library being
+   opened, create threads).
+
+   The lock here is meant to synchronize threads in the same process.  The
+   same optimization cannot be applied to locks that synchronize different
+   processes (e.g. through shared memory mappings).  */
+
+#if HAVE_SYS_SINGLE_THREADED_H /* glibc >= 2.32 */
+# include <sys/single_threaded.h>
+# define IF_MT_DECL  char optimize_for_single_thread = __libc_single_threaded
+# define IF_MT       if (optimize_for_single_thread)
+#else
+# define IF_MT_DECL  (void *)0
+# define IF_MT
+#endif
+
+#endif /* _THREAD_OPTIM_H */
diff --git a/modules/thread-optim b/modules/thread-optim
new file mode 100644
index 0000000..caf4518
--- /dev/null
+++ b/modules/thread-optim
@@ -0,0 +1,21 @@
+Description:
+Optimization of multithreaded code.
+
+Files:
+lib/thread-optim.h
+
+Depends-on:
+
+configure.ac:
+AC_CHECK_HEADERS([sys/single_threaded.h])
+
+Makefile.am:
+
+Include:
+"thread-optim.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4

>From f9f3407212edb967b97d14f007919e7ee0927135 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 8 Aug 2020 22:05:25 +0200
Subject: [PATCH 2/4] fatal-signal: Use module 'thread-optim'.

* lib/fatal-signal.c: Include thread-optim.h.
(at_fatal_signal, block_fatal_signals, unblock_fatal_signals): Use IF_MT
macro.
* modules/fatal-signal (Depends-on): Add thread-optim.
---
 ChangeLog            |  8 ++++++++
 lib/fatal-signal.c   | 19 +++++++++++++------
 modules/fatal-signal |  1 +
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ee9b6ce..37a7a07 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2020-08-08  Bruno Haible  <[email protected]>
 
+	fatal-signal: Use module 'thread-optim'.
+	* lib/fatal-signal.c: Include thread-optim.h.
+	(at_fatal_signal, block_fatal_signals, unblock_fatal_signals): Use IF_MT
+	macro.
+	* modules/fatal-signal (Depends-on): Add thread-optim.
+
+2020-08-08  Bruno Haible  <[email protected]>
+
 	New module 'thread-optim'.
 	* lib/thread-optim.h: New file.
 	* modules/thread-optim: New file.
diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index 29184e0..541c4cb 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -27,6 +27,7 @@
 #include <unistd.h>
 
 #include "glthread/lock.h"
+#include "thread-optim.h"
 #include "sig-handler.h"
 #include "xalloc.h"
 
@@ -213,7 +214,9 @@ gl_lock_define_initialized (static, at_fatal_signal_lock)
 void
 at_fatal_signal (action_t action)
 {
-  gl_lock_lock (at_fatal_signal_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (at_fatal_signal_lock);
 
   static bool cleanup_initialized = false;
   if (!cleanup_initialized)
@@ -260,7 +263,7 @@ at_fatal_signal (action_t action)
   actions[actions_count].action = action;
   actions_count++;
 
-  gl_lock_unlock (at_fatal_signal_lock);
+  IF_MT gl_lock_unlock (at_fatal_signal_lock);
 }
 
 
@@ -300,7 +303,9 @@ static unsigned int fatal_signals_block_counter = 0;
 void
 block_fatal_signals (void)
 {
-  gl_lock_lock (fatal_signals_block_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (fatal_signals_block_lock);
 
   if (fatal_signals_block_counter++ == 0)
     {
@@ -308,14 +313,16 @@ block_fatal_signals (void)
       sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
     }
 
-  gl_lock_unlock (fatal_signals_block_lock);
+  IF_MT gl_lock_unlock (fatal_signals_block_lock);
 }
 
 /* Stop delaying the catchable fatal signals.  */
 void
 unblock_fatal_signals (void)
 {
-  gl_lock_lock (fatal_signals_block_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (fatal_signals_block_lock);
 
   if (fatal_signals_block_counter == 0)
     /* There are more calls to unblock_fatal_signals() than to
@@ -327,7 +334,7 @@ unblock_fatal_signals (void)
       sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
     }
 
-  gl_lock_unlock (fatal_signals_block_lock);
+  IF_MT gl_lock_unlock (fatal_signals_block_lock);
 }
 
 
diff --git a/modules/fatal-signal b/modules/fatal-signal
index de53de7..7029687 100644
--- a/modules/fatal-signal
+++ b/modules/fatal-signal
@@ -13,6 +13,7 @@ stdbool
 unistd
 sigaction
 lock
+thread-optim
 sigprocmask
 raise
 
-- 
2.7.4

>From a7c4d409435d09428d990c4d4adeea09c4c00912 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 8 Aug 2020 22:09:09 +0200
Subject: [PATCH 3/4] clean-temp: Use module 'thread-optim'.

* lib/clean-temp.c: Include thread-optim.h.
(register_temporary_file, unregister_temporary_file, create_temp_dir,
register_temp_file, unregister_temp_file, register_temp_subdir,
unregister_temp_subdir, cleanup_temp_dir_contents, register_fd,
close_temp, fclose_variant_temp): Use IF_MT macro.
* modules/clean-temp (Depends-on): Add thread-optim.
---
 ChangeLog          |  8 +++++++
 lib/clean-temp.c   | 65 +++++++++++++++++++++++++++++++++++-------------------
 modules/clean-temp |  1 +
 3 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 37a7a07..1ee85d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2020-08-08  Bruno Haible  <[email protected]>
 
+	clean-temp: Use module 'thread-optim'.
+	* lib/clean-temp.c: Include thread-optim.h.
+	(register_temporary_file, unregister_temporary_file, create_temp_dir,
+	register_temp_file, unregister_temp_file, register_temp_subdir,
+	unregister_temp_subdir, cleanup_temp_dir_contents, register_fd,
+	close_temp, fclose_variant_temp): Use IF_MT macro.
+	* modules/clean-temp (Depends-on): Add thread-optim.
+
 	fatal-signal: Use module 'thread-optim'.
 	* lib/fatal-signal.c: Include thread-optim.h.
 	(at_fatal_signal, block_fatal_signals, unblock_fatal_signals): Use IF_MT
diff --git a/lib/clean-temp.c b/lib/clean-temp.c
index 34ebb9b..605390b 100644
--- a/lib/clean-temp.c
+++ b/lib/clean-temp.c
@@ -44,6 +44,7 @@
 #include "xalloc.h"
 #include "xmalloca.h"
 #include "glthread/lock.h"
+#include "thread-optim.h"
 #include "gl_xlist.h"
 #include "gl_linkedhash_list.h"
 #include "gl_linked_list.h"
@@ -406,7 +407,9 @@ init_clean_temp (void)
 void
 register_temporary_file (const char *absolute_file_name)
 {
-  gl_lock_lock (file_cleanup_list_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (file_cleanup_list_lock);
 
   /* Make sure that this facility and the file_cleanup_list are initialized.  */
   if (file_cleanup_list == NULL)
@@ -421,7 +424,7 @@ register_temporary_file (const char *absolute_file_name)
   if (gl_list_search (file_cleanup_list, absolute_file_name) == NULL)
     gl_list_add_first (file_cleanup_list, xstrdup (absolute_file_name));
 
-  gl_lock_unlock (file_cleanup_list_lock);
+  IF_MT gl_lock_unlock (file_cleanup_list_lock);
 }
 
 /* Unregister the given ABSOLUTE_FILE_NAME as being a file that needs to be
@@ -430,7 +433,9 @@ register_temporary_file (const char *absolute_file_name)
 void
 unregister_temporary_file (const char *absolute_file_name)
 {
-  gl_lock_lock (file_cleanup_list_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (file_cleanup_list_lock);
 
   gl_list_t list = file_cleanup_list;
   if (list != NULL)
@@ -445,7 +450,7 @@ unregister_temporary_file (const char *absolute_file_name)
         }
     }
 
-  gl_lock_unlock (file_cleanup_list_lock);
+  IF_MT gl_lock_unlock (file_cleanup_list_lock);
 }
 
 /* Remove a file, with optional error message.
@@ -493,7 +498,9 @@ struct temp_dir *
 create_temp_dir (const char *prefix, const char *parentdir,
                  bool cleanup_verbose)
 {
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   struct tempdir * volatile *tmpdirp = NULL;
   struct tempdir *tmpdir;
@@ -600,12 +607,12 @@ create_temp_dir (const char *prefix, const char *parentdir,
      block because then the cleanup handler would not remove the directory
      if xstrdup fails.  */
   tmpdir->dirname = xstrdup (tmpdirname);
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
   freea (xtemplate);
   return (struct temp_dir *) tmpdir;
 
  quit:
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
   freea (xtemplate);
   return NULL;
 }
@@ -618,14 +625,15 @@ register_temp_file (struct temp_dir *dir,
                     const char *absolute_file_name)
 {
   struct tempdir *tmpdir = (struct tempdir *)dir;
+  IF_MT_DECL;
 
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   /* Add absolute_file_name to tmpdir->files, without duplicates.  */
   if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
     gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
 
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
 }
 
 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
@@ -636,8 +644,9 @@ unregister_temp_file (struct temp_dir *dir,
                       const char *absolute_file_name)
 {
   struct tempdir *tmpdir = (struct tempdir *)dir;
+  IF_MT_DECL;
 
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   gl_list_t list = tmpdir->files;
   gl_list_node_t node;
@@ -651,7 +660,7 @@ unregister_temp_file (struct temp_dir *dir,
       free (old_string);
     }
 
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
 }
 
 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
@@ -662,14 +671,15 @@ register_temp_subdir (struct temp_dir *dir,
                       const char *absolute_dir_name)
 {
   struct tempdir *tmpdir = (struct tempdir *)dir;
+  IF_MT_DECL;
 
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   /* Add absolute_dir_name to tmpdir->subdirs, without duplicates.  */
   if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
     gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
 
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
 }
 
 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
@@ -681,8 +691,9 @@ unregister_temp_subdir (struct temp_dir *dir,
                         const char *absolute_dir_name)
 {
   struct tempdir *tmpdir = (struct tempdir *)dir;
+  IF_MT_DECL;
 
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   gl_list_t list = tmpdir->subdirs;
   gl_list_node_t node;
@@ -696,7 +707,7 @@ unregister_temp_subdir (struct temp_dir *dir,
       free (old_string);
     }
 
-  gl_lock_unlock (dir_cleanup_list_lock);
+  IF_MT gl_lock_unlock (dir_cleanup_list_lock);
 }
 
 /* Remove a directory, with optional error message.
@@ -792,7 +803,9 @@ cleanup_temp_dir_contents (struct temp_dir *dir)
 int
 cleanup_temp_dir (struct temp_dir *dir)
 {
-  gl_lock_lock (dir_cleanup_list_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (dir_cleanup_list_lock);
 
   struct tempdir *tmpdir = (struct tempdir *)dir;
   int err = 0;
@@ -819,7 +832,7 @@ cleanup_temp_dir (struct temp_dir *dir)
         gl_list_free (tmpdir->subdirs);
         free (tmpdir->dirname);
         free (tmpdir);
-        gl_lock_unlock (dir_cleanup_list_lock);
+        IF_MT gl_lock_unlock (dir_cleanup_list_lock);
         return err;
       }
 
@@ -866,7 +879,9 @@ supports_delete_on_close ()
 static void
 register_fd (int fd)
 {
-  gl_lock_lock (descriptors_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (descriptors_lock);
 
   if (descriptors == NULL)
     descriptors = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL,
@@ -880,7 +895,7 @@ register_fd (int fd)
 
   gl_list_add_first (descriptors, element);
 
-  gl_lock_unlock (descriptors_lock);
+  IF_MT gl_lock_unlock (descriptors_lock);
 }
 
 /* Open a temporary file in a temporary directory.
@@ -1026,7 +1041,9 @@ close_temp (int fd)
   int result = 0;
   int saved_errno = 0;
 
-  gl_lock_lock (descriptors_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (descriptors_lock);
 
   gl_list_t list = descriptors;
   if (list == NULL)
@@ -1072,7 +1089,7 @@ close_temp (int fd)
     /* descriptors should already contain fd.  */
     abort ();
 
-  gl_lock_unlock (descriptors_lock);
+  IF_MT gl_lock_unlock (descriptors_lock);
 
   errno = saved_errno;
   return result;
@@ -1088,7 +1105,9 @@ fclose_variant_temp (FILE *fp, int (*fclose_variant) (FILE *))
   int result = 0;
   int saved_errno = 0;
 
-  gl_lock_lock (descriptors_lock);
+  IF_MT_DECL;
+
+  IF_MT gl_lock_lock (descriptors_lock);
 
   gl_list_t list = descriptors;
   if (list == NULL)
@@ -1134,7 +1153,7 @@ fclose_variant_temp (FILE *fp, int (*fclose_variant) (FILE *))
     /* descriptors should have contained fd.  */
     abort ();
 
-  gl_lock_unlock (descriptors_lock);
+  IF_MT gl_lock_unlock (descriptors_lock);
 
   errno = saved_errno;
   return result;
diff --git a/modules/clean-temp b/modules/clean-temp
index 940869d..69157a5 100644
--- a/modules/clean-temp
+++ b/modules/clean-temp
@@ -10,6 +10,7 @@ stdbool
 stdint
 unistd
 lock
+thread-optim
 error
 fatal-signal
 asyncsafe-spin
-- 
2.7.4

>From 50ccda39b28fe3c8bc4de61e36184ddbf0f3e3cd Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 8 Aug 2020 22:11:50 +0200
Subject: [PATCH 4/4] localename: Use module 'thread-optim'.

* lib/localename.c: Include thread-optim.h.
(struniq): Use IF_MT macro.
* modules/localename (Depends-on): Add thread-optim.
---
 ChangeLog          |  5 +++++
 lib/localename.c   | 40 ++++++++++++++++++++++------------------
 modules/localename |  1 +
 3 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1ee85d6..d9a78c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-08-08  Bruno Haible  <[email protected]>
 
+	localename: Use module 'thread-optim'.
+	* lib/localename.c: Include thread-optim.h.
+	(struniq): Use IF_MT macro.
+	* modules/localename (Depends-on): Add thread-optim.
+
 	clean-temp: Use module 'thread-optim'.
 	* lib/clean-temp.c: Include thread-optim.h.
 	(register_temporary_file, unregister_temporary_file, create_temp_dir,
diff --git a/lib/localename.c b/lib/localename.c
index dc60b07..2e76c11 100644
--- a/lib/localename.c
+++ b/lib/localename.c
@@ -35,6 +35,7 @@
 
 #include "flexmember.h"
 #include "setlocale_null.h"
+#include "thread-optim.h"
 
 /* We cannot support uselocale() on platforms where the locale_t type is fake.
    See intl-thread-locale.m4 for details.  */
@@ -2697,24 +2698,27 @@ struniq (const char *string)
     /* Out of memory.  Return a statically allocated string.  */
     return "C";
   memcpy (new_node->contents, string, size);
-  /* Lock while inserting new_node.  */
-  gl_lock_lock (struniq_lock);
-  /* Check whether another thread already added the string while we were
-     waiting on the lock.  */
-  for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
-    if (strcmp (p->contents, string) == 0)
-      {
-        free (new_node);
-        new_node = p;
-        goto done;
-      }
-  /* Really insert new_node into the hash table.  Fill new_node entirely first,
-     because other threads may be iterating over the linked list.  */
-  new_node->next = struniq_hash_table[slot];
-  struniq_hash_table[slot] = new_node;
- done:
-  /* Unlock after new_node is inserted.  */
-  gl_lock_unlock (struniq_lock);
+  {
+    IF_MT_DECL;
+    /* Lock while inserting new_node.  */
+    IF_MT gl_lock_lock (struniq_lock);
+    /* Check whether another thread already added the string while we were
+       waiting on the lock.  */
+    for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
+      if (strcmp (p->contents, string) == 0)
+        {
+          free (new_node);
+          new_node = p;
+          goto done;
+        }
+    /* Really insert new_node into the hash table.  Fill new_node entirely
+       first, because other threads may be iterating over the linked list.  */
+    new_node->next = struniq_hash_table[slot];
+    struniq_hash_table[slot] = new_node;
+   done:
+    /* Unlock after new_node is inserted.  */
+    IF_MT gl_lock_unlock (struniq_lock);
+  }
   return new_node->contents;
 }
 
diff --git a/modules/localename b/modules/localename
index c528acb..28710d0 100644
--- a/modules/localename
+++ b/modules/localename
@@ -19,6 +19,7 @@ strdup
 lock
 langinfo
 setlocale-null
+thread-optim
 
 configure.ac:
 gl_LOCALENAME
-- 
2.7.4

Reply via email to