bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

setlocale-null: remove need for -lpthread on musl libc, *BSD, Haiku


From: Bruno Haible
Subject: setlocale-null: remove need for -lpthread on musl libc, *BSD, Haiku
Date: Mon, 16 Dec 2019 10:42:26 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-166-generic; KDE/5.18.0; x86_64; ; )

This patch removes the need to link with -lpthread on several platforms,
by using the "weak symbols" trick from lock.h. With this, the only platform
on which setlocale-null requires -lpthread is AIX.


2019-12-16  Bruno Haible  <address@hidden>

        setlocale-null: Remove need for -lpthread on musl libc, *BSD, Haiku.
        Reported by Arnold Robbins <address@hidden>.
        * lib/setlocale_null.c (c11_threads_in_use, pthread_in_use): New macros,
        copied from lib/glthread/lock.h.
        (pthread_mutex_lock, pthread_mutex_unlock): Mark as weak.
        (setlocale_null_with_lock): If pthread_in_use() is false, use
        setlocale_null_unlocked directly.
        * m4/threadlib.m4 (gl_WEAK_SYMBOLS): New macro, extracted from
        gl_THREADLIB_BODY. Define HAVE_WEAK_SYMBOLS.
        (gl_THREADLIB_BODY): Invoke gl_WEAK_SYMBOLS.
        * m4/setlocale_null.m4 (gl_FUNC_SETLOCALE_NULL): Invoke gl_WEAK_SYMBOLS.
        Set LIB_SETLOCALE_NULL to empty if weak symbols are supported.
        * m4/duplocale.m4 (gl_FUNC_DUPLOCALE): Add comment.

diff --git a/lib/setlocale_null.c b/lib/setlocale_null.c
index b0506b9..350eca7 100644
--- a/lib/setlocale_null.c
+++ b/lib/setlocale_null.c
@@ -30,12 +30,25 @@
 
 #if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
 # if defined _WIN32 && !defined __CYGWIN__
+
 #  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 #  include <windows.h>
+
 # elif HAVE_PTHREAD_API
+
 #  include <pthread.h>
+#  if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
+#   include <threads.h>
+#   pragma weak thrd_exit
+#   define c11_threads_in_use() (thrd_exit != NULL)
+#  else
+#   define c11_threads_in_use() 0
+#  endif
+
 # elif HAVE_THREADS_H
+
 #  include <threads.h>
+
 # endif
 #endif
 
@@ -100,7 +113,7 @@ setlocale_null_unlocked (int category, char *buf, size_t 
bufsize)
 #endif
 }
 
-#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
+#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, 
macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
 
 /* Use a lock, so that no two threads can invoke setlocale_null_unlocked
    at the same time.  */
@@ -125,7 +138,7 @@ setlocale_null_with_lock (int category, char *buf, size_t 
bufsize)
   return ret;
 }
 
-# elif HAVE_PTHREAD_API
+# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, 
Haiku, Cygwin */
 
 extern
 #  if defined _WIN32 || defined __CYGWIN__
@@ -133,19 +146,40 @@ extern
 #  endif
   pthread_mutex_t *gl_get_setlocale_null_lock (void);
 
+#  if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
+
+    /* Avoid the need to link with '-lpthread'.  */
+#   pragma weak pthread_mutex_lock
+#   pragma weak pthread_mutex_unlock
+
+    /* Determine whether libpthread is in use.  */
+#   pragma weak pthread_mutexattr_gettype
+    /* See the comments in lock.h.  */
+#   define pthread_in_use() \
+      (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
+
+#  else
+#   define pthread_in_use() 1
+#  endif
+
 static int
 setlocale_null_with_lock (int category, char *buf, size_t bufsize)
 {
-  pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
-  int ret;
+  if (pthread_in_use())
+    {
+      pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
+      int ret;
 
-  if (pthread_mutex_lock (lock))
-    abort ();
-  ret = setlocale_null_unlocked (category, buf, bufsize);
-  if (pthread_mutex_unlock (lock))
-    abort ();
+      if (pthread_mutex_lock (lock))
+        abort ();
+      ret = setlocale_null_unlocked (category, buf, bufsize);
+      if (pthread_mutex_unlock (lock))
+        abort ();
 
-  return ret;
+      return ret;
+    }
+  else
+    return setlocale_null_unlocked (category, buf, bufsize);
 }
 
 # elif HAVE_THREADS_H
diff --git a/m4/duplocale.m4 b/m4/duplocale.m4
index 3900b53..a2ac467 100644
--- a/m4/duplocale.m4
+++ b/m4/duplocale.m4
@@ -115,6 +115,8 @@ int main ()
   else
     LIB_DUPLOCALE=
   fi
+  dnl LIB_DUPLOCALE is expected to be '-pthread' or '-lpthread' on AIX
+  dnl with gcc or xlc, and empty otherwise.
   AC_SUBST([LIB_DUPLOCALE])
 ])
 
diff --git a/m4/setlocale_null.m4 b/m4/setlocale_null.m4
index 5c69a3f..eff6e76 100644
--- a/m4/setlocale_null.m4
+++ b/m4/setlocale_null.m4
@@ -1,4 +1,4 @@
-# setlocale_null.m4 serial 1
+# setlocale_null.m4 serial 2
 dnl Copyright (C) 2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -75,10 +75,18 @@ AC_DEFUN([gl_FUNC_SETLOCALE_NULL],
   if test $SETLOCALE_NULL_ALL_MTSAFE = 0 || test $SETLOCALE_NULL_ONE_MTSAFE = 
0; then
     case "$host_os" in
       mingw*) LIB_SETLOCALE_NULL= ;;
