Commit 6be28624 authored by Bruno Haible's avatar Bruno Haible
Browse files

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

Reported by Arnold Robbins <arnold@skeeve.com>.

* 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.
parent ecb700c1
2019-12-16 Bruno Haible <bruno@clisp.org>
setlocale-null: Remove need for -lpthread on musl libc, *BSD, Haiku.
Reported by Arnold Robbins <arnold@skeeve.com>.
* 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.
2019-12-16 Paul Eggert <eggert@cs.ucla.edu>
 
dfa: make dfasyntax thread-safe
......@@ -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
......
......@@ -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])
])
......
# 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])
])
# 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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment