summaryrefslogtreecommitdiff
path: root/make/autoconf/otp.m4
diff options
context:
space:
mode:
Diffstat (limited to 'make/autoconf/otp.m4')
-rw-r--r--make/autoconf/otp.m43310
1 files changed, 3310 insertions, 0 deletions
diff --git a/make/autoconf/otp.m4 b/make/autoconf/otp.m4
new file mode 100644
index 0000000000..98b8ea5f61
--- /dev/null
+++ b/make/autoconf/otp.m4
@@ -0,0 +1,3310 @@
+dnl -*-Autoconf-*-
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 1998-2023. All Rights Reserved.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+dnl
+dnl otp.m4
+dnl
+dnl Local macros that can be used in `configure.ac` files in OTP. To use
+dnl any of the macros your `configure.ac` file should include this file
+dnl using `m4_include([otp.m4])` after AC_INIT.
+dnl
+dnl The Local Macros which could be part of autoconf are prefixed LM_,
+dnl macros specific dnl to the Erlang system are prefixed ERL_ (this is
+dnl not always consistently made...).
+dnl
+
+AC_DEFUN([ERL_CANONICAL_SYSTEM_TYPE],
+[
+ AC_CANONICAL_HOST
+ # Adjust for local legacy windows hack...
+ AS_CASE([$host],
+ [local-*-windows],
+ [
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ])
+
+ AC_CANONICAL_BUILD
+ # Adjust for local legacy windows hack...
+ AS_CASE([$build],
+ [local-*-windows],
+ [
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ])
+
+ AC_CANONICAL_TARGET
+ # Adjust for local legacy windows hack...
+ AS_CASE([$target],
+ [local-*-windows],
+ [
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ])
+
+ AS_IF([test "$cross_compiling" = "yes" -a "$build" = "$host"],
+ [AC_MSG_ERROR([
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ ])])
+])
+
+AC_DEFUN(LM_PRECIOUS_VARS,
+[
+
+dnl ERL_TOP
+AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
+
+dnl Tools
+AC_ARG_VAR(CC, [C compiler])
+AC_ARG_VAR(CFLAGS, [C compiler flags])
+AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
+AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
+AC_ARG_VAR(CPP, [C/C++ preprocessor])
+AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
+AC_ARG_VAR(CXX, [C++ compiler])
+AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
+AC_ARG_VAR(LD, [linker (is often overridden by configure)])
+AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overridden by configure)])
+AC_ARG_VAR(LIBS, [libraries])
+AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
+AC_ARG_VAR(RANLIB, [ranlib])
+AC_ARG_VAR(AR, [ar])
+AC_ARG_VAR(GETCONF, [getconf])
+
+dnl Cross system root
+AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
+
+dnl Cross compilation variables
+AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+
+])
+
+AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
+[
+erl_xcomp_without_sysroot=no
+if test "$cross_compiling" = "yes"; then
+ test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
+ test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
+else
+ erl_xcomp_sysroot=
+ erl_xcomp_isysroot=
+fi
+])
+
+AC_DEFUN(LM_CHECK_GETCONF,
+[
+AS_IF(
+ [test "$cross_compiling" != "yes"],
+ [
+ AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
+ ],
+ [
+ dnl First check if we got a `<HOST>-getconf' in $PATH
+ host_getconf="$host_alias-getconf"
+ AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
+ AS_IF(
+ [test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""],
+ [
+ dnl We should perhaps give up if we haven't found it by now, but at
+ dnl least in one Tilera MDE `getconf' under sysroot is a bourne
+ dnl shell script which we can use. We try to find `<HOST>-getconf'
+ dnl or `getconf' under sysconf, but only under sysconf since
+ dnl `getconf' in $PATH is almost guaranteed to be for the build
+ dnl machine.
+ GETCONF=
+ prfx="$erl_xcomp_sysroot"
+ AC_PATH_TOOL([GETCONF], [getconf], [false],
+ ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
+ ])
+ ])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine the windows build environment, i.e.
+dnl MIXED_VC or MIXED_MINGW
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+
+if test "X$windows_environment_" != "Xchecked"; then
+windows_environment_=checked
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+MIXED_VSL=no
+
+dnl MIXED_VC is Microsoft Visual C++ used as standard compiler
+MIXED_VC=no
+dnl MIXED_MINGW is mingw(32|64) used as standard compiler
+MIXED_MINGW=no
+
+AC_MSG_CHECKING(for mixed mingw-gcc and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/msys-?.0.dll; then
+ CFLAGS="$CFLAGS -O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
+ elif test -x /usr/bin/cygpath; then
+ CFLAGS="$CFLAGS -O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
+ elif test -x /bin/wslpath; then
+ CFLAGS="$CFLAGS -O2"
+ MIXED_WSL=yes
+ AC_MSG_RESULT([WSL and VC])
+ MIXED_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not within any known env, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="$CFLAGS -O2"
+ AC_MSG_RESULT([yes])
+ MIXED_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+else
+ AC_MSG_CHECKING(for mixed MSYS and native MinGW environment)
+ if test "x$GCC" = x"yes"; then
+ if test -x /usr/bin/msys-=.0.dll; then
+ CFLAGS="$CFLAGS -O2"
+ AC_MSG_RESULT([yes])
+ MIXED_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with msys, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+fi
+AC_SUBST(MIXED_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_MSG_CHECKING(if we mix WSL with another native compiler)
+if test "X$MIXED_WSL" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_FIND_EMU_CC
+dnl
+dnl
+dnl Tries fairly hard to find a C compiler that can handle jump tables.
+dnl Defines the @EMU_CC@ variable for the makefiles and
+dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
+dnl
+
+AC_DEFUN(LM_FIND_EMU_CC,
+ [AC_CACHE_CHECK(for a compiler that handles jumptables,
+ ac_cv_prog_emu_cc,
+ [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ extern int magic(void);
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+lbl1:
+ return 1;
+lbl2:
+ return 2;
+]])],[ac_cv_prog_emu_cc="$CC"],[ac_cv_prog_emu_cc=no])
+
+if test "$ac_cv_prog_emu_cc" = no; then
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_progname"; then
+ ac_cv_prog_emu_cc="$ac_dir/$ac_progname"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ if test "$ac_cv_prog_emu_cc" != no; then
+ break
+ fi
+ done
+fi
+
+AS_IF([test "$ac_cv_prog_emu_cc" != no],
+ [
+ save_CC="$CC"
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ CC="$ac_cv_prog_emu_cc"
+ CFLAGS=""
+ CPPFLAGS=""
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ extern int magic(void);
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+ lbl1:
+ return 1;
+ lbl2:
+ return 2;
+ ]])],[ac_cv_prog_emu_cc="$CC"],[ac_cv_prog_emu_cc=no])
+ CC=$save_CC
+ CFLAGS=$save_CFLAGS
+ CPPFLAGS=$save_CPPFLAGS
+ ])
+])
+if test "$ac_cv_prog_emu_cc" = no; then
+ AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
+ EMU_CC="$CC"
+else
+ EMU_CC="$ac_cv_prog_emu_cc"
+fi
+AC_SUBST(EMU_CC)
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl Figure out how to create directories with parents.
+dnl (In my opinion INSTALL_DIR is a bad name, MKSUBDIRS or something is better)
+dnl
+dnl We prefer 'install -d', but use 'mkdir -p' if it exists.
+dnl If none of these methods works, we give up.
+dnl
+
+
+AC_DEFUN(LM_PROG_INSTALL_DIR,
+[AC_CACHE_CHECK(how to create a directory including parents,
+ac_cv_prog_mkdir_p,
+[
+temp_name_base=config.$$
+temp_name=$temp_name_base/x/y/z
+$INSTALL -d $temp_name >/dev/null 2>&1
+ac_cv_prog_mkdir_p=none
+if test -d $temp_name; then
+ ac_cv_prog_mkdir_p="$INSTALL -d"
+else
+ mkdir -p $temp_name >/dev/null 2>&1
+ if test -d $temp_name; then
+ ac_cv_prog_mkdir_p="mkdir -p"
+ fi
+fi
+rm -fr $temp_name_base
+])
+
+case "${ac_cv_prog_mkdir_p}" in
+ none) AC_MSG_ERROR(don't know how create directories with parents) ;;
+ *) INSTALL_DIR="$ac_cv_prog_mkdir_p" AC_SUBST(INSTALL_DIR) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_PERL5
+dnl
+dnl Try to find perl version 5. If found set PERL to the absolute path
+dnl of the program, if not found set PERL to false.
+dnl
+AC_DEFUN(LM_PROG_PERL5,
+[AC_PATH_PROGS(PERL, perl5 perl, false,
+ /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
+if test "$PERL" = "false"; then
+ ac_cv_path_PERL=false
+ PERL=false
+dnl AC_MSG_WARN(perl version 5 not found)
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SO_BSDCOMPAT
+dnl
+dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
+dnl
+AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
+[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[int i = SO_BSDCOMPAT;]])],[ac_cv_decl_so_bsdcompat=yes],[ac_cv_decl_so_bsdcompat=no]))
+
+case "${ac_cv_decl_so_bsdcompat}" in
+ "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
+ [Define if you have SO_BSDCOMPAT flag on sockets]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_INADDR_LOOPBACK
+dnl
+dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
+dnl
+
+AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
+[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
+ ac_cv_decl_inaddr_loopback,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <netinet/in.h>]], [[int i = INADDR_LOOPBACK;]])],[ac_cv_decl_inaddr_loopback=yes],[ac_cv_decl_inaddr_loopback=no])
+])
+
+AS_IF(
+ [test ${ac_cv_decl_inaddr_loopback} = no],
+ [
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
+ ac_cv_decl_inaddr_loopback_rpc,
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <rpc/types.h>]], [[int i = INADDR_LOOPBACK;]])],[ac_cv_decl_inaddr_loopback_rpc=yes],[ac_cv_decl_inaddr_loopback_rpc=no]))
+
+ AS_IF(
+ [test "${ac_cv_decl_inaddr_loopback_rpc}" = "yes"],
+ [
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
+ [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined])
+ ],
+ [
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
+ ac_cv_decl_inaddr_loopback_winsock2,
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>]], [[int i = INADDR_LOOPBACK;]])],[ac_cv_decl_inaddr_loopback_winsock2=yes],[ac_cv_decl_inaddr_loopback_winsock2=no]))
+ case "${ac_cv_decl_inaddr_loopback_winsock2}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
+ [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ # couldn't find it anywhere
+ AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
+ [Define if you don't have a definition of INADDR_LOOPBACK]) ;;
+ esac
+ ])
+ ])
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_SOCKADDR_SA_LEN
+dnl
+dnl Check if the sockaddr structure has the field sa_len
+dnl
+
+AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
+[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
+ ac_cv_struct_sockaddr_sa_len,
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <sys/socket.h>]], [[struct sockaddr s; s.sa_len = 10;]])],[ac_cv_struct_sockaddr_sa_len=yes],[ac_cv_struct_sockaddr_sa_len=no]))
+
+dnl FIXME convbreak
+case ${ac_cv_struct_sockaddr_sa_len} in
+ "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
+ *) ;;
+esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_IPV6
+dnl
+dnl Check for ipv6 support and what the in6_addr structure is called.
+dnl (early linux used in_addr6 instead of in6_addr)
+dnl
+
+AC_DEFUN(LM_SYS_IPV6,
+[AC_MSG_CHECKING(for IP version 6 support)
+AC_CACHE_VAL(ac_cv_sys_ipv6_support,
+[ok_so_far=yes
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif]], [[struct in6_addr a6; struct sockaddr_in6 s6;]])],[ok_so_far=yes],[ok_so_far=no])
+
+AS_IF(
+ [test $ok_so_far = yes],
+ [
+ ac_cv_sys_ipv6_support=yes
+ ],
+ [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif]], [[struct in_addr6 a6; struct sockaddr_in6 s6;]])],[ac_cv_sys_ipv6_support=in_addr6],[ac_cv_sys_ipv6_support=no])
+ ])
+])dnl
+
+dnl
+dnl Have to use old style AC_DEFINE due to BC with old autoconf.
+dnl
+
+case ${ac_cv_sys_ipv6_support} in
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ ;;
+ in_addr6)
+ AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_MULTICAST
+dnl
+dnl Check for multicast support. Only checks for multicast options in
+dnl setsockopt(), no check is performed that multicasting actually works.
+dnl If options are found defines HAVE_MULTICAST_SUPPORT
+dnl
+
+AC_DEFUN(LM_SYS_MULTICAST,
+[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
+[
+AC_EGREP_CPP(^yes$,
+[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
+yes
+#endif
+], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
+if test $ac_cv_sys_multicast_support = yes; then
+ AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
+ [Define if setsockopt() accepts multicast options])
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SYS_ERRLIST
+dnl
+dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
+dnl in a system header file, stdio.h or errno.h.
+dnl
+
+AC_DEFUN(LM_DECL_SYS_ERRLIST,
+[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
+ ac_cv_decl_sys_errlist,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
+#include <errno.h>]], [[char *msg = *(sys_errlist + 1);]])],[ac_cv_decl_sys_errlist=yes],[ac_cv_decl_sys_errlist=no])])
+if test $ac_cv_decl_sys_errlist = yes; then
+ AC_DEFINE(SYS_ERRLIST_DECLARED,[],
+ [define if the variable sys_errlist is declared in a system header file])
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
+dnl [, action-if-found [, action-if-not-found]]] )
+dnl
+dnl Checks if the declaration "declaration" of "funname" conflicts
+dnl with the header files idea of how the function should be
+dnl declared. It is useful on systems which lack prototypes and you
+dnl need to provide your own (e.g. when you want to take the address
+dnl of a function). The 4'th argument is expanded if conflicting,
+dnl the 5'th argument otherwise
+dnl
+dnl
+
+AC_DEFUN(LM_CHECK_FUNC_DECL,
+[AC_MSG_CHECKING([for conflicting declaration of $1])
+AC_CACHE_VAL(ac_cv_func_decl_$1,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
+$3]], [[$2
+char *c = (char *)$1;
+]])],[eval "ac_cv_func_decl_$1=no"],[eval "ac_cv_func_decl_$1=yes"])])
+if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$4], , :, [$4])
+else
+ AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])dnl # AC_C_DOUBLE_MIDDLE_ENDIAN
+
+
+AC_DEFUN(ERL_MONOTONIC_CLOCK,
+[
+ # CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
+ # and Monterey, since it may step backwards.
+ if test "$3" = "yes"; then
+ case $host_os in
+ darwin*)
+ default_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_RAW"
+ low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_RAW_APPROX"
+ high_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_RAW";;
+ *)
+ default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_BOOTTIME CLOCK_MONOTONIC"
+ low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST"
+ high_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_PRECISE";;
+ esac
+ else
+ case $host_os in
+ darwin*)
+ default_resolution_clock_gettime_monotonic="CLOCK_UPTIME_RAW"
+ low_resolution_clock_gettime_monotonic="CLOCK_UPTIME_RAW_APPROX"
+ high_resolution_clock_gettime_monotonic="CLOCK_UPTIME_RAW";;
+ *)
+ default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_UPTIME CLOCK_MONOTONIC"
+ low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_UPTIME_FAST"
+ high_resolution_clock_gettime_monotonic="CLOCK_UPTIME_PRECISE";;
+ esac
+ fi
+
+ case "$1" in
+ high_resolution)
+ check_msg="high resolution "
+ prefer_resolution_clock_gettime_monotonic="$high_resolution_clock_gettime_monotonic"
+ ;;
+ low_resolution)
+ check_msg="low resolution "
+ prefer_resolution_clock_gettime_monotonic="$low_resolution_clock_gettime_monotonic"
+ ;;
+ custom_resolution)
+ check_msg="custom resolution "
+ prefer_resolution_clock_gettime_monotonic="$2"
+ ;;
+ *)
+ check_msg="custom "
+ prefer_resolution_clock_gettime_monotonic="$2"
+ ;;
+ esac
+
+ clock_gettime_lib=""
+ AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"])
+
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $clock_gettime_lib"
+
+ if test "$LD_MAY_BE_WEAK" != "no"; then
+ trust_test="#error May not be there due to weak linking"
+ else
+ trust_test=""
+ fi
+
+ AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC_RAW, _)], erl_cv_clock_gettime_monotonic_raw,
+ [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <time.h>
+$trust_test
+ ]], [[
+ struct timespec ts;
+ long long result;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ ]])],[erl_cv_clock_gettime_monotonic_raw=yes],[erl_cv_clock_gettime_monotonic_raw=no])
+ ])
+
+ AC_CACHE_CHECK([for clock_gettime() with ${check_msg}monotonic clock type], erl_cv_clock_gettime_monotonic_$1,
+ [
+ for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <time.h>
+$trust_test
+ ]], [[
+ struct timespec ts;
+ long long result;
+ clock_gettime($clock_type,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ ]])],[erl_cv_clock_gettime_monotonic_$1=$clock_type],[erl_cv_clock_gettime_monotonic_$1=no])
+ test $erl_cv_clock_gettime_monotonic_$1 = no || break
+ done
+ ])
+
+ LIBS="$save_LIBS"
+
+ AS_IF(
+ [test "$LD_MAY_BE_WEAK" != "no"],
+ [
+ AC_CHECK_FUNCS([clock_get_attributes gethrtime])
+ ],
+ [
+ AC_CHECK_FUNCS([clock_getres clock_get_attributes gethrtime])
+ ])
+
+ AC_CACHE_CHECK([for mach clock_get_time() with monotonic clock type], erl_cv_mach_clock_get_time_monotonic,
+ [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <mach/clock.h>
+#include <mach/mach.h>
+ ]], [[
+ kern_return_t res;
+ clock_serv_t clk_srv;
+ mach_timespec_t time_spec;
+
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clk_srv);
+ res = clock_get_time(clk_srv, &time_spec);
+ mach_port_deallocate(mach_task_self(), clk_srv);
+ ]])],[erl_cv_mach_clock_get_time_monotonic=yes],[erl_cv_mach_clock_get_time_monotonic=no])
+ ])
+
+ erl_corrected_monotonic_clock=no
+ case $erl_cv_clock_gettime_monotonic_$1-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
+ *-*-*-win32)
+ erl_monotonic_clock_func=WindowsAPI
+ ;;
+ CLOCK_*-*-*-linux*)
+ case $erl_cv_clock_gettime_monotonic_$1-$erl_cv_clock_gettime_monotonic_raw in
+ CLOCK_BOOTTIME-yes|CLOCK_MONOTONIC-yes)
+ erl_corrected_monotonic_clock=yes
+ ;;
+ *)
+ # We don't trust CLOCK_MONOTONIC to be NTP
+ # adjusted on linux systems that do not have
+ # CLOCK_MONOTONIC_RAW (although it seems to
+ # be...)
+ ;;
+ esac
+ erl_monotonic_clock_func=clock_gettime
+ ;;
+ no-no-no-linux*)
+ erl_monotonic_clock_func=times
+ ;;
+ CLOCK_*-*-*-*)
+ erl_monotonic_clock_func=clock_gettime
+ ;;
+ no-yes-*-*)
+ erl_monotonic_clock_func=gethrtime
+ ;;
+ no-no-yes-*)
+ erl_monotonic_clock_func=mach_clock_get_time
+ ;;
+ no-no-no-*)
+ erl_monotonic_clock_func=none
+ ;;
+ esac
+
+ erl_monotonic_clock_low_resolution=no
+ erl_monotonic_clock_lib=
+ erl_monotonic_clock_id=
+ case $erl_monotonic_clock_func in
+ clock_gettime)
+ erl_monotonic_clock_id=$erl_cv_clock_gettime_monotonic_$1
+ for low_res_id in $low_resolution_clock_gettime_monotonic; do
+ if test $erl_monotonic_clock_id = $low_res_id; then
+ erl_monotonic_clock_low_resolution=yes
+ break
+ fi
+ done
+ erl_monotonic_clock_lib=$clock_gettime_lib
+ ;;
+ mach_clock_get_time)
+ erl_monotonic_clock_id=SYSTEM_CLOCK
+ ;;
+ times)
+ erl_monotonic_clock_low_resolution=yes
+ ;;
+ *)
+ ;;
+ esac
+
+])
+
+AC_DEFUN(ERL_WALL_CLOCK,
+[
+ default_resolution_clock_gettime_wall="CLOCK_REALTIME"
+ low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
+ high_resolution_clock_gettime_wall="CLOCK_REALTIME_PRECISE"
+
+ case "$1" in
+ high_resolution)
+ check_msg="high resolution "
+ prefer_resolution_clock_gettime_wall="$high_resolution_clock_gettime_wall"
+ ;;
+ low_resolution)
+ check_msg="low resolution "
+ prefer_resolution_clock_gettime_wall="$low_resolution_clock_gettime_wall"
+ ;;
+ custom_resolution)
+ check_msg="custom resolution "
+ prefer_resolution_clock_gettime_wall="$2"
+ ;;
+ *)
+ check_msg=""
+ prefer_resolution_clock_gettime_wall=
+ ;;
+ esac
+
+ clock_gettime_lib=""
+ AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"])
+
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $clock_gettime_lib"
+
+ if test "$LD_MAY_BE_WEAK" != "no"; then
+ trust_test="#error May not be there due to weak linking"
+ else
+ trust_test=""
+ fi
+
+ AC_CACHE_CHECK([for clock_gettime() with ${check_msg}wall clock type], erl_cv_clock_gettime_wall_$1,
+ [
+ for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <time.h>
+$trust_test
+ ]], [[
+ struct timespec ts;
+ long long result;
+ clock_gettime($clock_type,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ ]])],[erl_cv_clock_gettime_wall_$1=$clock_type],[erl_cv_clock_gettime_wall_$1=no])
+ test $erl_cv_clock_gettime_wall_$1 = no || break
+ done
+ ])
+
+ LIBS="$save_LIBS"
+
+ AS_IF([test "$LD_MAY_BE_WEAK" = "no"],
+ [
+ AC_CHECK_FUNCS([clock_getres])
+ ])
+
+ AC_CHECK_FUNCS([clock_get_attributes gettimeofday])
+
+ AC_CACHE_CHECK([for mach clock_get_time() with wall clock type], erl_cv_mach_clock_get_time_wall,
+ [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <mach/clock.h>
+#include <mach/mach.h>
+ ]], [[
+ kern_return_t res;
+ clock_serv_t clk_srv;
+ mach_timespec_t time_spec;
+
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk_srv);
+ res = clock_get_time(clk_srv, &time_spec);
+ mach_port_deallocate(mach_task_self(), clk_srv);
+ ]])],[erl_cv_mach_clock_get_time_wall=yes],[erl_cv_mach_clock_get_time_wall=no])
+ ])
+
+ erl_wall_clock_lib=
+ erl_wall_clock_low_resolution=no
+ erl_wall_clock_id=
+ case $1-$erl_cv_clock_gettime_wall_$1-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in
+ *-*-*-*-win32)
+ erl_wall_clock_func=WindowsAPI
+ erl_wall_clock_low_resolution=yes
+ ;;
+ high_resolution-no-yes-*-*)
+ erl_wall_clock_func=mach_clock_get_time
+ erl_wall_clock_id=CALENDAR_CLOCK
+ ;;
+ *-CLOCK_*-*-*-*)
+ erl_wall_clock_func=clock_gettime
+ erl_wall_clock_lib=$clock_gettime_lib
+ erl_wall_clock_id=$erl_cv_clock_gettime_wall_$1
+ for low_res_id in $low_resolution_clock_gettime_wall; do
+ if test $erl_wall_clock_id = $low_res_id; then
+ erl_wall_clock_low_resolution=yes
+ break
+ fi
+ done
+ ;;
+ *-no-*-yes-*)
+ erl_wall_clock_func=gettimeofday
+ ;;
+ *)
+ erl_wall_clock_func=none
+ ;;
+ esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_THR_LIB
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
+dnl checks for some pthread headers which will appear in DEFS or config.h.
+dnl
+
+AC_DEFUN(LM_CHECK_THR_LIB,
+[
+
+NEED_NPTL_PTHREAD_H=no
+
+dnl win32?
+AC_MSG_CHECKING([for native win32 threads])
+AS_IF(
+ [test "X$host_os" = "Xwin32"],
+ [
+ AC_MSG_RESULT(yes)
+ THR_DEFS="-DWIN32_THREADS"
+ THR_LIBS=
+ THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
+ ],
+ [
+ AC_MSG_RESULT(no)
+ THR_DEFS=
+ THR_LIBS=
+ THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
+
+dnl Try to find POSIX threads
+
+dnl The usual pthread lib...
+ AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
+
+dnl Very old versions of FreeBSD have pthreads in special c library, c_r...
+ AS_IF([test "x$THR_LIBS" = "x"],
+ [
+ AC_CHECK_LIB([c_r], [pthread_create], [THR_LIBS="-lc_r"])
+ ])
+
+dnl QNX has pthreads in standard C library
+ AS_IF([test "x$THR_LIBS" = "x"],
+ [
+ AC_CHECK_FUNC([pthread_create], [THR_LIBS="none_needed"])
+ ])
+
+dnl On ofs1 the '-pthread' switch should be used
+ AS_IF(
+ [test "x$THR_LIBS" = "x"],
+ [
+ AC_MSG_CHECKING([if the '-pthread' switch can be used])
+ saved_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -pthread"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_create((void*)0,(void*)0,(void*)0,(void*)0);]])],[THR_DEFS="-pthread"
+ THR_LIBS="-pthread"],[])
+ CFLAGS=$saved_cflags
+ if test "x$THR_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ])
+
+ AS_IF(
+ [test "x$THR_LIBS" != "x"],
+ [
+ THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
+ THR_LIB_NAME=pthread
+ if test "x$THR_LIBS" = "xnone_needed"; then
+ THR_LIBS=
+ fi
+ AS_CASE(
+ [$host_os],
+ [solaris*],
+ [
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ],
+ [linux*],
+ [
+ THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
+
+ LM_CHECK_GETCONF
+ AC_MSG_CHECKING(for Native POSIX Thread Library)
+ libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
+ if test $? -eq 0; then
+ case "$libpthr_vsn" in
+ *nptl*|*NPTL*) nptl=yes;;
+ *) nptl=no;;
+ esac
+ elif test "$cross_compiling" = "yes"; then
+ case "$erl_xcomp_linux_nptl" in
+ "") nptl=cross;;
+ yes|no) nptl=$erl_xcomp_linux_nptl;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
+ esac
+ else
+ nptl=no
+ fi
+ AC_MSG_RESULT($nptl)
+ if test $nptl = cross; then
+ nptl=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ AS_IF(
+ [test $nptl = yes],
+ [
+ THR_LIB_TYPE=posix_nptl
+ need_nptl_incldir=no
+ AC_CHECK_HEADER([nptl/pthread.h],
+ [need_nptl_incldir=yes
+ NEED_NPTL_PTHREAD_H=yes])
+ AS_IF(
+ [test $need_nptl_incldir = yes],
+ [
+ # Ahh...
+ nptl_path="$C_INCLUDE_PATH:$CPATH"
+ if test X$cross_compiling != Xyes; then
+ nptl_path="$nptl_path:/usr/local/include:/usr/include"
+ else
+ IROOT="$erl_xcomp_isysroot"
+ test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
+ test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
+ nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
+ fi
+ nptl_ws_path=
+ save_ifs="$IFS"; IFS=":"
+ for dir in $nptl_path; do
+ if test "x$dir" != "x"; then
+ nptl_ws_path="$nptl_ws_path $dir"
+ fi
+ done
+ IFS=$save_ifs
+ nptl_incldir=
+ for dir in $nptl_ws_path; do
+ AC_CHECK_HEADER([$dir/nptl/pthread.h],
+ [nptl_incldir=$dir/nptl])
+ if test "x$nptl_incldir" != "x"; then
+ THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
+ break
+ fi
+ done
+ if test "x$nptl_incldir" = "x"; then
+ AC_MSG_ERROR(Failed to locate nptl system include directory)
+ fi
+ ])
+ ])
+ ])
+
+ dnl We sometimes need THR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $THR_DEFS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h,
+ AC_DEFINE(HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ])
+ ])
+
+])
+
+AC_DEFUN(ERL_INTERNAL_LIBS,
+[
+
+ERTS_INTERNAL_X_LIBS=
+
+AC_CHECK_LIB(kstat, kstat_open,
+[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
+ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
+
+AC_SUBST(ERTS_INTERNAL_X_LIBS)
+
+])
+
+AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OP__,
+[
+ # $1 - atomic_op
+
+ for atomic_bit_size in 32 64 128; do
+ case $atomic_bit_size in
+ 32) gcc_atomic_type="$gcc_atomic_type32";;
+ 64) gcc_atomic_type="$gcc_atomic_type64";;
+ 128) gcc_atomic_type="$gcc_atomic_type128";;
+ esac
+ gcc_atomic_lockfree="int x[[(2*__atomic_always_lock_free(sizeof($gcc_atomic_type), 0))-1]]"
+ case $1 in
+ __sync_add_and_fetch | __sync_fetch_and_and | __sync_fetch_and_or)
+ atomic_call="volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, ($gcc_atomic_type) 0);"
+ ;;
+ __sync_val_compare_and_swap)
+ atomic_call="volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, ($gcc_atomic_type) 0, ($gcc_atomic_type) 0);"
+ ;;
+ __atomic_store_n)
+ atomic_call="$gcc_atomic_lockfree; volatile $gcc_atomic_type var; $1(&var, ($gcc_atomic_type) 0, __ATOMIC_RELAXED); $1(&var, ($gcc_atomic_type) 0, __ATOMIC_RELEASE);"
+ ;;
+ __atomic_load_n)
+ atomic_call="$gcc_atomic_lockfree; volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, __ATOMIC_RELAXED); res = $1(&var, __ATOMIC_ACQUIRE);"
+ ;;
+ __atomic_add_fetch| __atomic_fetch_and | __atomic_fetch_or)
+ atomic_call="$gcc_atomic_lockfree; volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, ($gcc_atomic_type) 0, __ATOMIC_RELAXED); res = $1(&var, ($gcc_atomic_type) 0, __ATOMIC_ACQUIRE); res = $1(&var, ($gcc_atomic_type) 0, __ATOMIC_RELEASE);"
+ ;;
+ __atomic_compare_exchange_n)
+ atomic_call="$gcc_atomic_lockfree; volatile $gcc_atomic_type var; $gcc_atomic_type val; int res = $1(&var, &val, ($gcc_atomic_type) 0, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); res = $1(&var, &val, ($gcc_atomic_type) 0, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);"
+ ;;
+ *)
+ AC_MSG_ERROR([Internal error: missing implementation for $1])
+ ;;
+ esac
+ eval atomic${atomic_bit_size}_call=\"$atomic_call\"
+ done
+
+ AC_CACHE_CHECK([for 32-bit $1()], ethr_cv_32bit_$1,
+ [
+ ethr_cv_32bit_$1=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic32_call]])],[ethr_cv_32bit_$1=yes],[])
+ ])
+ AC_CACHE_CHECK([for 64-bit $1()], ethr_cv_64bit_$1,
+ [
+ ethr_cv_64bit_$1=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic64_call]])],[ethr_cv_64bit_$1=yes],[])
+ ])
+ AC_CACHE_CHECK([for 128-bit $1()], ethr_cv_128bit_$1,
+ [
+ ethr_cv_128bit_$1=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic128_call]])],[ethr_cv_128bit_$1=yes],[])
+ ])
+
+ case $ethr_cv_128bit_$1-$ethr_cv_64bit_$1-$ethr_cv_32bit_$1 in
+ no-no-no)
+ have_atomic_ops=0;;
+ no-no-yes)
+ have_atomic_ops=4;;
+ no-yes-no)
+ have_atomic_ops=8;;
+ no-yes-yes)
+ have_atomic_ops=12;;
+ yes-no-no)
+ have_atomic_ops=16;;
+ yes-no-yes)
+ have_atomic_ops=20;;
+ yes-yes-no)
+ have_atomic_ops=24;;
+ yes-yes-yes)
+ have_atomic_ops=28;;
+ esac
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_$1], [$have_atomic_ops], [Define as a bitmask corresponding to the word sizes that $1() can handle on your system])
+])
+
+AC_DEFUN(ETHR_CHK_IF_NOOP,
+[
+ ethr_test_filename="chk_if_$1$3_noop_config1test.$$"
+ cat > "${ethr_test_filename}.c" <<EOF
+int
+my_test(void)
+{
+ $1$2;
+ return 0;
+}
+EOF
+ $CC -O3 $ETHR_DEFS -c "${ethr_test_filename}.c" -o "${ethr_test_filename}1.o"
+ cat > "${ethr_test_filename}.c" <<EOF
+int
+my_test(void)
+{
+ ;
+ return 0;
+}
+EOF
+ $CC -O3 $ETHR_DEFS -c "${ethr_test_filename}.c" -o "${ethr_test_filename}2.o"
+ if diff "${ethr_test_filename}1.o" "${ethr_test_filename}2.o" >/dev/null 2>&1; then
+ ethr_$1$3_noop=yes
+ else
+ ethr_$1$3_noop=no
+ fi
+ rm -f "${ethr_test_filename}.c" "${ethr_test_filename}1.o" "${ethr_test_filename}2.o"
+])
+
+AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
+[
+ AC_CHECK_SIZEOF(short)
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_short" = "4"; then
+ gcc_atomic_type32="short"
+ elif test "$ac_cv_sizeof_int" = "4"; then
+ gcc_atomic_type32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ gcc_atomic_type32="long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof_int" = "8"; then
+ gcc_atomic_type64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ gcc_atomic_type64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ gcc_atomic_type64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ gcc_atomic_type128="__int128_t"
+ else
+ gcc_atomic_type128="#error "
+ fi
+ AC_CACHE_CHECK([for a working __sync_synchronize()], ethr_cv___sync_synchronize,
+ [
+ ethr_cv___sync_synchronize=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ __sync_synchronize(); ]])],[ethr_cv___sync_synchronize=yes],[])
+ if test $ethr_cv___sync_synchronize = yes; then
+ #
+ # Old gcc versions on at least x86 have a buggy
+ # __sync_synchronize() which does not emit a
+ # memory barrier. We try to detect this by
+ # compiling to assembly with and without
+ # __sync_synchronize() and compare the results.
+ #
+ ETHR_CHK_IF_NOOP(__sync_synchronize, [()], [])
+ if test $ethr___sync_synchronize_noop = yes; then
+ # Got a buggy implementation of
+ # __sync_synchronize...
+ ethr_cv___sync_synchronize="no; buggy implementation"
+ fi
+ fi
+ ])
+
+ if test "$ethr_cv___sync_synchronize" = "yes"; then
+ have_sync_synchronize_value="~0"
+ else
+ have_sync_synchronize_value="0"
+ fi
+ AC_DEFINE_UNQUOTED([ETHR_HAVE___sync_synchronize], [$have_sync_synchronize_value], [Define as a bitmask corresponding to the word sizes that __sync_synchronize() can handle on your system])
+
+ ETHR_CHK_GCC_ATOMIC_OP__(__sync_add_and_fetch)
+ ETHR_CHK_GCC_ATOMIC_OP__(__sync_fetch_and_and)
+ ETHR_CHK_GCC_ATOMIC_OP__(__sync_fetch_and_or)
+ ETHR_CHK_GCC_ATOMIC_OP__(__sync_val_compare_and_swap)
+
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_store_n)
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_load_n)
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_add_fetch)
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_fetch_and)
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_fetch_or)
+ ETHR_CHK_GCC_ATOMIC_OP__(__atomic_compare_exchange_n)
+
+ ethr_have_gcc_native_atomics=no
+ ethr_arm_dbm_sy_instr_val=0
+ ethr_arm_dbm_st_instr_val=0
+ ethr_arm_dbm_ld_instr_val=0
+ ethr_arm_isb_sy_instr_val=0
+ ethr_arm_dc_cvau_instr_val=0
+ ethr_arm_ic_ivau_instr_val=0
+ AS_CASE(
+ ["$GCC-$host_cpu"],
+ [yes-arm*|yes-aarch*],
+ [
+ AC_CACHE_CHECK([for ARM 'dmb sy' instruction], ethr_cv_arm_dbm_sy_instr,
+ [
+ ethr_cv_arm_dbm_sy_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ __asm__ __volatile__("dmb sy" : : : "memory");
+ ]])],[ethr_cv_arm_dbm_sy_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_dbm_sy_instr = yes; then
+ ethr_arm_dbm_sy_instr_val=1
+ test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
+ ethr_have_gcc_native_atomics=yes
+ fi
+ AC_CACHE_CHECK([for ARM 'dmb st' instruction], ethr_cv_arm_dbm_st_instr,
+ [
+ ethr_cv_arm_dbm_st_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ __asm__ __volatile__("dmb st" : : : "memory");
+ ]])],[ethr_cv_arm_dbm_st_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_dbm_st_instr = yes; then
+ ethr_arm_dbm_st_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'dmb ld' instruction], ethr_cv_arm_dbm_ld_instr,
+ [
+ ethr_cv_arm_dbm_ld_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ __asm__ __volatile__("dmb ld" : : : "memory");
+ ]])],[ethr_cv_arm_dbm_ld_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_dbm_ld_instr = yes; then
+ ethr_arm_dbm_ld_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'isb sy' instruction], ethr_cv_arm_isb_sy_instr,
+ [
+ ethr_cv_arm_isb_sy_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ __asm__ __volatile__("isb sy" : : : "memory");
+ ]])],[ethr_cv_arm_isb_sy_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_isb_sy_instr = yes; then
+ ethr_arm_isb_sy_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'dc cvau' instruction], ethr_cv_arm_dc_cvau_instr,
+ [
+ ethr_cv_arm_dc_cvau_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
+ ]])],[ethr_cv_arm_dc_cvau_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_dc_cvau_instr = yes; then
+ ethr_arm_dc_cvau_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'ic ivau' instruction], ethr_cv_arm_ic_ivau_instr,
+ [
+ ethr_cv_arm_ic_ivau_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
+ ]])],[ethr_cv_arm_ic_ivau_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_ic_ivau_instr = yes; then
+ ethr_arm_ic_ivau_instr_val=1
+ fi
+ ])
+
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION], [$ethr_arm_dbm_sy_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb sy' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION], [$ethr_arm_dbm_st_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb st' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION], [$ethr_arm_dbm_ld_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb ld' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION], [$ethr_arm_isb_sy_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'isb sy' instruction, and are compiling for an ARM processor with ARM ISB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION], [$ethr_arm_dc_cvau_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dc cvau' instruction, and are compiling for an ARM processor with ARM DC instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION], [$ethr_arm_ic_ivau_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'ic ivau' instruction, and are compiling for an ARM processor with ARM IC instruction support, or not])
+
+ test $ethr_cv_32bit___sync_val_compare_and_swap = yes &&
+ ethr_have_gcc_native_atomics=yes
+ test $ethr_cv_64bit___sync_val_compare_and_swap = yes &&
+ ethr_have_gcc_native_atomics=yes
+ if test "$ethr_cv___sync_synchronize" = "yes"; then
+ test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
+ ethr_have_gcc_native_atomics=yes
+ test $ethr_cv_32bit___atomic_compare_exchange_n = yes &&
+ ethr_have_gcc_native_atomics=yes
+ fi
+ ethr_have_gcc_atomic_builtins=0
+ if test $ethr_have_gcc_native_atomics = yes; then
+ ethr_native_atomic_implementation=gcc_sync
+ test $ethr_cv_32bit___atomic_compare_exchange_n = yes && ethr_have_gcc_atomic_builtins=1
+ test $ethr_cv_64bit___atomic_compare_exchange_n = yes && ethr_have_gcc_atomic_builtins=1
+ test $ethr_have_gcc_atomic_builtins = 1 && ethr_native_atomic_implementation=gcc_atomic_sync
+ fi
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC___ATOMIC_BUILTINS], [$ethr_have_gcc_atomic_builtins], [Define as a boolean indicating whether you have a gcc __atomic builtins or not])
+ test $ethr_have_gcc_native_atomics = yes && ethr_have_native_atomics=yes
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ]], [[
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ]])],[have_interlocked_op=yes],[])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_FIND_ETHR_LIB
+dnl
+dnl NOTE! This macro may be changed at any time! Should *only* be used by
+dnl ERTS!
+dnl
+dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
+dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
+dnl except that the ethread lib itself is not included), ETHR_DEFS to
+dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
+dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
+dnl to the name of the library where the ethread implementation is located.
+dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
+dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
+dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
+dnl empty string.
+dnl
+
+AC_DEFUN(ERL_FIND_ETHR_LIB,
+[
+
+AC_ARG_ENABLE(native-ethr-impls,
+ AS_HELP_STRING([--disable-native-ethr-impls],
+ [disable native ethread implementations]),
+[ case "$enableval" in
+ no) disable_native_ethr_impls=yes ;;
+ *) disable_native_ethr_impls=no ;;
+ esac ], disable_native_ethr_impls=no)
+
+test "X$disable_native_ethr_impls" = "Xyes" &&
+ AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
+
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
+AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
+ AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
+ [prefer gcc native ethread implementations]),
+[ case "$enableval" in
+ yes) enable_prefer_gcc_native_ethr_impls=yes ;;
+ *) enable_prefer_gcc_native_ethr_impls=no ;;
+ esac ], enable_prefer_gcc_native_ethr_impls=no)
+
+test $enable_prefer_gcc_native_ethr_impls = yes &&
+ AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+
+AC_ARG_ENABLE(trust-gcc-atomic-builtins-memory-barriers,
+ AS_HELP_STRING([--enable-trust-gcc-atomic-builtins-memory-barriers],
+ [trust gcc atomic builtins memory barriers]),
+[ case "$enableval" in
+ yes) trust_gcc_atomic_builtins_mbs=1 ;;
+ *) trust_gcc_atomic_builtins_mbs=0 ;;
+ esac ], trust_gcc_atomic_builtins_mbs=0)
+
+AC_DEFINE_UNQUOTED(ETHR_TRUST_GCC_ATOMIC_BUILTINS_MEMORY_BARRIERS, [$trust_gcc_atomic_builtins_mbs], [Define as a boolean indicating whether you trust gcc's __atomic_* builtins memory barrier implementations, or not])
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+AC_ARG_ENABLE(ppc-lwsync-instruction,
+AS_HELP_STRING([--enable-ppc-lwsync-instruction], [enable use of powerpc lwsync instruction])
+AS_HELP_STRING([--disable-ppc-lwsync-instruction], [disable use of powerpc lwsync instruction]),
+[ case "$enableval" in
+ no) enable_lwsync=no ;;
+ *) enable_lwsync=yes ;;
+ esac ],
+[
+ AC_CHECK_SIZEOF(void *)
+ case $host_cpu-$ac_cv_sizeof_void_p in
+ macppc-8|powerpc-8|ppc-8|powerpc64-8|ppc64-8|powerpc64le-8|ppc64le-8|"Power Macintosh"-8)
+ enable_lwsync=yes;;
+ *)
+ enable_lwsync=undefined;;
+ esac ])
+
+case $enable_lwsync in
+ no)
+ AC_DEFINE(ETHR_PPC_HAVE_NO_LWSYNC, [1], [Define if you do not have the powerpc lwsync instruction])
+ ;;
+ yes)
+ AC_DEFINE(ETHR_PPC_HAVE_LWSYNC, [1], [Define if you have the powerpc lwsync instruction])
+ ;;
+ *)
+ ;;
+esac
+
+LM_CHECK_THR_LIB
+ERL_INTERNAL_LIBS
+
+ERL_MONOTONIC_CLOCK(try_find_pthread_compatible, CLOCK_HIGHRES CLOCK_UPTIME_RAW CLOCK_MONOTONIC, no)
+
+case $erl_monotonic_clock_func in
+ clock_gettime)
+ AC_DEFINE(ETHR_HAVE_CLOCK_GETTIME_MONOTONIC, [1], [Define if you have a clock_gettime() with a monotonic clock])
+ ;;
+ mach_clock_get_time)
+ AC_DEFINE(ETHR_HAVE_MACH_CLOCK_GET_TIME, [1], [Define if you have a mach clock_get_time() with a monotonic clock])
+ ;;
+ gethrtime)
+ AC_DEFINE(ETHR_HAVE_GETHRTIME, [1], [Define if you have a monotonic gethrtime()])
+ ;;
+ *)
+ ;;
+esac
+
+if test "x$erl_monotonic_clock_id" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MONOTONIC_CLOCK_ID, [$erl_monotonic_clock_id], [Define to the monotonic clock id to use])
+fi
+
+ethr_native_atomic_implementation=none
+ethr_have_native_atomics=no
+ethr_have_native_spinlock=no
+ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
+ETHR_DEFS="$THR_DEFS"
+ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS $erl_monotonic_clock_lib"
+ETHR_LIBS=
+ETHR_LIB_NAME=
+
+ethr_modified_default_stack_size=
+
+AC_ARG_WITH(threadnames,
+AS_HELP_STRING([--with-threadnames], [use pthread_setname to set the thread names (default)])
+AS_HELP_STRING([--without-threadnames],
+ [do not set any thread names]),
+[],
+[with_threadnames=yes])
+
+dnl Name of lib where ethread implementation is located
+ethr_lib_name=ethread
+
+AS_CASE(
+ ["$THR_LIB_NAME"],
+ [win32_threads],
+ [
+ ETHR_THR_LIB_BASE_DIR=win
+ # * _WIN32_WINNT >= 0x0400 is needed for
+ # TryEnterCriticalSection
+ # * _WIN32_WINNT >= 0x0403 is needed for
+ # InitializeCriticalSectionAndSpinCount
+ # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
+ #
+ # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
+ # and save it in ETHR_DEFS.
+ found_win32_winnt=no
+ for cppflag in $CPPFLAGS; do
+ case $cppflag in
+ -DWINVER*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ ;;
+ -D_WIN32_WINNT*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ found_win32_winnt=yes
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if test $found_win32_winnt = no; then
+ AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
+ fi
+
+ AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
+
+ if test "X$disable_native_ethr_impls" = "Xyes"; then
+ have_interlocked_op=no
+ ethr_have_native_atomics=no
+ else
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+ fi
+ if test "$ethr_have_native_atomics" = "yes"; then
+ ethr_native_atomic_implementation=windows
+ ethr_have_native_spinlock=yes
+ fi
+ ],
+ [pthread],
+ [
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
+ case $host_os in
+ openbsd*)
+ # The default stack size is insufficient for our needs
+ # on OpenBSD. We increase it to 256 kilo words.
+ ethr_modified_default_stack_size=256;;
+ linux*)
+ ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
+
+ if test X$cross_compiling = Xyes; then
+ case X$erl_xcomp_linux_usable_sigusrx in
+ X) usable_sigusrx=cross;;
+ Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
+ esac
+ case X$erl_xcomp_linux_usable_sigaltstack in
+ X) usable_sigaltstack=cross;;
+ Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
+ esac
+ else
+ # FIXME: Test for actual problems instead of kernel versions
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
+ usable_sigusrx=no
+ usable_sigaltstack=no;;
+ 2.[[2-3]]|2.[[2-3]].*)
+ usable_sigusrx=yes
+ usable_sigaltstack=no;;
+ *)
+ usable_sigusrx=yes
+ usable_sigaltstack=yes;;
+ esac
+ fi
+
+ AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
+ AC_MSG_RESULT($usable_sigusrx)
+ if test $usable_sigusrx = cross; then
+ usable_sigusrx=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigusrx = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
+ fi
+
+ AC_MSG_CHECKING(if sigaltstack can be used)
+ AC_MSG_RESULT($usable_sigaltstack)
+ if test $usable_sigaltstack = cross; then
+ usable_sigaltstack=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigaltstack = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need ETHR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
+
+ dnl We need the thread library in order to find some functions
+ saved_libs="$LIBS"
+ LIBS="$LIBS $ETHR_X_LIBS"
+
+ dnl
+ dnl Check for headers
+ dnl
+ AC_CHECK_HEADER(pthread.h, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ if test $NEED_NPTL_PTHREAD_H = yes; then
+ AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
+[Define if you need the <nptl/pthread.h> header file.])
+ fi
+
+ AC_CHECK_HEADER(sched.h, \
+ AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
+[Define if you have the <sched.h> header file.]))
+
+ AC_CHECK_HEADER(sys/time.h, \
+ AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
+[Define if you have the <sys/time.h> header file.]))
+
+ AC_MSG_CHECKING([for usable PTHREAD_STACK_MIN])
+ pthread_stack_min=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <limits.h>
+#if defined(ETHR_NEED_NPTL_PTHREAD_H)
+#include <nptl/pthread.h>
+#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+#include <pthread/mit/pthread.h>
+#elif defined(ETHR_HAVE_PTHREAD_H)
+#include <pthread.h>
+#endif
+ ]], [[return PTHREAD_STACK_MIN;]])],[pthread_stack_min=yes],[])
+
+ AC_MSG_RESULT([$pthread_stack_min])
+ test $pthread_stack_min != yes || {
+ AC_DEFINE(ETHR_HAVE_USABLE_PTHREAD_STACK_MIN, 1, [Define if you can use PTHREAD_STACK_MIN])
+ }
+
+ dnl
+ dnl Check for functions
+ dnl
+ AC_CHECK_FUNC([pthread_spin_lock], \
+ [ethr_have_native_spinlock=yes \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
+[Define if you have the pthread_spin_lock function.])])
+
+ have_sched_yield=no
+ have_librt_sched_yield=no
+ AC_CHECK_FUNC([sched_yield], [have_sched_yield=yes])
+ AS_IF(
+ [test $have_sched_yield = no],
+ [
+ AC_CHECK_LIB([rt], [sched_yield],
+ [have_librt_sched_yield=yes
+ ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
+ ])
+ AS_IF(
+ [test $have_sched_yield = yes || test $have_librt_sched_yield = yes],
+ [
+ AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
+ AC_MSG_CHECKING([whether sched_yield() returns an int])
+ sched_yield_ret_int=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #ifdef ETHR_HAVE_SCHED_H
+ #include <sched.h>
+ #endif
+ ]], [[int sched_yield();]])],[sched_yield_ret_int=yes],[])
+ AC_MSG_RESULT([$sched_yield_ret_int])
+ if test $sched_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
+ fi
+ ])
+
+ have_pthread_yield=no
+ AC_CHECK_FUNC([pthread_yield], [have_pthread_yield=yes])
+ AS_IF(
+ [test $have_pthread_yield = yes],
+ [
+ AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
+ AC_MSG_CHECKING([whether pthread_yield() returns an int])
+ pthread_yield_ret_int=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ]], [[int pthread_yield();]])],[pthread_yield_ret_int=yes],[])
+ AC_MSG_RESULT([$pthread_yield_ret_int])
+ if test $pthread_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
+ fi
+ ])
+
+ have_pthread_rwlock_init=no
+ AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
+ AS_IF(
+ [test $have_pthread_rwlock_init = yes],
+ [
+ ethr_have_pthread_rwlockattr_setkind_np=no
+ AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
+ [ethr_have_pthread_rwlockattr_setkind_np=yes])
+
+ AS_IF(
+ [test $ethr_have_pthread_rwlockattr_setkind_np = yes],
+ [
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
+[Define if you have the pthread_rwlockattr_setkind_np() function.])
+
+ AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
+ ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ]], [[
+ pthread_rwlockattr_t *attr;
+ return pthread_rwlockattr_setkind_np(attr,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ ]])],[ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes],[])
+ AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
+ if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
+[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
+ fi
+ ])
+ ])
+
+ if test "$force_pthread_rwlocks" = "yes"; then
+
+ AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
+[Define if you want to force usage of pthread rwlocks])
+
+ if test $have_pthread_rwlock_init = yes; then
+ AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
+ else
+ AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
+ fi
+ fi
+
+ AC_CHECK_FUNC(pthread_attr_setguardsize, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
+[Define if you have the pthread_attr_setguardsize function.]))
+
+ AS_IF(
+ [test "x$erl_monotonic_clock_id" != "x"],
+ [
+ AC_MSG_CHECKING(whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout)
+ pthread_cond_timedwait_monotonic=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ # include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ # include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ # include <pthread.h>
+ #endif
+ #include <time.h>
+ #ifdef ETHR_HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ #endif
+ #if defined(ETHR_HAVE_MACH_CLOCK_GET_TIME)
+ # include <mach/clock.h>
+ # include <mach/mach.h>
+ #endif
+ ]], [[
+ int res;
+ pthread_condattr_t attr;
+ pthread_cond_t cond;
+ struct timespec cond_timeout;
+ pthread_mutex_t mutex;
+ res = pthread_condattr_init(&attr);
+ res = pthread_condattr_setclock(&attr, ETHR_MONOTONIC_CLOCK_ID);
+ res = pthread_cond_init(&cond, &attr);
+ res = pthread_cond_timedwait(&cond, &mutex, &cond_timeout);
+ ]])],[pthread_cond_timedwait_monotonic=yes],[])
+ AC_MSG_RESULT([$pthread_cond_timedwait_monotonic])
+ if test $pthread_cond_timedwait_monotonic = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC, [1], [Define if pthread_cond_timedwait() can be used with a monotonic clock])
+ fi
+ ])
+
+ linux_futex=no
+ AC_MSG_CHECKING([for Linux futexes])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ ]], [[
+ int i = 1;
+ syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
+ (void*)0,(void*)0, 0);
+ syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
+ (void*)0,(void*)0, 0);
+ return 0;
+ ]])],[linux_futex=yes],[])
+ AC_MSG_RESULT([$linux_futex])
+ test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
+
+ pthread_setname=no
+ AC_MSG_CHECKING([for pthread_setname_np])
+ old_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -Werror"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #include <pthread.h>]], [[pthread_setname_np(pthread_self(), "name");]])],[pthread_setname=linux],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #include <pthread.h>]], [[pthread_set_name_np(pthread_self(), "name");]])],[pthread_setname=bsd],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _DARWIN_C_SOURCE
+ #include <pthread.h>]], [[pthread_setname_np("name");]])],[pthread_setname=darwin],[])
+ AC_MSG_RESULT([$pthread_setname])
+ case $with_threadnames-$pthread_setname in
+ yes-linux) AC_DEFINE(ETHR_HAVE_PTHREAD_SETNAME_NP_2, 1,
+ [Define if you have linux style pthread_setname_np]);;
+ yes-bsd) AC_DEFINE(ETHR_HAVE_PTHREAD_SET_NAME_NP_2, 1,
+ [Define if you have bsd style pthread_set_name_np]);;
+ yes-darwin) AC_DEFINE(ETHR_HAVE_PTHREAD_SETNAME_NP_1, 1,
+ [Define if you have darwin style pthread_setname_np]);;
+ *) ;;
+ esac
+
+ pthread_getname=no
+ AC_MSG_CHECKING([for pthread_getname_np])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #define _DARWIN_C_SOURCE
+ #include <pthread.h>]], [[char buff[256]; pthread_getname_np(pthread_self(), buff, 256);]])],[pthread_getname=linux],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #define _DARWIN_C_SOURCE
+ #include <pthread.h>]], [[char buff[256]; pthread_getname_np(pthread_self(), buff);]])],[pthread_getname=ibm],[])
+ AC_MSG_RESULT([$pthread_getname])
+ case $pthread_getname in
+ linux) AC_DEFINE(ETHR_HAVE_PTHREAD_GETNAME_NP_3, 1,
+ [Define if you have linux style pthread_getname_np]);;
+ ibm) AC_DEFINE(ETHR_HAVE_PTHREAD_GETNAME_NP_2, 1,
+ [Define if you have ibm style pthread_getname_np]);;
+ *) ;;
+ esac
+ CFLAGS=$old_CFLAGS
+
+ AS_IF(
+ [test "X$disable_native_ethr_impls" = "Xyes"],
+ [
+ ethr_have_native_atomics=no
+ ],
+ [
+ ETHR_CHK_GCC_ATOMIC_OPS([])
+
+ AC_MSG_CHECKING([for a usable libatomic_ops implementation])
+ case "x$with_libatomic_ops" in
+ xno | xyes | x)
+ libatomic_ops_include=
+ ;;
+ *)
+ if test -d "${with_libatomic_ops}/include"; then
+ libatomic_ops_include="-I$with_libatomic_ops/include"
+ CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
+ else
+ AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
+ fi;;
+ esac
+ ethr_have_libatomic_ops=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "atomic_ops.h"]], [[
+ volatile AO_t x;
+ AO_t y;
+ int z;
+
+ AO_nop_full();
+#if defined(AO_HAVE_store)
+ AO_store(&x, (AO_t) 0);
+#elif defined(AO_HAVE_store_release)
+ AO_store_release(&x, (AO_t) 0);
+#else
+#error No store
+#endif
+#if defined(AO_HAVE_load)
+ z = AO_load(&x);
+#elif defined(AO_HAVE_load_acquire)
+ z = AO_load_acquire(&x);
+#else
+#error No load
+#endif
+#if defined(AO_HAVE_compare_and_swap_full)
+ z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
+#elif defined(AO_HAVE_compare_and_swap_release)
+ z = AO_compare_and_swap_release(&x, (AO_t) 0, (AO_t) 1);
+#elif defined(AO_HAVE_compare_and_swap_acquire)
+ z = AO_compare_and_swap_acquire(&x, (AO_t) 0, (AO_t) 1);
+#elif defined(AO_HAVE_compare_and_swap)
+ z = AO_compare_and_swap(&x, (AO_t) 0, (AO_t) 1);
+#else
+#error No compare_and_swap
+#endif
+ ]])],[ethr_have_native_atomics=yes
+ ethr_native_atomic_implementation=libatomic_ops
+ ethr_have_libatomic_ops=yes],[])
+ AC_MSG_RESULT([$ethr_have_libatomic_ops])
+ AS_IF(
+ [test $ethr_have_libatomic_ops = yes],
+ [
+ AC_CHECK_SIZEOF(AO_t, ,
+ [
+ #include <stdio.h>
+ #include "atomic_ops.h"
+ ])
+ AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
+
+ AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
+ if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
+ fi
+ ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
+ ],
+ [test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"],
+ [
+ AC_MSG_ERROR([No usable libatomic_ops implementation found])
+ ])
+
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_native_atomic_implementation=ethread
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_native_atomic_implementation=ethread
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | powerpc | "Power Macintosh")
+ ethr_native_atomic_implementation=ethread
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_native_atomic_implementation=ethread
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ ])
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
+ dnl Restore LIBS
+ LIBS=$saved_libs
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ])
+
+AC_MSG_CHECKING([whether default stack size should be modified])
+if test "x$ethr_modified_default_stack_size" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
+ AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
+else
+ AC_MSG_RESULT([no])
+fi
+
+if test "x$ETHR_THR_LIB_BASE" != "x"; then
+ ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
+ ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
+ ETHR_LIB_NAME=$ethr_lib_name
+fi
+
+AC_CHECK_SIZEOF(void *)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
+
+AC_CHECK_SIZEOF(int)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
+AC_CHECK_SIZEOF(long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
+AC_CHECK_SIZEOF(long long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
+AC_CHECK_SIZEOF(__int64)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
+
+
+case X$erl_xcomp_bigendian in
+ X) ;;
+ Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
+esac
+
+AC_C_BIGENDIAN
+
+if test "$ac_cv_c_bigendian" = "yes"; then
+ AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
+fi
+
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
+ETHR_X86_SSE2_ASM=no
+AS_CASE(
+ ["$GCC-$ac_cv_sizeof_void_p-$host_cpu"],
+ [yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64],
+ [
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ]])],[gcc_sse2_asm=yes],[])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ])
+
+AS_CASE(
+ ["$GCC-$host_cpu"],
+ [yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64],
+ [
+ if test $ac_cv_sizeof_void_p = 4; then
+ dw_cmpxchg="cmpxchg8b"
+ else
+ dw_cmpxchg="cmpxchg16b"
+ fi
+
+ gcc_dw_cmpxchg_asm=no
+ gcc_pic_dw_cmpxchg_asm=no
+ gcc_cflags_pic=no
+ gcc_cmpxchg8b_pic_no_clobber_ebx=no
+ gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=no
+
+ save_CFLAGS="$CFLAGS"
+
+ # Check if it works out of the box using passed CFLAGS
+ # and with -fPIC added to CFLAGS if the passed CFLAGS
+ # doesn't trigger position independent code
+ pic_cmpxchg=unknown
+ while true; do
+
+ case $pic_cmpxchg in
+ yes) pic_text="pic ";;
+ *) pic_text="";;
+ esac
+
+ AC_MSG_CHECKING([for gcc $pic_text$dw_cmpxchg plain asm support])
+
+ plain_cmpxchg=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
+#endif
+ "setz %3\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "b"(new[0])
+ : "cc", "memory");
+ ]])],[plain_cmpxchg=yes],[])
+
+ AC_MSG_RESULT([$plain_cmpxchg])
+
+ if test $pic_cmpxchg = yes; then
+ gcc_pic_dw_cmpxchg_asm=$plain_cmpxchg
+ break
+ fi
+
+ gcc_dw_cmpxchg_asm=$plain_cmpxchg
+
+ # If not already compiling to position independent
+ # code add -fPIC to CFLAGS and do it again. This
+ # since we want also want to know how to compile
+ # to position independent code since this might
+ # cause problems with the use of the EBX register
+ # as input to the asm on 32-bit x86 and old gcc
+ # compilers (gcc vsn < 5).
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+#if !defined(__PIC__) || !__PIC__
+# error no pic
+#endif
+ ]])],[pic_cmpxchg=yes
+ gcc_cflags_pic=yes],[pic_cmpxchg=no])
+
+ if test $pic_cmpxchg = yes; then
+ gcc_pic_dw_cmpxchg_asm=$gcc_dw_cmpxchg_asm
+ break
+ fi
+
+ CFLAGS="$save_CFLAGS -fPIC"
+ pic_cmpxchg=yes
+
+ done
+
+ AS_IF(
+ [test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4],
+ [
+
+ AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX workaround])
+
+ # Check if we can work around it by managing the ebx
+ # register explicitly in the asm...
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "r"(new[0])
+ : "cc", "memory");
+ ]])],[gcc_pic_dw_cmpxchg_asm=yes
+ gcc_cmpxchg8b_pic_no_clobber_ebx=yes],[])
+
+ AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
+
+ AS_IF(
+ [test $gcc_pic_dw_cmpxchg_asm = no],
+ [
+
+ AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds])
+ # If no optimization is enabled we sometimes get a
+ # register shortage. Check if we can work around
+ # this...
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "r"(new)
+ : "cc", "memory");
+
+ ]])],[gcc_pic_dw_cmpxchg_asm=yes
+ gcc_cmpxchg8b_pic_no_clobber_ebx=yes
+ gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=yes],[])
+
+ AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
+ ])
+
+ if test $gcc_cflags_pic = yes; then
+ gcc_dw_cmpxchg_asm=$gcc_pic_dw_cmpxchg_asm
+ fi
+ ])
+
+ CFLAGS="$save_CFLAGS"
+
+ if test "$gcc_cmpxchg8b_pic_no_clobber_ebx" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX, 1, [Define if gcc won't let you clobber ebx with cmpxchg8b and position independent code])
+ fi
+ if test "$gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi
+ ])
+
+AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
+[Define if you have all ethread defines])
+
+AC_SUBST(ETHR_X_LIBS)
+AC_SUBST(ETHR_LIBS)
+AC_SUBST(ETHR_LIB_NAME)
+AC_SUBST(ETHR_DEFS)
+AC_SUBST(ETHR_THR_LIB_BASE)
+AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
+
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_TIME_CORRECTION
+dnl
+dnl Check for primitives that can be used for implementing
+dnl erts_os_monotonic_time() and erts_os_system_time()
+dnl
+
+AC_DEFUN(ERL_TIME_CORRECTION,
+[
+
+AC_ARG_WITH(clock-resolution,
+AS_HELP_STRING([--with-clock-resolution=high|low|default],
+ [specify wanted clock resolution]))
+
+AC_ARG_WITH(clock-gettime-realtime-id,
+AS_HELP_STRING([--with-clock-gettime-realtime-id=CLOCKID],
+ [specify clock id to use with clock_gettime() for realtime time)]))
+
+AC_ARG_WITH(clock-gettime-monotonic-id,
+AS_HELP_STRING([--with-clock-gettime-monotonic-id=CLOCKID],
+ [specify clock id to use with clock_gettime() for monotonic time)]))
+
+AC_ARG_ENABLE(prefer-elapsed-monotonic-time-during-suspend,
+AS_HELP_STRING([--enable-prefer-elapsed-monotonic-time-during-suspend],
+ [Prefer an OS monotonic time source with elapsed time during suspend])
+AS_HELP_STRING([--disable-prefer-elapsed-monotonic-time-during-suspend],
+ [Do not prefer an OS monotonic time source with elapsed time during suspend]),
+[ case "$enableval" in
+ yes) prefer_elapsed_monotonic_time_during_suspend=yes ;;
+ *) prefer_elapsed_monotonic_time_during_suspend=no ;;
+ esac ], prefer_elapsed_monotonic_time_during_suspend=no)
+
+AC_ARG_ENABLE(gettimeofday-as-os-system-time,
+ AS_HELP_STRING([--enable-gettimeofday-as-os-system-time],
+ [Force usage of gettimeofday() for OS system time]),
+[ case "$enableval" in
+ yes) force_gettimeofday_os_system_time=yes ;;
+ *) force_gettimeofday_os_system_time=no ;;
+ esac ], force_gettimeofday_os_system_time=no)
+
+case "$with_clock_resolution" in
+ ""|no|yes)
+ with_clock_resolution=default;;
+ high|low|default)
+ ;;
+ *)
+ AC_MSG_ERROR([Invalid wanted clock resolution: $with_clock_resolution])
+ ;;
+esac
+
+AS_IF(
+ [test "$force_gettimeofday_os_system_time" = "yes"],
+ [
+
+ AC_CHECK_FUNCS([gettimeofday])
+ if test "$ac_cv_func_gettimeofday" = "yes"; then
+ AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY, [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
+ else
+ AC_MSG_ERROR([No gettimeofday() available])
+ fi
+ ],
+ [
+ # $force_gettimeofday_os_system_time != yes
+
+case "$with_clock_gettime_realtime_id" in
+ ""|no)
+ with_clock_gettime_realtime_id=no
+ ;;
+ CLOCK_*CPUTIME*)
+ AC_MSG_ERROR([Invalid clock_gettime() realtime clock id: Refusing to use the cputime clock id $with_clock_gettime_realtime_id as realtime clock id])
+ ;;
+ CLOCK_MONOTONIC*|CLOCK_BOOTTIME*|CLOCK_UPTIME*|CLOCK_HIGHRES*)
+ AC_MSG_ERROR([Invalid clock_gettime() realtime clock id: Refusing to use the monotonic clock id $with_clock_gettime_realtime_id as realtime clock id])
+ ;;
+ CLOCK_*)
+ ;;
+ *)
+ AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_realtime_id])
+ ;;
+esac
+
+AS_CASE(["$with_clock_resolution-$with_clock_gettime_realtime_id"],
+ [high-no],
+ [
+ ERL_WALL_CLOCK([high_resolution])
+ ],
+ [low-no],
+ [
+ ERL_WALL_CLOCK([low_resolution])
+ ],
+ [default-no],
+ [
+ ERL_WALL_CLOCK([default_resolution])
+ ],
+ [
+ ERL_WALL_CLOCK([custom_resolution], [$with_clock_gettime_realtime_id])
+ ])
+
+case "$erl_wall_clock_func-$erl_wall_clock_id-$with_clock_gettime_realtime_id" in
+ *-*-no)
+ ;;
+ clock_gettime-$with_clock_gettime_realtime_id-$with_clock_gettime_realtime_id)
+ ;;
+ *)
+ AC_MSG_ERROR([$with_clock_gettime_realtime_id as clock id to clock_gettime() doesn't compile])
+ ;;
+esac
+
+case $erl_wall_clock_func in
+ none)
+ AC_MSG_ERROR([No wall clock source found])
+ ;;
+ mach_clock_get_time)
+ AC_DEFINE(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_system_time() using mach clock_get_time()])
+ ;;
+ clock_gettime)
+ AC_DEFINE(OS_SYSTEM_TIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_system_time() using clock_gettime()])
+ ;;
+ gettimeofday)
+ AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY, [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
+ ;;
+ *)
+ ;;
+esac
+
+if test "x$erl_wall_clock_id" != "x"; then
+ AC_DEFINE_UNQUOTED(WALL_CLOCK_ID_STR, ["$erl_wall_clock_id"], [Define as a string of wall clock id to use])
+ AC_DEFINE_UNQUOTED(WALL_CLOCK_ID, [$erl_wall_clock_id], [Define to wall clock id to use])
+fi
+
+ ]) # $force_gettimeofday_os_system_time != yes
+
+case "$with_clock_gettime_monotonic_id" in
+ ""|no)
+ with_clock_gettime_monotonic_id=no
+ ;;
+ CLOCK_*CPUTIME*)
+ AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the cputime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
+ ;;
+ CLOCK_REALTIME*|CLOCK_TAI*)
+ AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the realtime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
+ ;;
+ CLOCK_MONOTONIC)
+ case $host_os in
+ darwin*)
+ # CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
+ # and Monterey, since it may step backwards.
+ AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use $with_clock_gettime_monotonic_id as monotonic clock id since it is buggy on MacOS]);;
+ *)
+ ;;
+ esac;;
+ CLOCK_*)
+ ;;
+ *)
+ AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_monotonic_id])
+ ;;
+esac
+
+AS_CASE(["$with_clock_resolution-$with_clock_gettime_monotonic_id"],
+ [high-no],
+ [
+ ERL_MONOTONIC_CLOCK([high_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [low-no],
+ [
+ ERL_MONOTONIC_CLOCK([low_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [default-no],
+ [
+ ERL_MONOTONIC_CLOCK([default_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [
+ ERL_MONOTONIC_CLOCK([custom_resolution], [$with_clock_gettime_monotonic_id], [$prefer_elapsed_monotonic_time_during_suspend])
+ ])
+
+case "$erl_monotonic_clock_func-$erl_monotonic_clock_id-$with_clock_gettime_monotonic_id" in
+ *-*-no)
+ ;;
+ clock_gettime-$with_clock_gettime_monotonic_id-$with_clock_gettime_monotonic_id)
+ ;;
+ *)
+ AC_MSG_ERROR([$with_clock_gettime_monotonic_id as clock id to clock_gettime() doesn't compile])
+ ;;
+esac
+
+case $erl_monotonic_clock_func in
+ times)
+ AC_DEFINE(OS_MONOTONIC_TIME_USING_TIMES, [1], [Define if you want to implement erts_os_monotonic_time() using times()])
+ ;;
+ mach_clock_get_time)
+ AC_DEFINE(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_monotonic_time() using mach clock_get_time()])
+ ;;
+ clock_gettime)
+ AC_DEFINE(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_monotonic_time() using clock_gettime()])
+ ;;
+ gethrtime)
+ AC_DEFINE(OS_MONOTONIC_TIME_USING_GETHRTIME, [1], [Define if you want to implement erts_os_monotonic_time() using gethrtime()])
+ ;;
+ *)
+ ;;
+esac
+
+if test $erl_corrected_monotonic_clock = yes; then
+ AC_DEFINE(ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME, [1], [Define if OS monotonic clock is corrected])
+fi
+
+if test $erl_monotonic_clock_low_resolution = yes; then
+ AC_DEFINE(ERTS_HAVE_LOW_RESOLUTION_OS_MONOTONIC_LOW, [1], [Define if you have a low resolution OS monotonic clock])
+fi
+
+xrtlib=
+if test "$erl_monotonic_clock_lib" != ""; then
+ xrtlib="$erl_monotonic_clock_lib"
+fi
+if test "$erl_wall_clock_lib" != ""; then
+ xrtlib="$erl_wall_clock_lib"
+fi
+if test "x$erl_monotonic_clock_id" != "x"; then
+ AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID_STR, ["$erl_monotonic_clock_id"], [Define as a string of monotonic clock id to use])
+ AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID, [$erl_monotonic_clock_id], [Define to monotonic clock id to use])
+fi
+
+if test $erl_cv_clock_gettime_monotonic_raw = yes; then
+ AC_DEFINE(HAVE_CLOCK_GETTIME_MONOTONIC_RAW, [1], [Define if you have clock_gettime(CLOCK_MONOTONIC_RAW, _)])
+fi
+
+ERL_MONOTONIC_CLOCK([high_resolution], [undefined], [no])
+
+case $erl_monotonic_clock_low_resolution-$erl_monotonic_clock_func in
+ no-mach_clock_get_time)
+ monotonic_hrtime=yes
+ AC_DEFINE(SYS_HRTIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_hrtime() using mach clock_get_time()])
+ ;;
+ no-clock_gettime)
+ monotonic_hrtime=yes
+ AC_DEFINE(SYS_HRTIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_hrtime() using clock_gettime()])
+ ;;
+ no-gethrtime)
+ monotonic_hrtime=yes
+ AC_DEFINE(SYS_HRTIME_USING_GETHRTIME, [1], [Define if you want to implement erts_os_hrtime() using gethrtime()])
+ ;;
+ *)
+ monotonic_hrtime=no
+ ;;
+esac
+
+if test $monotonic_hrtime = yes; then
+ AC_DEFINE(HAVE_MONOTONIC_ERTS_SYS_HRTIME, [1], [Define if you have a monotonic erts_os_hrtime() implementation])
+fi
+
+if test "x$erl_monotonic_clock_id" != "x"; then
+ AC_DEFINE_UNQUOTED(HRTIME_CLOCK_ID_STR, ["$erl_monotonic_clock_id"], [Define as a string of monotonic clock id to use])
+ AC_DEFINE_UNQUOTED(HRTIME_CLOCK_ID, [$erl_monotonic_clock_id], [Define to monotonic clock id to use])
+fi
+
+
+dnl
+dnl Check if gethrvtime is working, and if to use procfs ioctl
+dnl or (yet to be written) write to the procfs ctl file.
+dnl
+
+AC_MSG_CHECKING([if gethrvtime works and how to use it])
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+/* gethrvtime procfs ioctl test */
+/* These need to be undef:ed to not break activation of
+ * micro level process accounting on /proc/self
+ */
+#ifdef _LARGEFILE_SOURCE
+# undef _LARGEFILE_SOURCE
+#endif
+#ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+int main() {
+ long msacct = PR_MSACCT;
+ int fd;
+ long long start, stop;
+ int i;
+ pid_t pid = getpid();
+ char proc_self[30] = "/proc/";
+
+ sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
+ if ( (fd = open(proc_self, O_WRONLY)) == -1)
+ exit(1);
+ if (ioctl(fd, PIOCSET, &msacct) < 0)
+ exit(2);
+ if (close(fd) < 0)
+ exit(3);
+ start = gethrvtime();
+ for (i = 0; i < 100; i++)
+ stop = gethrvtime();
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+}
+]])],[erl_gethrvtime=procfs_ioctl],[erl_gethrvtime=false],[
+case X$erl_xcomp_gethrvtime_procfs_ioctl in
+ X)
+ erl_gethrvtime=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
+ erl_gethrvtime=procfs_ioctl
+ else
+ erl_gethrvtime=false
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
+esac
+])
+
+LIBRT=$xrtlib
+AS_IF([test "$erl_gethrvtime" = "procfs_ioctl"],
+ [
+ AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
+ [define if gethrvtime() works and uses ioctl() to /proc/self])
+ AC_MSG_RESULT(uses ioctl to procfs)
+ ],
+ [
+ if test $erl_gethrvtime = cross; then
+ erl_gethrvtime=false
+ AC_MSG_RESULT(cross)
+ AC_MSG_WARN([result 'not working' guessed because of cross compilation])
+ else
+ AC_MSG_RESULT(not working)
+ fi
+
+ dnl
+ dnl Check if clock_gettime (linux) is working
+ dnl
+
+ AC_MSG_CHECKING([if clock_gettime can be used to get thread CPU time])
+ save_libs=$LIBS
+ LIBS="-lrt"
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <time.h>
+ int main() {
+ long long start, stop;
+ int i;
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp) < 0)
+ exit(1);
+ start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ for (i = 0; i < 100; i++)
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
+ stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+ }
+ ]])],[erl_clock_gettime_cpu_time=yes],[erl_clock_gettime_cpu_time=no],[
+ case X$erl_xcomp_clock_gettime_cpu_time in
+ X) erl_clock_gettime_cpu_time=cross;;
+ Xyes|Xno) erl_clock_gettime_cpu_time=$erl_xcomp_clock_gettime_cpu_time;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
+ esac
+ ])
+ LIBS=$save_libs
+ AC_MSG_RESULT($erl_clock_gettime_cpu_time)
+ case $erl_clock_gettime_cpu_time in
+ yes)
+ AC_DEFINE(HAVE_CLOCK_GETTIME_CPU_TIME,[],
+ [define if clock_gettime() works for getting thread time])
+ LIBRT=-lrt
+ ;;
+ cross)
+ erl_clock_gettime_cpu_time=no
+ AC_MSG_WARN([result no guessed because of cross compilation])
+ ;;
+ *)
+ ;;
+ esac
+ ])
+AC_SUBST(LIBRT)
+])dnl
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_TRY_ENABLE_CFLAG
+dnl
+dnl
+dnl Tries a CFLAG and sees if it can be enabled without compiler errors
+dnl $1: textual cflag to add
+dnl $2: variable to store the modified CFLAG in
+dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS])
+dnl
+dnl
+AC_DEFUN([LM_TRY_ENABLE_CFLAG], [
+ AC_MSG_CHECKING([if we can add $1 to $2 (via CFLAGS)])
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="$1 $$2";
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[can_enable_flag=true],[can_enable_flag=false])
+ CFLAGS=$saved_CFLAGS;
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
+ AC_MSG_RESULT([yes])
+ AS_VAR_SET($2, "$1 $$2")
+ ],
+ [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([LM_CHECK_ENABLE_CFLAG], [
+ AC_MSG_CHECKING([whether $CC accepts $1...])
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="$1 $CFLAGS";
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[can_enable_flag=true],[can_enable_flag=false])
+ CFLAGS=$saved_CFLAGS;
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
+ AS_VAR_SET($2, true)
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AS_VAR_SET($2, false)
+ AC_MSG_RESULT([no])
+ ])
+])
+
+dnl
+dnl LM_CHECK_RUN_CFLAG
+dnl
+dnl As LM_CHECK_ENABLE_CFLAG but also runs the command. Required for testing
+dnl profile-guided optimization, for which the "use" step may require that the
+dnl binary created in the "generate" step runs.
+dnl
+AC_DEFUN([LM_CHECK_RUN_CFLAG], [
+ AC_MSG_CHECKING([whether $CC accepts $1...])
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="$1 $CFLAGS";
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[]])],[return 0;],[can_enable_flag=true],[can_enable_flag=false])
+ CFLAGS=$saved_CFLAGS;
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
+ AS_VAR_SET($2, true)
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AS_VAR_SET($2, false)
+ AC_MSG_RESULT([no])
+ ])
+])
+
+dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
+dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Freely inspired by AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[],[]). (Maybe better to create a
+dnl AC_LANG_JAVA instead...)
+AC_DEFUN(ERL_TRY_LINK_JAVA,
+[java_link='$JAVAC conftest.java 1>&AS_MESSAGE_LOG_FD'
+changequote(, )dnl
+cat > conftest.java <<EOF
+$1
+class conftest { public static void main(String[] args) {
+ $2
+ ; return; }}
+EOF
+changequote([, ])dnl
+AS_IF(
+ [AC_TRY_EVAL(java_link) && test -s conftest.class],
+ [
+ ifelse([$3], , :, [rm -rf conftest*
+ $3])
+
+ ],
+ [
+ echo "configure: failed program was:" 1>&AS_MESSAGE_LOG_FD
+ cat conftest.java 1>&AS_MESSAGE_LOG_FD
+ echo "configure: PATH was $PATH" 1>&AS_MESSAGE_LOG_FD
+ifelse([$4], , , [ rm -rf conftest*
+ $4
+])dnl
+
+ ])
+rm -f conftest*])
+dnl #define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_HARDWARE_ARCH
+dnl
+dnl Determine target hardware in ARCH
+dnl
+AC_DEFUN([LM_HARDWARE_ARCH], [
+ AC_MSG_CHECKING([target hardware architecture])
+ if test "x$host_alias" != "x" -a "x$host_cpu" != "x"; then
+ chk_arch_=$host_cpu
+ else
+ chk_arch_=`uname -m`
+ fi
+
+ case $chk_arch_ in
+ sun4u) ARCH=ultrasparc;;
+ sparc64) ARCH=sparc64;;
+ sun4v) ARCH=ultrasparc;;
+ i86pc) ARCH=x86;;
+ i386) ARCH=x86;;
+ i486) ARCH=x86;;
+ i586) ARCH=x86;;
+ i686) ARCH=x86;;
+ x86_64) ARCH=amd64;;
+ amd64) ARCH=amd64;;
+ macppc) ARCH=ppc;;
+ powerpc) ARCH=ppc;;
+ ppc) ARCH=ppc;;
+ ppc64) ARCH=ppc64;;
+ ppc64le) ARCH=ppc64le;;
+ powerpc64) ARCH=ppc64;;
+ powerpc64le) ARCH=ppc64le;;
+ "Power Macintosh") ARCH=ppc;;
+ arm64) ARCH=arm64;;
+ armv5b) ARCH=arm;;
+ armv5teb) ARCH=arm;;
+ armv5tel) ARCH=arm;;
+ armv5tejl) ARCH=arm;;
+ armv6l) ARCH=arm;;
+ armv6hl) ARCH=arm;;
+ armv7l) ARCH=arm;;
+ armv7hl) ARCH=arm;;
+ armv8*) ARCH=arm;;
+ aarch64) ARCH=arm64;;
+ aarch*) ARCH=arm;;
+ tile) ARCH=tile;;
+ e2k) ARCH=e2k;;
+ *) ARCH=noarch;;
+ esac
+ AC_MSG_RESULT($ARCH)
+
+ dnl
+ dnl Convert between x86 and amd64 based on the compiler's mode.
+ dnl Ditto between ultrasparc and sparc64.
+ dnl
+ AC_MSG_CHECKING(whether compilation mode forces ARCH adjustment)
+ case "$ARCH-$ac_cv_sizeof_void_p" in
+ x86-8)
+ AC_MSG_RESULT(yes: adjusting ARCH=x86 to ARCH=amd64)
+ ARCH=amd64
+ ;;
+ amd64-4)
+ AC_MSG_RESULT(yes: adjusting ARCH=amd64 to ARCH=x86)
+ ARCH=x86
+ ;;
+ ultrasparc-8)
+ AC_MSG_RESULT(yes: adjusting ARCH=ultrasparc to ARCH=sparc64)
+ ARCH=sparc64
+ ;;
+ sparc64-4)
+ AC_MSG_RESULT(yes: adjusting ARCH=sparc64 to ARCH=ultrasparc)
+ ARCH=ultrasparc
+ ;;
+ ppc64-4)
+ AC_MSG_RESULT(yes: adjusting ARCH=ppc64 to ARCH=ppc)
+ ARCH=ppc
+ ;;
+ ppc-8)
+ AC_MSG_RESULT(yes: adjusting ARCH=ppc to ARCH=ppc64)
+ ARCH=ppc64
+ ;;
+ arm-8)
+ AC_MSG_RESULT(yes: adjusting ARCH=arm to ARCH=arm64)
+ ARCH=arm64
+ ;;
+ *)
+ AC_MSG_RESULT(no: ARCH is $ARCH)
+ ;;
+ esac
+
+ AC_SUBST(ARCH)
+])
+
+dnl
+dnl--------------------------------------------------------------------
+dnl Dynamic Erlang Drivers
+dnl
+dnl Linking to produce dynamic Erlang drivers to be loaded by Erlang's
+dnl Dynamic Driver Loader and Linker (DDLL). Below the prefix DED is an
+dnl abbreviation for `Dynamic Erlang Driver'.
+dnl
+dnl For DED we need something quite sloppy, which allows undefined references
+dnl (notably driver functions) in the resulting shared library.
+dnl Example of Makefile rule (and settings of macros):
+dnl
+dnl LIBS = @LIBS@
+dnl LD = @DED_LD@
+dnl LDFLAGS = @DED_LDFLAGS@
+dnl soname = @ldsoname@
+dnl
+dnl my_drv.so: my_drv.o my_utils.o
+dnl $(LD) $(LDFLAGS) $(soname) $@ -o $@ $^ -lc $(LIBS)
+dnl
+dnl--------------------------------------------------------------------
+dnl
+
+AC_DEFUN(ERL_DED,
+ [
+
+LM_CHECK_THR_LIB
+
+if test "$THR_DEFS" = ""; then
+ DED_THR_DEFS="-D_THREAD_SAFE -D_REENTRANT"
+else
+ DED_THR_DEFS="$THR_DEFS"
+fi
+
+AC_SUBST(DED_THR_DEFS)
+
+ERL_DED_FLAGS
+
+])
+
+AC_DEFUN(ERL_DED_FLAGS,
+ [
+
+USER_LD=$LD
+USER_LDFLAGS="$LDFLAGS"
+
+DED_CC=$CC
+DED_GCC=$GCC
+
+DED_CFLAGS=
+DED_OSTYPE=unix
+case $host_os in
+ linux*)
+ DED_CFLAGS="-D_GNU_SOURCE" ;;
+ win32)
+ DED_CFLAGS="-D_WIN32_WINNT=0x0600 -DWINVER=0x0600"
+ DED_OSTYPE=win32 ;;
+ *)
+ ;;
+esac
+
+DED_WARN_FLAGS="-Wall -Wstrict-prototypes"
+case "$host_cpu" in
+ tile*)
+ # tile-gcc is a bit stricter with -Wmissing-prototypes than other gccs,
+ # and too strict for our taste.
+ ;;
+ *)
+ DED_WARN_FLAGS="$DED_WARN_FLAGS -Wmissing-prototypes";;
+esac
+
+LM_TRY_ENABLE_CFLAG([-Wdeclaration-after-statement], [DED_WARN_FLAGS])
+
+LM_TRY_ENABLE_CFLAG([-Werror=return-type], [DED_WERRORFLAGS])
+LM_TRY_ENABLE_CFLAG([-Werror=implicit], [DED_WERRORFLAGS])
+LM_TRY_ENABLE_CFLAG([-Werror=undef], [DED_WERRORFLAGS])
+
+DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$DED_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
+DED_INCLUDE=$DED_SYS_INCLUDE
+
+DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
+AS_IF(
+ [test "x$GCC" = xyes],
+ [
+ # Use -fno-common for gcc, that is link error if multiple definitions of
+ # global variables are encountered. This is ISO C compliant.
+ # Until version 10, gcc has had -fcommon as default, which allows and merges
+ # such dubious duplicates.
+ LM_TRY_ENABLE_CFLAG([-fno-common], [DED_CFLAGS])
+
+ LM_TRY_ENABLE_CFLAG([-fno-strict-aliasing], [DED_CFLAGS])
+
+ DED_STATIC_CFLAGS="$DED_CFLAGS"
+ DED_CFLAGS="$DED_CFLAGS -fPIC"
+ # Remove -fPIE and -fno-PIE
+ DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
+ ])
+
+DED_EXT=so
+case $host_os in
+ win32) DED_EXT=dll;;
+ darwin*)
+ DED_CFLAGS="$DED_CFLAGS -fno-common"
+ DED_STATIC_CFLAGS="$DED_STATIC_CFLAGS -fno-common";;
+ *)
+ ;;
+esac
+
+DED_STATIC_CFLAGS="$DED_STATIC_CFLAGS -DSTATIC_ERLANG_NIF -DSTATIC_ERLANG_DRIVER"
+
+if test "$CFLAG_RUNTIME_LIBRARY_PATH" = ""; then
+
+ CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-R"
+ case $host_os in
+ darwin*)
+ CFLAG_RUNTIME_LIBRARY_PATH=
+ ;;
+ win32)
+ CFLAG_RUNTIME_LIBRARY_PATH=
+ ;;
+ osf*)
+ CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-rpath,"
+ ;;
+ *)
+ ;;
+ esac
+
+fi
+
+# If DED_LD is set in environment, we expect all DED_LD* variables
+# to be specified (cross compiling)
+if test "x$DED_LD" = "x"; then
+
+DED_LDFLAGS_CONFTEST=
+
+DED_LD_FLAG_RUNTIME_LIBRARY_PATH="-R"
+case $host_os in
+ win32)
+ DED_LD="ld.sh"
+ DED_LDFLAGS="-dll"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH=
+ ;;
+ solaris2*|sysv4*)
+ DED_LDFLAGS="-G"
+ if test X${enable_m64_build} = Xyes; then
+ DED_LDFLAGS="-64 $DED_LDFLAGS"
+ fi
+ ;;
+ aix*|os400*)
+ DED_LDFLAGS="-G -bnoentry -bexpall"
+ ;;
+ freebsd2*)
+ # Non-ELF GNU linker
+ DED_LDFLAGS="-Bshareable"
+ ;;
+ darwin*)
+ # Mach-O linker: a shared lib and a loadable object file is not the same thing.
+
+ if test "X${ERL_DED_FLAT_BUNDLE}" = "Xtrue"; then
+ # EI sets this variable when building its .so file as beam.smp
+ # has not been built yet and any ei lib will not
+ # link to beam.smp anyways
+ DED_LDFLAGS="-bundle -flat_namespace -undefined suppress"
+ else
+ # Cannot use flat namespaces for drivers/nifs as that may cause
+ # symbols to collide during loading
+ DED_LDFLAGS="-bundle -bundle_loader ${ERL_TOP}/bin/$host/beam.smp"
+ fi
+ # DED_LDFLAGS_CONFTEST is for use in configure tests only. We
+ # cannot use DED_LDFLAGS in configure tests since beam.smp has not
+ # been built yet...
+ DED_LDFLAGS_CONFTEST="-bundle"
+ if test X${enable_m64_build} = Xyes; then
+ DED_LDFLAGS="-m64 $DED_LDFLAGS"
+ else
+ if test X${enable_m32_build} = Xyes; then
+ DED_LDFLAGS="-m32 $DED_LDFLAGS"
+ else
+ AC_CHECK_SIZEOF(void *)
+ case "$ac_cv_sizeof_void_p" in
+ 8)
+ DED_LDFLAGS="-m64 $DED_LDFLAGS";;
+ *)
+ ;;
+ esac
+ fi
+ fi
+ DED_LD="$CC"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
+ ;;
+ linux*)
+ DED_LD="$CC"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
+ DED_LDFLAGS="-shared -Wl,-Bsymbolic"
+ if test X${enable_m64_build} = Xyes; then
+ DED_LDFLAGS="-m64 $DED_LDFLAGS"
+ fi;
+ if test X${enable_m32_build} = Xyes; then
+ DED_LDFLAGS="-m32 $DED_LDFLAGS"
+ fi
+ ;;
+ freebsd*)
+ DED_LD="$CC"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
+ DED_LDFLAGS="-shared"
+ if test X${enable_m64_build} = Xyes; then
+ DED_LDFLAGS="-m64 $DED_LDFLAGS"
+ fi;
+ if test X${enable_m32_build} = Xyes; then
+ DED_LDFLAGS="-m32 $DED_LDFLAGS"
+ fi
+ ;;
+ openbsd*)
+ DED_LD="$CC"
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
+ DED_LDFLAGS="-shared"
+ ;;
+ osf*)
+ # NOTE! Whitespace after -rpath is important.
+ DED_LD_FLAG_RUNTIME_LIBRARY_PATH="-rpath "
+ DED_LDFLAGS="-shared -expect_unresolved '*'"
+ ;;
+ *)
+ # assume GNU linker and ELF
+ DED_LDFLAGS="-shared"
+ # GNU linker has no option for 64bit build, should not propagate -m64
+ ;;
+esac
+
+if test "$DED_LD" = "" && test "$USER_LD" != ""; then
+ DED_LD="$USER_LD"
+ DED_LDFLAGS="$USER_LDFLAGS $DED_LDFLAGS"
+fi
+
+DED_LIBS=$LIBS
+
+fi # "x$DED_LD" = "x"
+
+test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
+
+AC_CHECK_TOOL(DED_LD, ld, false)
+test "$DED_LD" != "false" || AC_MSG_ERROR([No linker found])
+
+AC_MSG_CHECKING(for static compiler flags)
+DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
+AC_MSG_RESULT([$DED_STATIC_CFLAGS])
+AC_MSG_CHECKING(for basic compiler flags for loadable drivers)
+DED_BASIC_CFLAGS=$DED_CFLAGS
+AC_MSG_RESULT([$DED_CFLAGS])
+AC_MSG_CHECKING(for compiler flags for loadable drivers)
+DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
+AC_MSG_RESULT([$DED_CFLAGS])
+AC_MSG_CHECKING(for linker for loadable drivers)
+AC_MSG_RESULT([$DED_LD])
+AC_MSG_CHECKING(for linker flags for loadable drivers)
+AC_MSG_RESULT([$DED_LDFLAGS])
+AC_MSG_CHECKING(for 'runtime library path' linker flag)
+if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
+ AC_MSG_RESULT([$DED_LD_FLAG_RUNTIME_LIBRARY_PATH])
+else
+ AC_MSG_RESULT([not found])
+fi
+
+AC_SUBST(DED_CC)
+AC_SUBST(DED_GCC)
+AC_SUBST(DED_EXT)
+AC_SUBST(DED_SYS_INCLUDE)
+AC_SUBST(DED_INCLUDE)
+AC_SUBST(DED_BASIC_CFLAGS)
+AC_SUBST(DED_CFLAGS)
+AC_SUBST(DED_STATIC_CFLAGS)
+AC_SUBST(DED_WARN_FLAGS)
+AC_SUBST(DED_WERRORFLAGS)
+AC_SUBST(DED_LD)
+AC_SUBST(DED_LDFLAGS)
+AC_SUBST(DED_LD_FLAG_RUNTIME_LIBRARY_PATH)
+AC_SUBST(DED_LIBS)
+AC_SUBST(DED_OSTYPE)
+
+])