-      *)      LIB_SETLOCALE_NULL="$LIBPTHREAD" ;;
+      *)
+        gl_WEAK_SYMBOLS
+        case "$gl_cv_have_weak" in
+          *yes) LIB_SETLOCALE_NULL= ;;
+          *)    LIB_SETLOCALE_NULL="$LIBPTHREAD" ;;
+        esac
+        ;;
     esac
   else
     LIB_SETLOCALE_NULL=
   fi
+  dnl LIB_SETLOCALE_NULL is expected to be '-pthread' or '-lpthread' on AIX
+  dnl with gcc or xlc, and empty otherwise.
   AC_SUBST([LIB_SETLOCALE_NULL])
 ])
diff --git a/m4/threadlib.m4 b/m4/threadlib.m4
index d6e6bf9..96c74c1 100644
--- a/m4/threadlib.m4
+++ b/m4/threadlib.m4
@@ -1,4 +1,4 @@
-# threadlib.m4 serial 23
+# threadlib.m4 serial 24
 dnl Copyright (C) 2005-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -142,6 +142,57 @@ changequote([,])dnl
   fi
 ])
 
+dnl Checks whether the compiler and linker support weak declarations of 
symbols.
+
+AC_DEFUN([gl_WEAK_SYMBOLS],
+[
+  AC_CACHE_CHECK([whether imported symbols can be declared weak],
+    [gl_cv_have_weak],
+    [gl_cv_have_weak=no
+     dnl First, test whether the compiler accepts it syntactically.
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[extern void xyzzy ();
+#pragma weak xyzzy]],
+          [[xyzzy();]])],
+       [gl_cv_have_weak=maybe])
+     if test $gl_cv_have_weak = maybe; then
+       dnl Second, test whether it actually works. On Cygwin 1.7.2, with
+       dnl gcc 4.3, symbols declared weak always evaluate to the address 0.
+       AC_RUN_IFELSE(
+         [AC_LANG_SOURCE([[
+#include <stdio.h>
+#pragma weak fputs
+int main ()
+{
+  return (fputs == NULL);
+}]])],
+         [gl_cv_have_weak=yes],
+         [gl_cv_have_weak=no],
+         [dnl When cross-compiling, assume that only ELF platforms support
+          dnl weak symbols.
+          AC_EGREP_CPP([Extensible Linking Format],
+            [#ifdef __ELF__
+             Extensible Linking Format
+             #endif
+            ],
+            [gl_cv_have_weak="guessing yes"],
+            [gl_cv_have_weak="guessing no"])
+         ])
+     fi
+     dnl But when linking statically, weak symbols don't work.
+     case " $LDFLAGS " in
+       *" -static "*) gl_cv_have_weak=no ;;
+     esac
+    ])
+  case "$gl_cv_have_weak" in
+    *yes)
+      AC_DEFINE([HAVE_WEAK_SYMBOLS], [1],
+        [Define to 1 if the compiler and linker support weak declarations of 
symbols.])
+      ;;
+  esac
+])
+
 dnl The guts of gl_PTHREADLIB. Needs to be expanded only once.
 
 AC_DEFUN([gl_PTHREADLIB_BODY],
@@ -242,45 +293,7 @@ AC_DEFUN([gl_THREADLIB_BODY],
   LTLIBMULTITHREAD=
   if test "$gl_use_threads" != no; then
     dnl Check whether the compiler and linker support weak declarations.
-    AC_CACHE_CHECK([whether imported symbols can be declared weak],
-      [gl_cv_have_weak],
-      [gl_cv_have_weak=no
-       dnl First, test whether the compiler accepts it syntactically.
-       AC_LINK_IFELSE(
-         [AC_LANG_PROGRAM(
-            [[extern void xyzzy ();
-#pragma weak xyzzy]],
-            [[xyzzy();]])],
-         [gl_cv_have_weak=maybe])
-       if test $gl_cv_have_weak = maybe; then
-         dnl Second, test whether it actually works. On Cygwin 1.7.2, with
-         dnl gcc 4.3, symbols declared weak always evaluate to the address 0.
-         AC_RUN_IFELSE(
-           [AC_LANG_SOURCE([[
-#include <stdio.h>
-#pragma weak fputs
-int main ()
-{
-  return (fputs == NULL);
-}]])],
-           [gl_cv_have_weak=yes],
-           [gl_cv_have_weak=no],
-           [dnl When cross-compiling, assume that only ELF platforms support
-            dnl weak symbols.
-            AC_EGREP_CPP([Extensible Linking Format],
-              [#ifdef __ELF__
-               Extensible Linking Format
-               #endif
-              ],
-              [gl_cv_have_weak="guessing yes"],
-              [gl_cv_have_weak="guessing no"])
-           ])
-       fi
-       dnl But when linking statically, weak symbols don't work.
-       case " $LDFLAGS " in
-         *" -static "*) gl_cv_have_weak=no ;;
-       esac
-      ])
+    gl_WEAK_SYMBOLS
     if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
       dnl If we use weak symbols to implement pthread_in_use / pth_in_use /
       dnl thread_in_use, we also need to test whether the ISO C 11 thrd_create




reply via email to

[Prev in Thread] Current Thread [Next in Thread]