2023-08-18 Bruno Haible <bruno@clisp.org>
+ thrd: Work around thrd_join bug on AIX 7.3.1.
+ * m4/threads_h.m4 (gl_THREADS_H): Test against AIX 7 thrd_join bug. Set
+ BROKEN_THRD_JOIN.
+ (gl_THREADS_H_DEFAULTS): Initialize BROKEN_THRD_JOIN.
+ * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set REPLACE_THRD_* to 1 also if
+ BROKEN_THRD_JOIN is 1. Define BROKEN_THRD_START_T_OR_JOIN instead of
+ BROKEN_THRD_START_T.
+ * modules/threads-h (Makefile.am): Substitute BROKEN_THRD_JOIN.
+ * lib/threads.in.h (rpl_thrd_t, thrd_t): Define also if BROKEN_THRD_JOIN
+ is 1.
+ * lib/thrd.c: Test BROKEN_THRD_START_T_OR_JOIN instead of
+ BROKEN_THRD_START_T.
+ * doc/posix-functions/thrd_join.texi: Update.
+ * doc/posix-functions/thrd_exit.texi: Likewise.
+
thrd: Refactor.
* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_JOIN_NULL, not
BROKEN_THRD_JOIN. Rename gl_cv_func_thrd_join_works to
glibc 2.27, macOS 11.1, FreeBSD 9.3, NetBSD 8.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@item
The exit code provided to this function is discarded on some platforms:
-AIX 7.2.
+AIX 7.3.1.
@end itemize
Portability problems not fixed by Gnulib:
glibc 2.27, macOS 11.1, FreeBSD 9.3, NetBSD 8.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@item
This function never stores an exit code on some platforms:
-AIX 7.2.
+AIX 7.3.1.
@item
This function crashes when the second argument is NULL on some platforms:
Solaris 11.4.
#if HAVE_THREADS_H
/* Provide workarounds. */
-# if BROKEN_THRD_START_T
+# if BROKEN_THRD_START_T_OR_JOIN
# undef thrd_t
/* AIX 7.1..7.2 defines thrd_start_t incorrectly, namely as
'void * (*) (void *)' instead of 'int (*) (void *)'.
- As a consequence, its thrd_join function never stores an exit code. */
+ As a consequence, its thrd_join function never stores an exit code.
+ AIX 7.3.1 has a corrected thrd_start_t. But the thrd_join function still
+ never stores an exit code. */
/* The Thread-Specific Storage (TSS) key that allows to access each thread's
'struct thrd_with_exitcode *' pointer. */
#if @BROKEN_THRD_START_T@
/* Need to override thrd_start_t, to make thrd_create work. */
# define thrd_start_t rpl_thrd_start_t
+#endif
+#if @BROKEN_THRD_START_T@ || @BROKEN_THRD_JOIN@
/* Need to override thrd_t, to make thrd_join work. */
struct thrd_with_exitcode
{
-# thrd.m4 serial 3
+# thrd.m4 serial 4
dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
if test $ac_cv_header_threads_h = yes; then
- if test $BROKEN_THRD_START_T = 1; then
+ if test $BROKEN_THRD_START_T = 1 || test $BROKEN_THRD_JOIN = 1; then
REPLACE_THRD_CREATE=1
REPLACE_THRD_CURRENT=1
REPLACE_THRD_DETACH=1
REPLACE_THRD_EQUAL=1
REPLACE_THRD_EXIT=1
REPLACE_THRD_JOIN=1
- AC_DEFINE([BROKEN_THRD_START_T], [1],
- [Define if the thrd_start_t type is not as described in ISO C 11.])
+ AC_DEFINE([BROKEN_THRD_START_T_OR_JOIN], [1],
+ [Define if the thrd_start_t type is not as described in ISO C 11 or if thrd_join discards the thread's exit code.])
dnl The thrd_exit replacement relies on pthread_exit, which on AIX is in
dnl libpthread.
LIBSTDTHREAD="$LIBSTDTHREAD $LIBPTHREAD"
-# threads_h.m4 serial 10.1
+# threads_h.m4 serial 10.2
dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
])
if test $gl_cv_thrd_start_t_correct != yes; then
BROKEN_THRD_START_T=1
+ else
+ dnl On AIX 7.3.1, thrd_join still never stores an exit code.
+ AC_CACHE_CHECK([whether thrd_join works],
+ [gl_cv_func_thrd_join_works],
+ [save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBSTDTHREAD"
+ AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stddef.h>
+ #include <threads.h>
+ #define MAGIC 1266074729
+ static int func (void *arg)
+ {
+ return MAGIC;
+ }
+ ]],
+ [[thrd_t thread;
+ if (thrd_create (&thread, func, NULL) != thrd_success)
+ return 1;
+ int ret = 0xDEADBEEF;
+ if (thrd_join (thread, &ret) != thrd_success)
+ return 2;
+ if (ret != MAGIC)
+ return (ret == 0xDEADBEEF ? 3 : 4);
+ return 0;
+ ]])],
+ [gl_cv_func_thrd_join_works=yes],
+ [gl_cv_func_thrd_join_works=no],
+ [case "$host_os" in
+ # Only AIX is known to be broken.
+ aix*) gl_cv_func_thrd_join_works="guessing no" ;;
+ *) gl_cv_func_thrd_join_works="guessing yes" ;;
+ esac
+ ])
+ LIBS="$save_LIBS"
+ ])
+ case "$gl_cv_func_thrd_join_works" in
+ *yes) ;;
+ *) BROKEN_THRD_JOIN=1 ;;
+ esac
fi
fi
[
dnl Assume proper GNU behavior unless another module says otherwise.
HAVE_THREAD_LOCAL=1; AC_SUBST([HAVE_THREAD_LOCAL])
+ BROKEN_THRD_JOIN=0; AC_SUBST([BROKEN_THRD_JOIN])
BROKEN_THRD_START_T=0; AC_SUBST([BROKEN_THRD_START_T])
REPLACE_THRD_CREATE=0; AC_SUBST([REPLACE_THRD_CREATE])
REPLACE_THRD_CURRENT=0; AC_SUBST([REPLACE_THRD_CURRENT])
-e 's/@''GNULIB_THRD''@/$(GNULIB_THRD)/g' \
-e 's/@''GNULIB_TSS''@/$(GNULIB_TSS)/g' \
-e 's|@''HAVE_THREAD_LOCAL''@|$(HAVE_THREAD_LOCAL)|g' \
+ -e 's|@''BROKEN_THRD_JOIN''@|$(BROKEN_THRD_JOIN)|g' \
-e 's|@''BROKEN_THRD_START_T''@|$(BROKEN_THRD_START_T)|g' \
-e 's|@''REPLACE_THRD_CREATE''@|$(REPLACE_THRD_CREATE)|g' \
-e 's|@''REPLACE_THRD_CURRENT''@|$(REPLACE_THRD_CURRENT)|g' \