1dnl
2dnl %CopyrightBegin%
3dnl
4dnl Copyright Ericsson AB 1998-2020. All Rights Reserved.
5dnl
6dnl Licensed under the Apache License, Version 2.0 (the "License");
7dnl you may not use this file except in compliance with the License.
8dnl You may obtain a copy of the License at
9dnl
10dnl     http://www.apache.org/licenses/LICENSE-2.0
11dnl
12dnl Unless required by applicable law or agreed to in writing, software
13dnl distributed under the License is distributed on an "AS IS" BASIS,
14dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15dnl See the License for the specific language governing permissions and
16dnl limitations under the License.
17dnl
18dnl %CopyrightEnd%
19dnl
20
21dnl
22dnl aclocal.m4
23dnl
24dnl Local macros used in configure.in. The Local Macros which
25dnl could/should be part of autoconf are prefixed LM_, macros specific
26dnl to the Erlang system are prefixed ERL_.
27dnl
28
29AC_DEFUN(LM_PRECIOUS_VARS,
30[
31
32dnl ERL_TOP
33AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
34
35dnl Tools
36AC_ARG_VAR(CC, [C compiler])
37AC_ARG_VAR(CFLAGS, [C compiler flags])
38AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
39AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
40AC_ARG_VAR(CPP, [C/C++ preprocessor])
41AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
42AC_ARG_VAR(CXX, [C++ compiler])
43AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
44AC_ARG_VAR(LD, [linker (is often overridden by configure)])
45AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)])
46AC_ARG_VAR(LIBS, [libraries])
47AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
48AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
49AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
50AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
51AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
52AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
53AC_ARG_VAR(RANLIB, [ranlib])
54AC_ARG_VAR(AR, [ar])
55AC_ARG_VAR(GETCONF, [getconf])
56
57dnl Cross system root
58AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
59AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
60
61dnl Cross compilation variables
62AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
63AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
64AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
65AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
66AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
67AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
68AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
69AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
70AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
71AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
72AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
73AC_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)])
74AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
75AC_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)])
76
77])
78
79AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
80[
81erl_xcomp_without_sysroot=no
82if test "$cross_compiling" = "yes"; then
83    test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
84    test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
85else
86    erl_xcomp_sysroot=
87    erl_xcomp_isysroot=
88fi
89])
90
91AC_DEFUN(LM_CHECK_GETCONF,
92[
93if test "$cross_compiling" != "yes"; then
94    AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
95else
96    dnl First check if we got a `<HOST>-getconf' in $PATH
97    host_getconf="$host_alias-getconf"
98    AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
99    if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
100	dnl We should perhaps give up if we have'nt found it by now, but at
101	dnl least in one Tilera MDE `getconf' under sysroot is a bourne
102	dnl shell script which we can use. We try to find `<HOST>-getconf'
103    	dnl or `getconf' under sysconf, but only under sysconf since
104	dnl `getconf' in $PATH is almost guaranteed to be for the build
105	dnl machine.
106	GETCONF=
107	prfx="$erl_xcomp_sysroot"
108        AC_PATH_TOOL([GETCONF], [getconf], [false],
109	             ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
110    fi
111fi
112])
113
114dnl ----------------------------------------------------------------------
115dnl
116dnl LM_WINDOWS_ENVIRONMENT
117dnl
118dnl
119dnl Tries to determine the windows build environment, i.e.
120dnl MIXED_VC or MIXED_MINGW
121dnl
122
123AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
124[
125
126if test "X$windows_environment_" != "Xchecked"; then
127windows_environment_=checked
128MIXED_CYGWIN=no
129MIXED_MSYS=no
130MIXED_VSL=no
131
132dnl MIXED_VC is Microsoft Visual C++ used as standard compiler
133MIXED_VC=no
134dnl MIXED_MINGW is mingw(32|64) used as standard compiler
135MIXED_MINGW=no
136
137AC_MSG_CHECKING(for mixed mingw-gcc and native VC++ environment)
138if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
139	if test -x /usr/bin/msys-?.0.dll; then
140	        CFLAGS="$CFLAGS -O2"
141		MIXED_MSYS=yes
142		AC_MSG_RESULT([MSYS and VC])
143		MIXED_VC=yes
144		CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
145	elif test -x /usr/bin/cygpath; then
146		CFLAGS="$CFLAGS -O2"
147		MIXED_CYGWIN=yes
148		AC_MSG_RESULT([Cygwin and VC])
149		MIXED_VC=yes
150		CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
151        elif test -x /bin/wslpath; then
152		CFLAGS="$CFLAGS -O2"
153		MIXED_WSL=yes
154		AC_MSG_RESULT([WSL and VC])
155		MIXED_VC=yes
156		CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
157	else
158		AC_MSG_RESULT([undeterminable])
159		AC_MSG_ERROR(Seems to be mixed windows but not within any known env, cannot handle this!)
160	fi
161else
162	AC_MSG_RESULT([no])
163fi
164
165AC_SUBST(MIXED_VC)
166
167if test "x$MIXED_MSYS" != "xyes"; then
168   AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
169   if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
170	if test -x /usr/bin/cygpath; then
171		CFLAGS="$CFLAGS -O2"
172		AC_MSG_RESULT([yes])
173		MIXED_MINGW=yes
174		CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
175	else
176		AC_MSG_RESULT([undeterminable])
177		AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
178	fi
179    else
180	AC_MSG_RESULT([no])
181    fi
182else
183   AC_MSG_CHECKING(for mixed MSYS and native MinGW environment)
184   if test "x$GCC" = x"yes"; then
185    	if test -x /usr/bin/msys-=.0.dll; then
186		CFLAGS="$CFLAGS -O2"
187		AC_MSG_RESULT([yes])
188		MIXED_MINGW=yes
189		CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
190	else
191		AC_MSG_RESULT([undeterminable])
192		AC_MSG_ERROR(Seems to be mixed windows but not with msys, cannot handle this!)
193	fi
194    else
195	AC_MSG_RESULT([no])
196    fi
197fi
198AC_SUBST(MIXED_MINGW)
199
200AC_MSG_CHECKING(if we mix cygwin with any native compiler)
201if test "X$MIXED_CYGWIN" = "Xyes"; then
202	AC_MSG_RESULT([yes])
203else
204	AC_MSG_RESULT([no])
205fi
206
207AC_MSG_CHECKING(if we mix msys with another native compiler)
208if test "X$MIXED_MSYS" = "Xyes" ; then
209	AC_MSG_RESULT([yes])
210else
211	AC_MSG_RESULT([no])
212fi
213
214AC_MSG_CHECKING(if we mix WSL with another native compiler)
215if test "X$MIXED_WSL" = "Xyes" ; then
216	AC_MSG_RESULT([yes])
217else
218	AC_MSG_RESULT([no])
219fi
220
221fi
222])
223
224dnl ----------------------------------------------------------------------
225dnl
226dnl LM_FIND_EMU_CC
227dnl
228dnl
229dnl Tries fairly hard to find a C compiler that can handle jump tables.
230dnl Defines the @EMU_CC@ variable for the makefiles and
231dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
232dnl
233
234AC_DEFUN(LM_FIND_EMU_CC,
235	[AC_CACHE_CHECK(for a compiler that handles jumptables,
236			ac_cv_prog_emu_cc,
237			[
238AC_TRY_COMPILE([],[
239#if defined(__clang_major__) && __clang_major__ >= 3
240    /* clang 3.x or later is fine */
241#elif defined(__llvm__)
242#error "this version of llvm is unable to correctly compile beam_emu.c"
243#endif
244    __label__ lbl1;
245    __label__ lbl2;
246    extern int magic(void);
247    int x = magic();
248    static void *jtab[2];
249
250    jtab[0] = &&lbl1;
251    jtab[1] = &&lbl2;
252    goto *jtab[x];
253lbl1:
254    return 1;
255lbl2:
256    return 2;
257],ac_cv_prog_emu_cc="$CC",ac_cv_prog_emu_cc=no)
258
259if test "$ac_cv_prog_emu_cc" = no; then
260	for ac_progname in emu_cc.sh gcc-4.2 gcc; do
261  		IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
262  		ac_dummy="$PATH"
263  		for ac_dir in $ac_dummy; do
264    			test -z "$ac_dir" && ac_dir=.
265    			if test -f "$ac_dir/$ac_progname"; then
266      				ac_cv_prog_emu_cc="$ac_dir/$ac_progname"
267      				break
268    			fi
269  		done
270  		IFS="$ac_save_ifs"
271		if test "$ac_cv_prog_emu_cc" != no; then
272			break
273		fi
274	done
275fi
276
277if test "$ac_cv_prog_emu_cc" != no; then
278	save_CC="$CC"
279	save_CFLAGS=$CFLAGS
280	save_CPPFLAGS=$CPPFLAGS
281	CC="$ac_cv_prog_emu_cc"
282	CFLAGS=""
283	CPPFLAGS=""
284	AC_TRY_COMPILE([],[
285#if defined(__clang_major__) && __clang_major__ >= 3
286    /* clang 3.x or later is fine */
287#elif defined(__llvm__)
288#error "this version of llvm is unable to correctly compile beam_emu.c"
289#endif
290    	__label__ lbl1;
291    	__label__ lbl2;
292	extern int magic(void);
293    	int x = magic();
294    	static void *jtab[2];
295
296    	jtab[0] = &&lbl1;
297    	jtab[1] = &&lbl2;
298    	goto *jtab[x];
299	lbl1:
300    	return 1;
301	lbl2:
302    	return 2;
303	],ac_cv_prog_emu_cc="$CC",ac_cv_prog_emu_cc=no)
304	CC=$save_CC
305	CFLAGS=$save_CFLAGS
306	CPPFLAGS=$save_CPPFLAGS
307fi
308])
309if test "$ac_cv_prog_emu_cc" = no; then
310	AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
311	EMU_CC="$CC"
312else
313	EMU_CC="$ac_cv_prog_emu_cc"
314fi
315AC_SUBST(EMU_CC)
316])
317
318
319
320dnl ----------------------------------------------------------------------
321dnl
322dnl LM_PROG_INSTALL_DIR
323dnl
324dnl This macro may be used by any OTP application.
325dnl
326dnl Figure out how to create directories with parents.
327dnl (In my opinion INSTALL_DIR is a bad name, MKSUBDIRS or something is better)
328dnl
329dnl We prefer 'install -d', but use 'mkdir -p' if it exists.
330dnl If none of these methods works, we give up.
331dnl
332
333
334AC_DEFUN(LM_PROG_INSTALL_DIR,
335[AC_CACHE_CHECK(how to create a directory including parents,
336ac_cv_prog_mkdir_p,
337[
338temp_name_base=config.$$
339temp_name=$temp_name_base/x/y/z
340$INSTALL -d $temp_name >/dev/null 2>&1
341ac_cv_prog_mkdir_p=none
342if test -d $temp_name; then
343        ac_cv_prog_mkdir_p="$INSTALL -d"
344else
345        mkdir -p $temp_name >/dev/null 2>&1
346        if test -d $temp_name; then
347                ac_cv_prog_mkdir_p="mkdir -p"
348        fi
349fi
350rm -fr $temp_name_base
351])
352
353case "${ac_cv_prog_mkdir_p}" in
354  none) AC_MSG_ERROR(don't know how create directories with parents) ;;
355  *)    INSTALL_DIR="$ac_cv_prog_mkdir_p" AC_SUBST(INSTALL_DIR)     ;;
356esac
357])
358
359
360dnl ----------------------------------------------------------------------
361dnl
362dnl LM_PROG_PERL5
363dnl
364dnl Try to find perl version 5. If found set PERL to the absolute path
365dnl of the program, if not found set PERL to false.
366dnl
367AC_DEFUN(LM_PROG_PERL5,
368[AC_PATH_PROGS(PERL, perl5 perl, false,
369   /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
370if test "$PERL" = "false"; then
371  ac_cv_path_PERL=false
372  PERL=false
373dnl  AC_MSG_WARN(perl version 5 not found)
374fi
375])dnl
376
377
378dnl ----------------------------------------------------------------------
379dnl
380dnl LM_DECL_SO_BSDCOMPAT
381dnl
382dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
383dnl
384AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
385[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
386AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;],
387               ac_cv_decl_so_bsdcompat=yes,
388               ac_cv_decl_so_bsdcompat=no))
389
390case "${ac_cv_decl_so_bsdcompat}" in
391  "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
392		[Define if you have SO_BSDCOMPAT flag on sockets]) ;;
393  * ) ;;
394esac
395])
396
397
398dnl ----------------------------------------------------------------------
399dnl
400dnl LM_DECL_INADDR_LOOPBACK
401dnl
402dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
403dnl
404
405AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
406[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
407 ac_cv_decl_inaddr_loopback,
408[AC_TRY_COMPILE([#include <sys/types.h>
409#include <netinet/in.h>], [int i = INADDR_LOOPBACK;],
410ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no)
411])
412
413if test ${ac_cv_decl_inaddr_loopback} = no; then
414  AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
415                   ac_cv_decl_inaddr_loopback_rpc,
416                   AC_TRY_COMPILE([#include <rpc/types.h>],
417                                   [int i = INADDR_LOOPBACK;],
418                                   ac_cv_decl_inaddr_loopback_rpc=yes,
419                                   ac_cv_decl_inaddr_loopback_rpc=no))
420
421   case "${ac_cv_decl_inaddr_loopback_rpc}" in
422     "yes" )
423        AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
424		[Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
425      * )
426  	AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
427                   ac_cv_decl_inaddr_loopback_winsock2,
428                   AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN
429				   #include <winsock2.h>],
430                                   [int i = INADDR_LOOPBACK;],
431                                   ac_cv_decl_inaddr_loopback_winsock2=yes,
432                                   ac_cv_decl_inaddr_loopback_winsock2=no))
433	case "${ac_cv_decl_inaddr_loopback_winsock2}" in
434     		"yes" )
435			AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
436				[Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
437		* )
438			# couldn't find it anywhere
439        		AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
440				[Define if you don't have a definition of INADDR_LOOPBACK]) ;;
441	esac;;
442   esac
443fi
444])
445
446
447dnl ----------------------------------------------------------------------
448dnl
449dnl LM_STRUCT_SOCKADDR_SA_LEN
450dnl
451dnl Check if the sockaddr structure has the field sa_len
452dnl
453
454AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
455[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
456                ac_cv_struct_sockaddr_sa_len,
457AC_TRY_COMPILE([#include <sys/types.h>
458#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;],
459  ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no))
460
461dnl FIXME convbreak
462case ${ac_cv_struct_sockaddr_sa_len} in
463  "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
464  *) ;;
465esac
466])
467
468dnl ----------------------------------------------------------------------
469dnl
470dnl LM_SYS_IPV6
471dnl
472dnl Check for ipv6 support and what the in6_addr structure is called.
473dnl (early linux used in_addr6 insted of in6_addr)
474dnl
475
476AC_DEFUN(LM_SYS_IPV6,
477[AC_MSG_CHECKING(for IP version 6 support)
478AC_CACHE_VAL(ac_cv_sys_ipv6_support,
479[ok_so_far=yes
480 AC_TRY_COMPILE([#include <sys/types.h>
481#ifdef __WIN32__
482#include <winsock2.h>
483#include <ws2tcpip.h>
484#else
485#include <netinet/in.h>
486#endif],
487   [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
488
489if test $ok_so_far = yes; then
490  ac_cv_sys_ipv6_support=yes
491else
492  AC_TRY_COMPILE([#include <sys/types.h>
493#ifdef __WIN32__
494#include <winsock2.h>
495#include <ws2tcpip.h>
496#else
497#include <netinet/in.h>
498#endif],
499    [struct in_addr6 a6; struct sockaddr_in6 s6;],
500    ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
501fi
502])dnl
503
504dnl
505dnl Have to use old style AC_DEFINE due to BC with old autoconf.
506dnl
507
508case ${ac_cv_sys_ipv6_support} in
509  yes)
510    AC_MSG_RESULT(yes)
511    AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
512    ;;
513  in_addr6)
514    AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
515    AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
516    AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
517    ;;
518  *)
519    AC_MSG_RESULT(no)
520    ;;
521esac
522])
523
524
525dnl ----------------------------------------------------------------------
526dnl
527dnl LM_SYS_MULTICAST
528dnl
529dnl Check for multicast support. Only checks for multicast options in
530dnl setsockopt(), no check is performed that multicasting actually works.
531dnl If options are found defines HAVE_MULTICAST_SUPPORT
532dnl
533
534AC_DEFUN(LM_SYS_MULTICAST,
535[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
536[AC_EGREP_CPP(^yes$,
537[#include <sys/types.h>
538#include <sys/socket.h>
539#include <netinet/in.h>
540#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
541yes
542#endif
543], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
544if test $ac_cv_sys_multicast_support = yes; then
545  AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
546	[Define if setsockopt() accepts multicast options])
547fi
548])dnl
549
550
551dnl ----------------------------------------------------------------------
552dnl
553dnl LM_DECL_SYS_ERRLIST
554dnl
555dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
556dnl in a system header file, stdio.h or errno.h.
557dnl
558
559AC_DEFUN(LM_DECL_SYS_ERRLIST,
560[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
561  ac_cv_decl_sys_errlist,
562[AC_TRY_COMPILE([#include <stdio.h>
563#include <errno.h>], [char *msg = *(sys_errlist + 1);],
564  ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)])
565if test $ac_cv_decl_sys_errlist = yes; then
566  AC_DEFINE(SYS_ERRLIST_DECLARED,[],
567	[define if the variable sys_errlist is declared in a system header file])
568fi
569])
570
571
572dnl ----------------------------------------------------------------------
573dnl
574dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
575dnl                     [, action-if-found [, action-if-not-found]]] )
576dnl
577dnl Checks if the declaration "declaration" of "funname" conflicts
578dnl with the header files idea of how the function should be
579dnl declared. It is useful on systems which lack prototypes and you
580dnl need to provide your own (e.g. when you want to take the address
581dnl of a function). The 4'th argument is expanded if conflicting,
582dnl the 5'th argument otherwise
583dnl
584dnl
585
586AC_DEFUN(LM_CHECK_FUNC_DECL,
587[AC_MSG_CHECKING([for conflicting declaration of $1])
588AC_CACHE_VAL(ac_cv_func_decl_$1,
589[AC_TRY_COMPILE([#include <stdio.h>
590$3],[$2
591char *c = (char *)$1;
592], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
593if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
594  AC_MSG_RESULT(yes)
595  ifelse([$4], , :, [$4])
596else
597  AC_MSG_RESULT(no)
598ifelse([$5], , , [$5
599])dnl
600fi
601])
602
603dnl ----------------------------------------------------------------------
604dnl
605dnl AC_DOUBLE_MIDDLE_ENDIAN
606dnl
607dnl Checks whether doubles are represented in "middle-endian" format.
608dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
609dnl as well as DOUBLE_MIDDLE_ENDIAN.
610dnl
611dnl
612
613AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
614[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
615[# It does not; compile a test program.
616AC_RUN_IFELSE(
617[AC_LANG_SOURCE([[#include <stdlib.h>
618
619int
620main(void)
621{
622  int i = 0;
623  int zero = 0;
624  int bigendian;
625  int zero_index = 0;
626
627  union
628  {
629    long int l;
630    char c[sizeof (long int)];
631  } u;
632
633  /* we'll use the one with 32-bit words */
634  union
635  {
636    double d;
637    unsigned int c[2];
638  } vint;
639
640  union
641  {
642    double d;
643    unsigned long c[2];
644  } vlong;
645
646  union
647  {
648    double d;
649    unsigned short c[2];
650  } vshort;
651
652
653  /* Are we little or big endian?  From Harbison&Steele.  */
654  u.l = 1;
655  bigendian = (u.c[sizeof (long int) - 1] == 1);
656
657  zero_index = bigendian ? 1 : 0;
658
659  vint.d = 1.0;
660  vlong.d = 1.0;
661  vshort.d = 1.0;
662
663  if (sizeof(unsigned int) == 4)
664    {
665      if (vint.c[zero_index] != 0)
666	zero = 1;
667    }
668  else if (sizeof(unsigned long) == 4)
669    {
670      if (vlong.c[zero_index] != 0)
671	zero = 1;
672    }
673  else if (sizeof(unsigned short) == 4)
674    {
675      if (vshort.c[zero_index] != 0)
676	zero = 1;
677    }
678
679  exit (zero);
680}
681]])],
682	      [ac_cv_c_double_middle_endian=no],
683	      [ac_cv_c_double_middle_endian=yes],
684	      [ac_cv_c_double_middle=unknown])])
685case $ac_cv_c_double_middle_endian in
686  yes)
687    m4_default([$1],
688      [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
689	[Define to 1 if your processor stores the words in a double in
690	 middle-endian format (like some ARMs).])]) ;;
691  no)
692    $2 ;;
693  *)
694    m4_default([$3],
695      [AC_MSG_WARN([unknown double endianness
696presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
697esac
698])# AC_C_DOUBLE_MIDDLE_ENDIAN
699
700
701AC_DEFUN(ERL_MONOTONIC_CLOCK,
702[
703  if test "$3" = "yes"; then
704     default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_BOOTTIME CLOCK_MONOTONIC"
705     low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST"
706     high_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_PRECISE"
707  else
708     default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_UPTIME CLOCK_MONOTONIC"
709     low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_UPTIME_FAST"
710     high_resolution_clock_gettime_monotonic="CLOCK_UPTIME_PRECISE"
711  fi
712
713  case "$1" in
714    high_resolution)
715	check_msg="high resolution "
716	prefer_resolution_clock_gettime_monotonic="$high_resolution_clock_gettime_monotonic"
717	;;
718    low_resolution)
719	check_msg="low resolution "
720	prefer_resolution_clock_gettime_monotonic="$low_resolution_clock_gettime_monotonic"
721	;;
722    custom_resolution)
723	check_msg="custom resolution "
724	prefer_resolution_clock_gettime_monotonic="$2"
725	;;
726    *)
727	check_msg="custom "
728	prefer_resolution_clock_gettime_monotonic="$2"
729	;;
730  esac
731
732  clock_gettime_lib=""
733  AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"])
734
735  save_LIBS="$LIBS"
736  LIBS="$LIBS $clock_gettime_lib"
737
738  if test "$LD_MAY_BE_WEAK" != "no"; then
739     trust_test="#error May not be there due to weak linking"
740  else
741     trust_test=""
742  fi
743
744  AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC_RAW, _)], erl_cv_clock_gettime_monotonic_raw,
745  [
746       AC_TRY_LINK([
747#include <time.h>
748$trust_test
749		      ],
750		      [
751    struct timespec ts;
752    long long result;
753    clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
754    result = ((long long) ts.tv_sec) * 1000000000LL +
755    ((long long) ts.tv_nsec);
756		      ],
757		      erl_cv_clock_gettime_monotonic_raw=yes,
758		      erl_cv_clock_gettime_monotonic_raw=no)
759  ])
760
761  AC_CACHE_CHECK([for clock_gettime() with ${check_msg}monotonic clock type], erl_cv_clock_gettime_monotonic_$1,
762  [
763     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
764       AC_TRY_LINK([
765#include <time.h>
766$trust_test
767		      ],
768		      [
769    struct timespec ts;
770    long long result;
771    clock_gettime($clock_type,&ts);
772    result = ((long long) ts.tv_sec) * 1000000000LL +
773    ((long long) ts.tv_nsec);
774		      ],
775		      erl_cv_clock_gettime_monotonic_$1=$clock_type,
776		      erl_cv_clock_gettime_monotonic_$1=no)
777       test $erl_cv_clock_gettime_monotonic_$1 = no || break
778     done
779  ])
780
781  LIBS="$save_LIBS"
782
783  if test "$LD_MAY_BE_WEAK" != "no"; then
784    AC_CHECK_FUNCS([clock_get_attributes gethrtime])
785  else
786    AC_CHECK_FUNCS([clock_getres clock_get_attributes gethrtime])
787  fi
788
789
790  AC_CACHE_CHECK([for mach clock_get_time() with monotonic clock type], erl_cv_mach_clock_get_time_monotonic,
791  [
792     AC_TRY_COMPILE([
793#include <mach/clock.h>
794#include <mach/mach.h>
795			],
796	 		[
797    kern_return_t res;
798    clock_serv_t clk_srv;
799    mach_timespec_t time_spec;
800
801    host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clk_srv);
802    res = clock_get_time(clk_srv, &time_spec);
803    mach_port_deallocate(mach_task_self(), clk_srv);
804    			],
805    			erl_cv_mach_clock_get_time_monotonic=yes,
806			erl_cv_mach_clock_get_time_monotonic=no)
807  ])
808
809  erl_corrected_monotonic_clock=no
810  case $erl_cv_clock_gettime_monotonic_$1-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
811    *-*-*-win32)
812      erl_monotonic_clock_func=WindowsAPI
813      ;;
814    CLOCK_*-*-*-linux*)
815      case $erl_cv_clock_gettime_monotonic_$1-$erl_cv_clock_gettime_monotonic_raw in
816        CLOCK_BOOTTIME-yes|CLOCK_MONOTONIC-yes)
817	  erl_corrected_monotonic_clock=yes
818	  ;;
819	*)
820	  # We don't trust CLOCK_MONOTONIC to be NTP
821	  # adjusted on linux systems that do not have
822	  # CLOCK_MONOTONIC_RAW (although it seems to
823	  # be...)
824	  ;;
825      esac
826      erl_monotonic_clock_func=clock_gettime
827      ;;
828    no-no-no-linux*)
829      erl_monotonic_clock_func=times
830      ;;
831    CLOCK_*-*-*-*)
832      erl_monotonic_clock_func=clock_gettime
833      ;;
834    no-yes-*-*)
835      erl_monotonic_clock_func=gethrtime
836      ;;
837    no-no-yes-*)
838      erl_monotonic_clock_func=mach_clock_get_time
839      ;;
840    no-no-no-*)
841      erl_monotonic_clock_func=none
842      ;;
843  esac
844
845  erl_monotonic_clock_low_resolution=no
846  erl_monotonic_clock_lib=
847  erl_monotonic_clock_id=
848  case $erl_monotonic_clock_func in
849    clock_gettime)
850      erl_monotonic_clock_id=$erl_cv_clock_gettime_monotonic_$1
851      for low_res_id in $low_resolution_clock_gettime_monotonic; do
852      	  if test $erl_monotonic_clock_id = $low_res_id; then
853	    erl_monotonic_clock_low_resolution=yes
854	    break
855	  fi
856      done
857      erl_monotonic_clock_lib=$clock_gettime_lib
858      ;;
859    mach_clock_get_time)
860      erl_monotonic_clock_id=SYSTEM_CLOCK
861      ;;
862    times)
863      erl_monotonic_clock_low_resolution=yes
864      ;;
865    *)
866      ;;
867  esac
868
869])
870
871AC_DEFUN(ERL_WALL_CLOCK,
872[
873  default_resolution_clock_gettime_wall="CLOCK_REALTIME"
874  low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
875  high_resolution_clock_gettime_wall="CLOCK_REALTIME_PRECISE"
876
877  case "$1" in
878    high_resolution)
879	check_msg="high resolution "
880	prefer_resolution_clock_gettime_wall="$high_resolution_clock_gettime_wall"
881	;;
882    low_resolution)
883	check_msg="low resolution "
884	prefer_resolution_clock_gettime_wall="$low_resolution_clock_gettime_wall"
885	;;
886    custom_resolution)
887	check_msg="custom resolution "
888	prefer_resolution_clock_gettime_wall="$2"
889	;;
890    *)
891	check_msg=""
892	prefer_resolution_clock_gettime_wall=
893	;;
894  esac
895
896  clock_gettime_lib=""
897  AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"])
898
899  save_LIBS="$LIBS"
900  LIBS="$LIBS $clock_gettime_lib"
901
902  if test "$LD_MAY_BE_WEAK" != "no"; then
903     trust_test="#error May not be there due to weak linking"
904  else
905     trust_test=""
906  fi
907
908  AC_CACHE_CHECK([for clock_gettime() with ${check_msg}wall clock type], erl_cv_clock_gettime_wall_$1,
909  [
910     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
911       AC_TRY_LINK([
912#include <time.h>
913$trust_test
914		      ],
915		      [
916    struct timespec ts;
917    long long result;
918    clock_gettime($clock_type,&ts);
919    result = ((long long) ts.tv_sec) * 1000000000LL +
920    ((long long) ts.tv_nsec);
921		      ],
922		      erl_cv_clock_gettime_wall_$1=$clock_type,
923		      erl_cv_clock_gettime_wall_$1=no)
924       test $erl_cv_clock_gettime_wall_$1 = no || break
925     done
926  ])
927
928  LIBS="$save_LIBS"
929
930  if test "$LD_MAY_BE_WEAK" != "no"; then
931     check_for_clock_getres=
932  else
933     check_for_clock_getres=clock_getres
934  fi
935
936  AC_CHECK_FUNCS([$check_for_clock_getres clock_get_attributes gettimeofday])
937
938  AC_CACHE_CHECK([for mach clock_get_time() with wall clock type], erl_cv_mach_clock_get_time_wall,
939  [
940     AC_TRY_COMPILE([
941#include <mach/clock.h>
942#include <mach/mach.h>
943			],
944	 		[
945    kern_return_t res;
946    clock_serv_t clk_srv;
947    mach_timespec_t time_spec;
948
949    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk_srv);
950    res = clock_get_time(clk_srv, &time_spec);
951    mach_port_deallocate(mach_task_self(), clk_srv);
952    			],
953    			erl_cv_mach_clock_get_time_wall=yes,
954			erl_cv_mach_clock_get_time_wall=no)
955  ])
956
957  erl_wall_clock_lib=
958  erl_wall_clock_low_resolution=no
959  erl_wall_clock_id=
960  case $1-$erl_cv_clock_gettime_wall_$1-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in
961    *-*-*-*-win32)
962      erl_wall_clock_func=WindowsAPI
963      erl_wall_clock_low_resolution=yes
964      ;;
965    high_resolution-no-yes-*-*)
966      erl_wall_clock_func=mach_clock_get_time
967      erl_wall_clock_id=CALENDAR_CLOCK
968      ;;
969    *-CLOCK_*-*-*-*)
970      erl_wall_clock_func=clock_gettime
971      erl_wall_clock_lib=$clock_gettime_lib
972      erl_wall_clock_id=$erl_cv_clock_gettime_wall_$1
973      for low_res_id in $low_resolution_clock_gettime_wall; do
974      	  if test $erl_wall_clock_id = $low_res_id; then
975	    erl_wall_clock_low_resolution=yes
976	    break
977	  fi
978      done
979      ;;
980    *-no-*-yes-*)
981      erl_wall_clock_func=gettimeofday
982      ;;
983    *)
984      erl_wall_clock_func=none
985      ;;
986  esac
987])
988
989dnl ----------------------------------------------------------------------
990dnl
991dnl LM_CHECK_THR_LIB
992dnl
993dnl This macro may be used by any OTP application.
994dnl
995dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
996dnl checks for some pthread headers which will appear in DEFS or config.h.
997dnl
998
999AC_DEFUN(LM_CHECK_THR_LIB,
1000[
1001
1002NEED_NPTL_PTHREAD_H=no
1003
1004dnl win32?
1005AC_MSG_CHECKING([for native win32 threads])
1006if test "X$host_os" = "Xwin32"; then
1007    AC_MSG_RESULT(yes)
1008    THR_DEFS="-DWIN32_THREADS"
1009    THR_LIBS=
1010    THR_LIB_NAME=win32_threads
1011    THR_LIB_TYPE=win32_threads
1012else
1013    AC_MSG_RESULT(no)
1014    THR_DEFS=
1015    THR_LIBS=
1016    THR_LIB_NAME=
1017    THR_LIB_TYPE=posix_unknown
1018
1019dnl Try to find POSIX threads
1020
1021dnl The usual pthread lib...
1022    AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
1023
1024dnl Very old versions of FreeBSD have pthreads in special c library, c_r...
1025    if test "x$THR_LIBS" = "x"; then
1026	AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r")
1027    fi
1028
1029dnl QNX has pthreads in standard C library
1030    if test "x$THR_LIBS" = "x"; then
1031	AC_CHECK_FUNC(pthread_create, THR_LIBS="none_needed")
1032    fi
1033
1034dnl On ofs1 the '-pthread' switch should be used
1035    if test "x$THR_LIBS" = "x"; then
1036	AC_MSG_CHECKING([if the '-pthread' switch can be used])
1037	saved_cflags=$CFLAGS
1038	CFLAGS="$CFLAGS -pthread"
1039	AC_TRY_LINK([#include <pthread.h>],
1040		    pthread_create((void*)0,(void*)0,(void*)0,(void*)0);,
1041		    [THR_DEFS="-pthread"
1042		     THR_LIBS="-pthread"])
1043	CFLAGS=$saved_cflags
1044	if test "x$THR_LIBS" != "x"; then
1045	    AC_MSG_RESULT(yes)
1046	else
1047	    AC_MSG_RESULT(no)
1048	fi
1049    fi
1050
1051    if test "x$THR_LIBS" != "x"; then
1052	THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
1053	THR_LIB_NAME=pthread
1054	if test "x$THR_LIBS" = "xnone_needed"; then
1055	    THR_LIBS=
1056	fi
1057	case $host_os in
1058	    solaris*)
1059		THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
1060	    linux*)
1061		THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
1062
1063		LM_CHECK_GETCONF
1064		AC_MSG_CHECKING(for Native POSIX Thread Library)
1065		libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
1066		if test $? -eq 0; then
1067		    case "$libpthr_vsn" in
1068			*nptl*|*NPTL*) nptl=yes;;
1069			*) nptl=no;;
1070		    esac
1071		elif test "$cross_compiling" = "yes"; then
1072		    case "$erl_xcomp_linux_nptl" in
1073			"") nptl=cross;;
1074			yes|no) nptl=$erl_xcomp_linux_nptl;;
1075			*) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
1076		    esac
1077		else
1078		    nptl=no
1079		fi
1080		AC_MSG_RESULT($nptl)
1081		if test $nptl = cross; then
1082		    nptl=yes
1083		    AC_MSG_WARN([result yes guessed because of cross compilation])
1084		fi
1085		if test $nptl = yes; then
1086		    THR_LIB_TYPE=posix_nptl
1087		    need_nptl_incldir=no
1088		    AC_CHECK_HEADER(nptl/pthread.h,
1089				    [need_nptl_incldir=yes
1090				     NEED_NPTL_PTHREAD_H=yes])
1091		    if test $need_nptl_incldir = yes; then
1092			# Ahh...
1093			nptl_path="$C_INCLUDE_PATH:$CPATH"
1094			if test X$cross_compiling != Xyes; then
1095			    nptl_path="$nptl_path:/usr/local/include:/usr/include"
1096			else
1097			    IROOT="$erl_xcomp_isysroot"
1098			    test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
1099			    test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
1100			    nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
1101			fi
1102			nptl_ws_path=
1103			save_ifs="$IFS"; IFS=":"
1104			for dir in $nptl_path; do
1105			    if test "x$dir" != "x"; then
1106				nptl_ws_path="$nptl_ws_path $dir"
1107			    fi
1108			done
1109			IFS=$save_ifs
1110			nptl_incldir=
1111			for dir in $nptl_ws_path; do
1112		            AC_CHECK_HEADER($dir/nptl/pthread.h,
1113					    nptl_incldir=$dir/nptl)
1114			    if test "x$nptl_incldir" != "x"; then
1115				THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
1116				break
1117			    fi
1118			done
1119			if test "x$nptl_incldir" = "x"; then
1120			    AC_MSG_ERROR(Failed to locate nptl system include directory)
1121			fi
1122		    fi
1123		fi
1124		;;
1125	    *) ;;
1126	esac
1127
1128	dnl We sometimes need THR_DEFS in order to find certain headers
1129	dnl (at least for pthread.h on osf1).
1130	saved_cppflags=$CPPFLAGS
1131	CPPFLAGS="$CPPFLAGS $THR_DEFS"
1132
1133	dnl
1134	dnl Check for headers
1135	dnl
1136
1137	AC_CHECK_HEADER(pthread.h,
1138			AC_DEFINE(HAVE_PTHREAD_H, 1, \
1139[Define if you have the <pthread.h> header file.]))
1140
1141	dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
1142	AC_CHECK_HEADER(pthread/mit/pthread.h, \
1143			AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
1144[Define if the pthread.h header file is in pthread/mit directory.]))
1145
1146	dnl restore CPPFLAGS
1147	CPPFLAGS=$saved_cppflags
1148
1149    fi
1150fi
1151
1152])
1153
1154AC_DEFUN(ERL_INTERNAL_LIBS,
1155[
1156
1157ERTS_INTERNAL_X_LIBS=
1158
1159AC_CHECK_LIB(kstat, kstat_open,
1160[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
1161ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
1162
1163AC_SUBST(ERTS_INTERNAL_X_LIBS)
1164
1165])
1166
1167AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OP__,
1168[
1169    # $1 - atomic_op
1170
1171    for atomic_bit_size in 32 64 128; do
1172	case $atomic_bit_size in
1173	    32) gcc_atomic_type="$gcc_atomic_type32";;
1174	    64) gcc_atomic_type="$gcc_atomic_type64";;
1175	    128) gcc_atomic_type="$gcc_atomic_type128";;
1176	esac
1177	gcc_atomic_lockfree="int x[[(2*__atomic_always_lock_free(sizeof($gcc_atomic_type), 0))-1]]"
1178	case $1 in
1179	    __sync_add_and_fetch | __sync_fetch_and_and | __sync_fetch_and_or)
1180		atomic_call="volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, ($gcc_atomic_type) 0);"
1181		;;
1182	    __sync_val_compare_and_swap)
1183		atomic_call="volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, ($gcc_atomic_type) 0, ($gcc_atomic_type) 0);"
1184		;;
1185	    __atomic_store_n)
1186		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);"
1187		;;
1188	    __atomic_load_n)
1189		atomic_call="$gcc_atomic_lockfree; volatile $gcc_atomic_type var; $gcc_atomic_type res = $1(&var, __ATOMIC_RELAXED); res = $1(&var, __ATOMIC_ACQUIRE);"
1190		;;
1191	    __atomic_add_fetch| __atomic_fetch_and | __atomic_fetch_or)
1192		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);"
1193		;;
1194	    __atomic_compare_exchange_n)
1195		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);"
1196		;;
1197	    *)
1198		AC_MSG_ERROR([Internal error: missing implementation for $1])
1199		;;
1200	esac
1201	eval atomic${atomic_bit_size}_call=\"$atomic_call\"
1202    done
1203
1204    AC_CACHE_CHECK([for 32-bit $1()], ethr_cv_32bit_$1,
1205		   [
1206		       ethr_cv_32bit_$1=no
1207		       AC_TRY_LINK([], [$atomic32_call], [ethr_cv_32bit_$1=yes])
1208		   ])
1209    AC_CACHE_CHECK([for 64-bit $1()], ethr_cv_64bit_$1,
1210		   [
1211		       ethr_cv_64bit_$1=no
1212		       AC_TRY_LINK([], [$atomic64_call], [ethr_cv_64bit_$1=yes])
1213		   ])
1214    AC_CACHE_CHECK([for 128-bit $1()], ethr_cv_128bit_$1,
1215		   [
1216		       ethr_cv_128bit_$1=no
1217		       AC_TRY_LINK([], [$atomic128_call], [ethr_cv_128bit_$1=yes])
1218		   ])
1219
1220	case $ethr_cv_128bit_$1-$ethr_cv_64bit_$1-$ethr_cv_32bit_$1 in
1221	    no-no-no)
1222		have_atomic_ops=0;;
1223	    no-no-yes)
1224		have_atomic_ops=4;;
1225	    no-yes-no)
1226		have_atomic_ops=8;;
1227	    no-yes-yes)
1228		have_atomic_ops=12;;
1229	    yes-no-no)
1230		have_atomic_ops=16;;
1231	    yes-no-yes)
1232		have_atomic_ops=20;;
1233	    yes-yes-no)
1234		have_atomic_ops=24;;
1235	    yes-yes-yes)
1236		have_atomic_ops=28;;
1237	esac
1238	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])
1239])
1240
1241AC_DEFUN(ETHR_CHK_IF_NOOP,
1242[
1243   ethr_test_filename="chk_if_$1$3_noop_config1test.$$"
1244   cat > "${ethr_test_filename}.c" <<EOF
1245int
1246my_test(void)
1247{
1248    $1$2;
1249    return 0;
1250}
1251EOF
1252   $CC -O3 $ETHR_DEFS -c "${ethr_test_filename}.c" -o "${ethr_test_filename}1.o"
1253   cat > "${ethr_test_filename}.c" <<EOF
1254int
1255my_test(void)
1256{
1257    ;
1258    return 0;
1259}
1260EOF
1261   $CC -O3 $ETHR_DEFS -c "${ethr_test_filename}.c" -o "${ethr_test_filename}2.o"
1262   if diff "${ethr_test_filename}1.o" "${ethr_test_filename}2.o" >/dev/null 2>&1; then
1263      ethr_$1$3_noop=yes
1264   else
1265      ethr_$1$3_noop=no
1266   fi
1267   rm -f "${ethr_test_filename}.c" "${ethr_test_filename}1.o"  "${ethr_test_filename}2.o"
1268])
1269
1270AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
1271[
1272    AC_CHECK_SIZEOF(short)
1273    AC_CHECK_SIZEOF(int)
1274    AC_CHECK_SIZEOF(long)
1275    AC_CHECK_SIZEOF(long long)
1276    AC_CHECK_SIZEOF(__int128_t)
1277
1278    if test "$ac_cv_sizeof_short" = "4"; then
1279	gcc_atomic_type32="short"
1280    elif test "$ac_cv_sizeof_int" = "4"; then
1281	gcc_atomic_type32="int"
1282    elif test "$ac_cv_sizeof_long" = "4"; then
1283	gcc_atomic_type32="long"
1284    else
1285	AC_MSG_ERROR([No 32-bit type found])
1286    fi
1287
1288    if test "$ac_cv_sizeof_int" = "8"; then
1289	gcc_atomic_type64="int"
1290    elif test "$ac_cv_sizeof_long" = "8"; then
1291	gcc_atomic_type64="long"
1292    elif test "$ac_cv_sizeof_long_long" = "8"; then
1293	gcc_atomic_type64="long long"
1294    else
1295	AC_MSG_ERROR([No 64-bit type found])
1296    fi
1297
1298    if test "$ac_cv_sizeof___int128_t" = "16"; then
1299	gcc_atomic_type128="__int128_t"
1300    else
1301	gcc_atomic_type128="#error "
1302    fi
1303    AC_CACHE_CHECK([for a working __sync_synchronize()], ethr_cv___sync_synchronize,
1304		   [
1305		       ethr_cv___sync_synchronize=no
1306		       AC_TRY_LINK([],
1307				   [ __sync_synchronize(); ],
1308				   [ethr_cv___sync_synchronize=yes])
1309		       if test $ethr_cv___sync_synchronize = yes; then
1310			   #
1311			   # Old gcc versions on at least x86 have a buggy
1312			   # __sync_synchronize() which does not emit a
1313			   # memory barrier. We try to detect this by
1314			   # compiling to assembly with and without
1315			   # __sync_synchronize() and compare the results.
1316			   #
1317			   ETHR_CHK_IF_NOOP(__sync_synchronize, [()], [])
1318			   if test $ethr___sync_synchronize_noop = yes; then
1319			      # Got a buggy implementation of
1320			      # __sync_synchronize...
1321			      ethr_cv___sync_synchronize="no; buggy implementation"
1322			   fi
1323		       fi
1324		   ])
1325
1326    if test "$ethr_cv___sync_synchronize" = "yes"; then
1327	have_sync_synchronize_value="~0"
1328    else
1329	have_sync_synchronize_value="0"
1330    fi
1331    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])
1332
1333    ETHR_CHK_GCC_ATOMIC_OP__(__sync_add_and_fetch)
1334    ETHR_CHK_GCC_ATOMIC_OP__(__sync_fetch_and_and)
1335    ETHR_CHK_GCC_ATOMIC_OP__(__sync_fetch_and_or)
1336    ETHR_CHK_GCC_ATOMIC_OP__(__sync_val_compare_and_swap)
1337
1338    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_store_n)
1339    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_load_n)
1340    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_add_fetch)
1341    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_fetch_and)
1342    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_fetch_or)
1343    ETHR_CHK_GCC_ATOMIC_OP__(__atomic_compare_exchange_n)
1344
1345    ethr_have_gcc_native_atomics=no
1346    ethr_arm_dbm_sy_instr_val=0
1347    ethr_arm_dbm_st_instr_val=0
1348    ethr_arm_dbm_ld_instr_val=0
1349    case "$GCC-$host_cpu" in
1350	yes-arm*|yes-aarch*)
1351	    AC_CACHE_CHECK([for ARM 'dmb sy' instruction], ethr_cv_arm_dbm_sy_instr,
1352			   [
1353				ethr_cv_arm_dbm_sy_instr=no
1354				AC_TRY_LINK([],
1355					    [
1356						__asm__ __volatile__("dmb sy" : : : "memory");
1357					    ],
1358					    [ethr_cv_arm_dbm_sy_instr=yes])
1359			   ])
1360	    if test $ethr_cv_arm_dbm_sy_instr = yes; then
1361		ethr_arm_dbm_sy_instr_val=1
1362		test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
1363		    ethr_have_gcc_native_atomics=yes
1364	    fi
1365	    AC_CACHE_CHECK([for ARM 'dmb st' instruction], ethr_cv_arm_dbm_st_instr,
1366			   [
1367				ethr_cv_arm_dbm_st_instr=no
1368				AC_TRY_LINK([],
1369					    [
1370						__asm__ __volatile__("dmb st" : : : "memory");
1371					    ],
1372					    [ethr_cv_arm_dbm_st_instr=yes])
1373			   ])
1374	    if test $ethr_cv_arm_dbm_st_instr = yes; then
1375		ethr_arm_dbm_st_instr_val=1
1376	    fi
1377	    AC_CACHE_CHECK([for ARM 'dmb ld' instruction], ethr_cv_arm_dbm_ld_instr,
1378			   [
1379				ethr_cv_arm_dbm_ld_instr=no
1380				AC_TRY_LINK([],
1381					    [
1382						__asm__ __volatile__("dmb ld" : : : "memory");
1383					    ],
1384					    [ethr_cv_arm_dbm_ld_instr=yes])
1385			   ])
1386	    if test $ethr_cv_arm_dbm_ld_instr = yes; then
1387		ethr_arm_dbm_ld_instr_val=1
1388	    fi;;
1389	*)
1390	    ;;
1391    esac
1392    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])
1393    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])
1394    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])
1395    test $ethr_cv_32bit___sync_val_compare_and_swap = yes &&
1396    	ethr_have_gcc_native_atomics=yes
1397    test $ethr_cv_64bit___sync_val_compare_and_swap = yes &&
1398    	ethr_have_gcc_native_atomics=yes
1399    if test "$ethr_cv___sync_synchronize" = "yes"; then
1400    	test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
1401    	    ethr_have_gcc_native_atomics=yes
1402    	test $ethr_cv_32bit___atomic_compare_exchange_n = yes &&
1403    	    ethr_have_gcc_native_atomics=yes
1404    fi
1405    ethr_have_gcc_atomic_builtins=0
1406    if test $ethr_have_gcc_native_atomics = yes; then
1407       ethr_native_atomic_implementation=gcc_sync
1408       test $ethr_cv_32bit___atomic_compare_exchange_n = yes && ethr_have_gcc_atomic_builtins=1
1409       test $ethr_cv_64bit___atomic_compare_exchange_n = yes && ethr_have_gcc_atomic_builtins=1
1410       test $ethr_have_gcc_atomic_builtins = 1 && ethr_native_atomic_implementation=gcc_atomic_sync
1411    fi
1412    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])
1413    test $ethr_have_gcc_native_atomics = yes && ethr_have_native_atomics=yes
1414])
1415
1416AC_DEFUN(ETHR_CHK_INTERLOCKED,
1417[
1418    ilckd="$1"
1419    AC_MSG_CHECKING([for ${ilckd}()])
1420    case "$2" in
1421	"1") ilckd_call="${ilckd}(var);";;
1422	"2") ilckd_call="${ilckd}(var, ($3) 0);";;
1423	"3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
1424	"4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
1425    esac
1426    have_interlocked_op=no
1427    AC_TRY_LINK(
1428	[
1429	#define WIN32_LEAN_AND_MEAN
1430	#include <windows.h>
1431	#include <intrin.h>
1432	],
1433	[
1434	    volatile $3 *var;
1435	    volatile $3 arr[2];
1436
1437	    $ilckd_call
1438	    return 0;
1439	],
1440	[have_interlocked_op=yes])
1441    test $have_interlocked_op = yes && $4
1442    AC_MSG_RESULT([$have_interlocked_op])
1443])
1444
1445dnl ----------------------------------------------------------------------
1446dnl
1447dnl ERL_FIND_ETHR_LIB
1448dnl
1449dnl NOTE! This macro may be changed at any time! Should *only* be used by
1450dnl       ERTS!
1451dnl
1452dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
1453dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
1454dnl except that the ethread lib itself is not included), ETHR_DEFS to
1455dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
1456dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
1457dnl to the name of the library where the ethread implementation is located.
1458dnl  ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
1459dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
1460dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
1461dnl empty string.
1462dnl
1463
1464AC_DEFUN(ERL_FIND_ETHR_LIB,
1465[
1466
1467AC_ARG_ENABLE(native-ethr-impls,
1468	      AS_HELP_STRING([--disable-native-ethr-impls],
1469                             [disable native ethread implementations]),
1470[ case "$enableval" in
1471    no) disable_native_ethr_impls=yes ;;
1472    *)  disable_native_ethr_impls=no ;;
1473  esac ], disable_native_ethr_impls=no)
1474
1475test "X$disable_native_ethr_impls" = "Xyes" &&
1476  AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
1477
1478AC_ARG_ENABLE(x86-out-of-order,
1479	      AS_HELP_STRING([--enable-x86-out-of-order],
1480                             [enable x86/x84_64 out of order support (default disabled)]))
1481
1482AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
1483	      AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
1484			     [prefer gcc native ethread implementations]),
1485[ case "$enableval" in
1486    yes) enable_prefer_gcc_native_ethr_impls=yes ;;
1487    *)  enable_prefer_gcc_native_ethr_impls=no ;;
1488  esac ], enable_prefer_gcc_native_ethr_impls=no)
1489
1490test $enable_prefer_gcc_native_ethr_impls = yes &&
1491  AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
1492
1493AC_ARG_ENABLE(trust-gcc-atomic-builtins-memory-barriers,
1494	      AS_HELP_STRING([--enable-trust-gcc-atomic-builtins-memory-barriers],
1495			     [trust gcc atomic builtins memory barriers]),
1496[ case "$enableval" in
1497    yes) trust_gcc_atomic_builtins_mbs=1 ;;
1498    *) trust_gcc_atomic_builtins_mbs=0 ;;
1499  esac ], trust_gcc_atomic_builtins_mbs=0)
1500
1501AC_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])
1502
1503AC_ARG_WITH(libatomic_ops,
1504	    AS_HELP_STRING([--with-libatomic_ops=PATH],
1505			   [specify and prefer usage of libatomic_ops in the ethread library]))
1506
1507AC_ARG_WITH(with_sparc_memory_order,
1508	    AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
1509			   [specify sparc memory order (defaults to RMO)]))
1510
1511AC_ARG_ENABLE(ppc-lwsync-instruction,
1512AS_HELP_STRING([--enable-ppc-lwsync-instruction], [enable use of powerpc lwsync instruction])
1513AS_HELP_STRING([--disable-ppc-lwsync-instruction], [disable use of powerpc lwsync instruction]),
1514[ case "$enableval" in
1515    no) enable_lwsync=no ;;
1516    *)  enable_lwsync=yes ;;
1517  esac ],
1518[
1519  AC_CHECK_SIZEOF(void *)
1520  case $host_cpu-$ac_cv_sizeof_void_p in
1521       macppc-8|powerpc-8|ppc-8|powerpc64-8|ppc64-8|powerpc64le-8|ppc64le-8|"Power Macintosh"-8)
1522           enable_lwsync=yes;;
1523       *)
1524           enable_lwsync=undefined;;
1525  esac ])
1526
1527case $enable_lwsync in
1528     no)
1529       AC_DEFINE(ETHR_PPC_HAVE_NO_LWSYNC, [1], [Define if you do not have the powerpc lwsync instruction])
1530       ;;
1531     yes)
1532       AC_DEFINE(ETHR_PPC_HAVE_LWSYNC, [1], [Define if you have the powerpc lwsync instruction])
1533       ;;
1534     *)
1535       ;;
1536esac
1537
1538LM_CHECK_THR_LIB
1539ERL_INTERNAL_LIBS
1540
1541ERL_MONOTONIC_CLOCK(try_find_pthread_compatible, CLOCK_HIGHRES CLOCK_MONOTONIC, no)
1542
1543case $erl_monotonic_clock_func in
1544  clock_gettime)
1545    AC_DEFINE(ETHR_HAVE_CLOCK_GETTIME_MONOTONIC, [1], [Define if you have a clock_gettime() with a monotonic clock])
1546    ;;
1547  mach_clock_get_time)
1548    AC_DEFINE(ETHR_HAVE_MACH_CLOCK_GET_TIME, [1], [Define if you have a mach clock_get_time() with a monotonic clock])
1549    ;;
1550  gethrtime)
1551    AC_DEFINE(ETHR_HAVE_GETHRTIME, [1], [Define if you have a monotonic gethrtime()])
1552    ;;
1553  *)
1554    ;;
1555esac
1556
1557if test "x$erl_monotonic_clock_id" != "x"; then
1558    AC_DEFINE_UNQUOTED(ETHR_MONOTONIC_CLOCK_ID, [$erl_monotonic_clock_id], [Define to the monotonic clock id to use])
1559fi
1560
1561ethr_native_atomic_implementation=none
1562ethr_have_native_atomics=no
1563ethr_have_native_spinlock=no
1564ETHR_THR_LIB_BASE="$THR_LIB_NAME"
1565ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
1566ETHR_DEFS="$THR_DEFS"
1567ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS $erl_monotonic_clock_lib"
1568ETHR_LIBS=
1569ETHR_LIB_NAME=
1570
1571ethr_modified_default_stack_size=
1572
1573AC_ARG_WITH(threadnames,
1574AS_HELP_STRING([--with-threadnames], [use pthread_setname to set the thread names (default)])
1575AS_HELP_STRING([--without-threadnames],
1576               [do not set any thread names]),
1577[],
1578[with_threadnames=yes])
1579
1580dnl Name of lib where ethread implementation is located
1581ethr_lib_name=ethread
1582
1583case "$THR_LIB_NAME" in
1584
1585    win32_threads)
1586	ETHR_THR_LIB_BASE_DIR=win
1587	# * _WIN32_WINNT >= 0x0400 is needed for
1588	#   TryEnterCriticalSection
1589	# * _WIN32_WINNT >= 0x0403 is needed for
1590	#   InitializeCriticalSectionAndSpinCount
1591	# The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
1592	#
1593	# -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
1594	# and save it in ETHR_DEFS.
1595	found_win32_winnt=no
1596	for cppflag in $CPPFLAGS; do
1597	    case $cppflag in
1598		-DWINVER*)
1599		    ETHR_DEFS="$ETHR_DEFS $cppflag"
1600		    ;;
1601		-D_WIN32_WINNT*)
1602		    ETHR_DEFS="$ETHR_DEFS $cppflag"
1603		    found_win32_winnt=yes
1604		    ;;
1605		*)
1606		    ;;
1607	    esac
1608        done
1609        if test $found_win32_winnt = no; then
1610	    AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
1611        fi
1612
1613	AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
1614
1615	if test "X$disable_native_ethr_impls" = "Xyes"; then
1616	    have_interlocked_op=no
1617	    ethr_have_native_atomics=no
1618	else
1619	    ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
1620	    ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
1621	    ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
1622	    ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
1623	    ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
1624	    ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
1625	    ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
1626	    ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
1627	    ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
1628	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
1629	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1630	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
1631	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1632	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
1633	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1634
1635	    ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
1636	    ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
1637	    ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
1638	    ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
1639	    ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
1640	    ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
1641	    ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
1642	    ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
1643	    ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
1644	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
1645	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1646	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
1647	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1648	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
1649	    test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
1650
1651	    ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
1652	fi
1653	if test "$ethr_have_native_atomics" = "yes"; then
1654	   ethr_native_atomic_implementation=windows
1655	   ethr_have_native_spinlock=yes
1656	fi
1657	;;
1658
1659    pthread)
1660	ETHR_THR_LIB_BASE_DIR=pthread
1661	AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
1662	case $host_os in
1663	    openbsd*)
1664		# The default stack size is insufficient for our needs
1665		# on OpenBSD. We increase it to 256 kilo words.
1666		ethr_modified_default_stack_size=256;;
1667	    linux*)
1668		ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
1669
1670		if test	X$cross_compiling = Xyes; then
1671		    case X$erl_xcomp_linux_usable_sigusrx in
1672			X) usable_sigusrx=cross;;
1673			Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
1674			*) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
1675		    esac
1676		    case X$erl_xcomp_linux_usable_sigaltstack in
1677			X) usable_sigaltstack=cross;;
1678			Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
1679			*) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
1680		    esac
1681		else
1682		    # FIXME: Test for actual problems instead of kernel versions
1683		    linux_kernel_vsn_=`uname -r`
1684		    case $linux_kernel_vsn_ in
1685			[[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
1686			    usable_sigusrx=no
1687			    usable_sigaltstack=no;;
1688			2.[[2-3]]|2.[[2-3]].*)
1689			    usable_sigusrx=yes
1690			    usable_sigaltstack=no;;
1691		    	*)
1692			    usable_sigusrx=yes
1693			    usable_sigaltstack=yes;;
1694		    esac
1695		fi
1696
1697		AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
1698		AC_MSG_RESULT($usable_sigusrx)
1699		if test $usable_sigusrx = cross; then
1700		    usable_sigusrx=yes
1701		    AC_MSG_WARN([result yes guessed because of cross compilation])
1702		fi
1703		if test $usable_sigusrx = no; then
1704		    ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
1705		fi
1706
1707		AC_MSG_CHECKING(if sigaltstack can be used)
1708		AC_MSG_RESULT($usable_sigaltstack)
1709		if test $usable_sigaltstack = cross; then
1710		    usable_sigaltstack=yes
1711		    AC_MSG_WARN([result yes guessed because of cross compilation])
1712		fi
1713		if test $usable_sigaltstack = no; then
1714		    ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
1715		fi
1716		;;
1717	    *) ;;
1718	esac
1719
1720	dnl We sometimes need ETHR_DEFS in order to find certain headers
1721	dnl (at least for pthread.h on osf1).
1722	saved_cppflags="$CPPFLAGS"
1723	CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
1724
1725	dnl We need the thread library in order to find some functions
1726	saved_libs="$LIBS"
1727	LIBS="$LIBS $ETHR_X_LIBS"
1728
1729	dnl
1730	dnl Check for headers
1731	dnl
1732	AC_CHECK_HEADER(pthread.h, \
1733			AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
1734[Define if you have the <pthread.h> header file.]))
1735
1736	dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
1737	AC_CHECK_HEADER(pthread/mit/pthread.h, \
1738			AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
1739[Define if the pthread.h header file is in pthread/mit directory.]))
1740
1741	if test $NEED_NPTL_PTHREAD_H = yes; then
1742	    AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
1743[Define if you need the <nptl/pthread.h> header file.])
1744	fi
1745
1746	AC_CHECK_HEADER(sched.h, \
1747			AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
1748[Define if you have the <sched.h> header file.]))
1749
1750	AC_CHECK_HEADER(sys/time.h, \
1751			AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
1752[Define if you have the <sys/time.h> header file.]))
1753
1754	AC_TRY_COMPILE([#include <time.h>
1755			#include <sys/time.h>],
1756			[struct timeval *tv; return 0;],
1757			AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \
1758[Define if you can safely include both <sys/time.h> and <time.h>.]))
1759
1760	AC_MSG_CHECKING([for usable PTHREAD_STACK_MIN])
1761	pthread_stack_min=no
1762	AC_TRY_COMPILE([
1763#include <limits.h>
1764#if defined(ETHR_NEED_NPTL_PTHREAD_H)
1765#include <nptl/pthread.h>
1766#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
1767#include <pthread/mit/pthread.h>
1768#elif defined(ETHR_HAVE_PTHREAD_H)
1769#include <pthread.h>
1770#endif
1771			],
1772			[return PTHREAD_STACK_MIN;],
1773			[pthread_stack_min=yes])
1774
1775	AC_MSG_RESULT([$pthread_stack_min])
1776	test $pthread_stack_min != yes || {
1777	     AC_DEFINE(ETHR_HAVE_USABLE_PTHREAD_STACK_MIN, 1, [Define if you can use PTHREAD_STACK_MIN])
1778	}
1779
1780	dnl
1781	dnl Check for functions
1782	dnl
1783	AC_CHECK_FUNC(pthread_spin_lock, \
1784			[ethr_have_native_spinlock=yes \
1785			 AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
1786[Define if you have the pthread_spin_lock function.])])
1787
1788	have_sched_yield=no
1789	have_librt_sched_yield=no
1790	AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes])
1791	if test $have_sched_yield = no; then
1792	    AC_CHECK_LIB(rt, sched_yield,
1793			 [have_librt_sched_yield=yes
1794			  ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
1795	fi
1796	if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
1797	    AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
1798	    AC_MSG_CHECKING([whether sched_yield() returns an int])
1799	    sched_yield_ret_int=no
1800	    AC_TRY_LINK([
1801				#ifdef ETHR_HAVE_SCHED_H
1802				#include <sched.h>
1803				#endif
1804			   ],
1805			   [int sched_yield();],
1806			   [sched_yield_ret_int=yes])
1807	    AC_MSG_RESULT([$sched_yield_ret_int])
1808	    if test $sched_yield_ret_int = yes; then
1809		AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
1810	    fi
1811	fi
1812
1813	have_pthread_yield=no
1814	AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes])
1815	if test $have_pthread_yield = yes; then
1816	    AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
1817	    AC_MSG_CHECKING([whether pthread_yield() returns an int])
1818	    pthread_yield_ret_int=no
1819	    AC_TRY_LINK([
1820				#if defined(ETHR_NEED_NPTL_PTHREAD_H)
1821				#include <nptl/pthread.h>
1822				#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
1823				#include <pthread/mit/pthread.h>
1824				#elif defined(ETHR_HAVE_PTHREAD_H)
1825				#include <pthread.h>
1826				#endif
1827			   ],
1828			   [int pthread_yield();],
1829			   [pthread_yield_ret_int=yes])
1830	    AC_MSG_RESULT([$pthread_yield_ret_int])
1831	    if test $pthread_yield_ret_int = yes; then
1832		AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
1833	    fi
1834	fi
1835
1836	have_pthread_rwlock_init=no
1837	AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
1838	if test $have_pthread_rwlock_init = yes; then
1839
1840	    ethr_have_pthread_rwlockattr_setkind_np=no
1841	    AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
1842			  [ethr_have_pthread_rwlockattr_setkind_np=yes])
1843
1844	    if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
1845		AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
1846[Define if you have the pthread_rwlockattr_setkind_np() function.])
1847
1848		AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
1849		ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
1850		AC_TRY_LINK([
1851				#if defined(ETHR_NEED_NPTL_PTHREAD_H)
1852				#include <nptl/pthread.h>
1853				#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
1854				#include <pthread/mit/pthread.h>
1855				#elif defined(ETHR_HAVE_PTHREAD_H)
1856				#include <pthread.h>
1857				#endif
1858			    ],
1859			    [
1860				pthread_rwlockattr_t *attr;
1861				return pthread_rwlockattr_setkind_np(attr,
1862				    PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
1863			    ],
1864			    [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes])
1865		AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
1866		if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
1867		    AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
1868[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
1869		fi
1870	    fi
1871	fi
1872
1873	if test "$force_pthread_rwlocks" = "yes"; then
1874
1875	    AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
1876[Define if you want to force usage of pthread rwlocks])
1877
1878	    if test $have_pthread_rwlock_init = yes; then
1879		AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
1880	    else
1881		AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
1882	    fi
1883	fi
1884
1885	AC_CHECK_FUNC(pthread_attr_setguardsize, \
1886			AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
1887[Define if you have the pthread_attr_setguardsize function.]))
1888
1889	if test "x$erl_monotonic_clock_id" != "x"; then
1890	  AC_MSG_CHECKING(whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout)
1891	  pthread_cond_timedwait_monotonic=no
1892	  AC_TRY_LINK([
1893			#if defined(ETHR_NEED_NPTL_PTHREAD_H)
1894			#  include <nptl/pthread.h>
1895			#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
1896			#  include <pthread/mit/pthread.h>
1897			#elif defined(ETHR_HAVE_PTHREAD_H)
1898			#  include <pthread.h>
1899			#endif
1900			#ifdef ETHR_TIME_WITH_SYS_TIME
1901			#  include <time.h>
1902			#  include <sys/time.h>
1903			#else
1904			#  ifdef ETHR_HAVE_SYS_TIME_H
1905			#    include <sys/time.h>
1906			#  else
1907			#    include <time.h>
1908			#  endif
1909			#endif
1910			#if defined(ETHR_HAVE_MACH_CLOCK_GET_TIME)
1911			#  include <mach/clock.h>
1912			#  include <mach/mach.h>
1913			#endif
1914			],
1915			[
1916			int res;
1917			pthread_condattr_t attr;
1918			pthread_cond_t cond;
1919			struct timespec cond_timeout;
1920			pthread_mutex_t mutex;
1921			res = pthread_condattr_init(&attr);
1922			res = pthread_condattr_setclock(&attr, ETHR_MONOTONIC_CLOCK_ID);
1923			res = pthread_cond_init(&cond, &attr);
1924			res = pthread_cond_timedwait(&cond, &mutex, &cond_timeout);
1925			],
1926			[pthread_cond_timedwait_monotonic=yes])
1927	  AC_MSG_RESULT([$pthread_cond_timedwait_monotonic])
1928	  if test $pthread_cond_timedwait_monotonic = yes; then
1929	    AC_DEFINE(ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC, [1], [Define if pthread_cond_timedwait() can be used with a monotonic clock])
1930	  fi
1931	fi
1932
1933	linux_futex=no
1934	AC_MSG_CHECKING([for Linux futexes])
1935	AC_TRY_LINK([
1936			#include <sys/syscall.h>
1937			#include <unistd.h>
1938			#include <linux/futex.h>
1939			#include <sys/time.h>
1940		    ],
1941		    [
1942			int i = 1;
1943			syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
1944				(void*)0,(void*)0, 0);
1945			syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
1946				(void*)0,(void*)0, 0);
1947			return 0;
1948		    ],
1949		    linux_futex=yes)
1950	AC_MSG_RESULT([$linux_futex])
1951	test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
1952
1953	pthread_setname=no
1954	AC_MSG_CHECKING([for pthread_setname_np])
1955	old_CFLAGS=$CFLAGS
1956	CFLAGS="$CFLAGS -Werror"
1957	AC_TRY_LINK([#define __USE_GNU
1958                     #include <pthread.h>],
1959                    [pthread_setname_np(pthread_self(), "name");],
1960                    pthread_setname=linux)
1961	AC_TRY_LINK([#define __USE_GNU
1962                     #include <pthread.h>],
1963                    [pthread_set_name_np(pthread_self(), "name");],
1964                    pthread_setname=bsd)
1965	AC_TRY_LINK([#define _DARWIN_C_SOURCE
1966                     #include <pthread.h>],
1967                    [pthread_setname_np("name");],
1968                    pthread_setname=darwin)
1969        AC_MSG_RESULT([$pthread_setname])
1970        case $with_threadnames-$pthread_setname in
1971             yes-linux) AC_DEFINE(ETHR_HAVE_PTHREAD_SETNAME_NP_2, 1,
1972                          [Define if you have linux style pthread_setname_np]);;
1973             yes-bsd) AC_DEFINE(ETHR_HAVE_PTHREAD_SET_NAME_NP_2, 1,
1974                          [Define if you have bsd style pthread_set_name_np]);;
1975             yes-darwin) AC_DEFINE(ETHR_HAVE_PTHREAD_SETNAME_NP_1, 1,
1976                          [Define if you have darwin style pthread_setname_np]);;
1977             *) ;;
1978	esac
1979
1980	pthread_getname=no
1981	AC_MSG_CHECKING([for pthread_getname_np])
1982	AC_TRY_LINK([#define __USE_GNU
1983                     #define _DARWIN_C_SOURCE
1984                     #include <pthread.h>],
1985                    [char buff[256]; pthread_getname_np(pthread_self(), buff, 256);],
1986                    pthread_getname=linux)
1987	AC_TRY_LINK([#define __USE_GNU
1988                     #define _DARWIN_C_SOURCE
1989                     #include <pthread.h>],
1990                    [char buff[256]; pthread_getname_np(pthread_self(), buff);],
1991                    pthread_getname=ibm)
1992        AC_MSG_RESULT([$pthread_getname])
1993        case $pthread_getname in
1994             linux) AC_DEFINE(ETHR_HAVE_PTHREAD_GETNAME_NP_3, 1,
1995                          [Define if you have linux style pthread_getname_np]);;
1996             ibm) AC_DEFINE(ETHR_HAVE_PTHREAD_GETNAME_NP_2, 1,
1997                          [Define if you have ibm style pthread_getname_np]);;
1998             *) ;;
1999	esac
2000	CFLAGS=$old_CFLAGS
2001
2002	if test "X$disable_native_ethr_impls" = "Xyes"; then
2003	    ethr_have_native_atomics=no
2004	else
2005
2006	    ETHR_CHK_GCC_ATOMIC_OPS([])
2007
2008	    AC_MSG_CHECKING([for a usable libatomic_ops implementation])
2009	    case "x$with_libatomic_ops" in
2010	        xno | xyes | x)
2011	    	    libatomic_ops_include=
2012	    	    ;;
2013	        *)
2014	    	    if test -d "${with_libatomic_ops}/include"; then
2015	    	        libatomic_ops_include="-I$with_libatomic_ops/include"
2016	    	        CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
2017	    	    else
2018	    	        AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
2019	    	    fi;;
2020	    esac
2021	    ethr_have_libatomic_ops=no
2022	    AC_TRY_LINK([#include "atomic_ops.h"],
2023	    	        [
2024	    	    	    volatile AO_t x;
2025	    	    	    AO_t y;
2026	    	    	    int z;
2027
2028	    	    	    AO_nop_full();
2029#if defined(AO_HAVE_store)
2030	    	    	    AO_store(&x, (AO_t) 0);
2031#elif defined(AO_HAVE_store_release)
2032	    	    	    AO_store_release(&x, (AO_t) 0);
2033#else
2034#error No store
2035#endif
2036#if defined(AO_HAVE_load)
2037	    	    	    z = AO_load(&x);
2038#elif defined(AO_HAVE_load_acquire)
2039	    	    	    z = AO_load_acquire(&x);
2040#else
2041#error No load
2042#endif
2043#if defined(AO_HAVE_compare_and_swap_full)
2044	    	    	    z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
2045#elif defined(AO_HAVE_compare_and_swap_release)
2046	    	    	    z = AO_compare_and_swap_release(&x, (AO_t) 0, (AO_t) 1);
2047#elif defined(AO_HAVE_compare_and_swap_acquire)
2048	    	    	    z = AO_compare_and_swap_acquire(&x, (AO_t) 0, (AO_t) 1);
2049#elif defined(AO_HAVE_compare_and_swap)
2050	    	    	    z = AO_compare_and_swap(&x, (AO_t) 0, (AO_t) 1);
2051#else
2052#error No compare_and_swap
2053#endif
2054	    	        ],
2055	    	        [ethr_have_native_atomics=yes
2056			 ethr_native_atomic_implementation=libatomic_ops
2057	    	         ethr_have_libatomic_ops=yes])
2058	    AC_MSG_RESULT([$ethr_have_libatomic_ops])
2059	    if test $ethr_have_libatomic_ops = yes; then
2060	        AC_CHECK_SIZEOF(AO_t, ,
2061	    	    	        [
2062	    	    	    	    #include <stdio.h>
2063	    	    	    	    #include "atomic_ops.h"
2064	    	    	        ])
2065	        AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
2066
2067	        AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
2068	        if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
2069	    	    AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
2070	        fi
2071	        ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
2072	    elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
2073	        AC_MSG_ERROR([No usable libatomic_ops implementation found])
2074	    fi
2075
2076	    case "$host_cpu" in
2077	      sparc | sun4u | sparc64 | sun4v)
2078	    	    case "$with_sparc_memory_order" in
2079	    	        "TSO")
2080	    	    	    AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
2081	    	        "PSO")
2082	    	    	    AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
2083	    	        "RMO"|"")
2084	    	    	    AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
2085	    	        *)
2086	    	    	    AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
2087	    	    esac
2088		    ethr_native_atomic_implementation=ethread
2089	    	    ethr_have_native_atomics=yes;;
2090	      i86pc | i*86 | x86_64 | amd64)
2091	    	    if test "$enable_x86_out_of_order" = "yes"; then
2092	    	    	    AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
2093	    	    fi
2094		    ethr_native_atomic_implementation=ethread
2095	    	    ethr_have_native_atomics=yes;;
2096	      macppc | ppc | powerpc | "Power Macintosh")
2097	      	    ethr_native_atomic_implementation=ethread
2098	    	    ethr_have_native_atomics=yes;;
2099	      tile)
2100	            ethr_native_atomic_implementation=ethread
2101	    	    ethr_have_native_atomics=yes;;
2102	      *)
2103	    	    ;;
2104	    esac
2105
2106	fi
2107
2108	test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
2109
2110	dnl Restore LIBS
2111	LIBS=$saved_libs
2112	dnl restore CPPFLAGS
2113	CPPFLAGS=$saved_cppflags
2114
2115	;;
2116    *)
2117	;;
2118esac
2119
2120AC_MSG_CHECKING([whether default stack size should be modified])
2121if test "x$ethr_modified_default_stack_size" != "x"; then
2122	AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
2123	AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
2124else
2125	AC_MSG_RESULT([no])
2126fi
2127
2128if test "x$ETHR_THR_LIB_BASE" != "x"; then
2129	ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
2130	ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
2131	ETHR_LIB_NAME=$ethr_lib_name
2132fi
2133
2134AC_CHECK_SIZEOF(void *)
2135AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
2136
2137AC_CHECK_SIZEOF(int)
2138AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
2139AC_CHECK_SIZEOF(long)
2140AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
2141AC_CHECK_SIZEOF(long long)
2142AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
2143AC_CHECK_SIZEOF(__int64)
2144AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
2145AC_CHECK_SIZEOF(__int128_t)
2146AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
2147
2148
2149case X$erl_xcomp_bigendian in
2150    X) ;;
2151    Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
2152    *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
2153esac
2154
2155AC_C_BIGENDIAN
2156
2157if test "$ac_cv_c_bigendian" = "yes"; then
2158    AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
2159fi
2160
2161case X$erl_xcomp_double_middle_endian in
2162    X) ;;
2163    Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
2164    *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
2165esac
2166
2167AC_C_DOUBLE_MIDDLE_ENDIAN
2168
2169ETHR_X86_SSE2_ASM=no
2170case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
2171  yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
2172    AC_MSG_CHECKING([for gcc sse2 asm support])
2173    save_CFLAGS="$CFLAGS"
2174    CFLAGS="$CFLAGS -msse2"
2175    gcc_sse2_asm=no
2176    AC_TRY_COMPILE([],
2177	[
2178		long long x, *y;
2179		__asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
2180	],
2181	[gcc_sse2_asm=yes])
2182    CFLAGS="$save_CFLAGS"
2183    AC_MSG_RESULT([$gcc_sse2_asm])
2184    if test "$gcc_sse2_asm" = "yes"; then
2185      AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
2186      ETHR_X86_SSE2_ASM=yes
2187    fi
2188    ;;
2189  *)
2190    ;;
2191esac
2192
2193case "$GCC-$host_cpu" in
2194  yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
2195
2196    if test $ac_cv_sizeof_void_p = 4; then
2197       dw_cmpxchg="cmpxchg8b"
2198    else
2199       dw_cmpxchg="cmpxchg16b"
2200    fi
2201
2202    gcc_dw_cmpxchg_asm=no
2203    gcc_pic_dw_cmpxchg_asm=no
2204    gcc_cflags_pic=no
2205    gcc_cmpxchg8b_pic_no_clobber_ebx=no
2206    gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=no
2207
2208    save_CFLAGS="$CFLAGS"
2209
2210    # Check if it works out of the box using passed CFLAGS
2211    # and with -fPIC added to CFLAGS if the passed CFLAGS
2212    # doesn't trigger position independent code
2213    pic_cmpxchg=unknown
2214    while true; do
2215
2216        case $pic_cmpxchg in
2217	  yes) pic_text="pic ";;
2218	  *) pic_text="";;
2219	esac
2220
2221	AC_MSG_CHECKING([for gcc $pic_text$dw_cmpxchg plain asm support])
2222
2223	plain_cmpxchg=no
2224    	AC_TRY_COMPILE([],
2225	[
2226    char xchgd;
2227    long new[2], xchg[2], *p;
2228    __asm__ __volatile__(
2229#if ETHR_SIZEOF_PTR == 4
2230	"lock; cmpxchg8b %0\n\t"
2231#else
2232	"lock; cmpxchg16b %0\n\t"
2233#endif
2234	"setz %3\n\t"
2235	: "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
2236	: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "b"(new[0])
2237	: "cc", "memory");
2238	],
2239	[plain_cmpxchg=yes])
2240
2241	AC_MSG_RESULT([$plain_cmpxchg])
2242
2243	if test $pic_cmpxchg = yes; then
2244	   gcc_pic_dw_cmpxchg_asm=$plain_cmpxchg
2245	   break
2246	fi
2247
2248	gcc_dw_cmpxchg_asm=$plain_cmpxchg
2249
2250    	# If not already compiling to position independent
2251	# code add -fPIC to CFLAGS and do it again. This
2252	# since we want also want to know how to compile
2253	# to position independent code since this might
2254	# cause problems with the use of the EBX register
2255	# as input to the asm on 32-bit x86 and old gcc
2256	# compilers (gcc vsn < 5).
2257
2258    	AC_TRY_COMPILE([],
2259	[
2260#if !defined(__PIC__) || !__PIC__
2261#  error no pic
2262#endif
2263	],
2264	[pic_cmpxchg=yes
2265	 gcc_cflags_pic=yes],
2266	[pic_cmpxchg=no])
2267
2268	if test $pic_cmpxchg = yes; then
2269	   gcc_pic_dw_cmpxchg_asm=$gcc_dw_cmpxchg_asm
2270	   break
2271	fi
2272
2273	CFLAGS="$save_CFLAGS -fPIC"
2274	pic_cmpxchg=yes
2275
2276    done
2277
2278    if test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
2279
2280      AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX workaround])
2281
2282      # Check if we can work around it by managing the ebx
2283      # register explicitly in the asm...
2284
2285      AC_TRY_COMPILE([],
2286	[
2287    char xchgd;
2288    long new[2], xchg[2], *p;
2289    __asm__ __volatile__(
2290	"pushl %%ebx\n\t"
2291	"movl %8, %%ebx\n\t"
2292	"lock; cmpxchg8b %0\n\t"
2293	"setz %3\n\t"
2294	"popl %%ebx\n\t"
2295	: "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
2296	: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "r"(new[0])
2297	: "cc", "memory");
2298	],
2299	[gcc_pic_dw_cmpxchg_asm=yes
2300	 gcc_cmpxchg8b_pic_no_clobber_ebx=yes])
2301
2302      AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
2303
2304      if test $gcc_pic_dw_cmpxchg_asm = no; then
2305
2306      	AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds])
2307        # If no optimization is enabled we sometimes get a
2308	# register shortage. Check if we can work around
2309	# this...
2310
2311      	AC_TRY_COMPILE([],
2312	  [
2313      char xchgd;
2314      long new[2], xchg[2], *p;
2315      __asm__ __volatile__(
2316	"pushl %%ebx\n\t"
2317	"movl (%7), %%ebx\n\t"
2318	"movl 4(%7), %%ecx\n\t"
2319	"lock; cmpxchg8b %0\n\t"
2320	"setz %3\n\t"
2321	"popl %%ebx\n\t"
2322	: "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
2323	: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "r"(new)
2324	: "cc", "memory");
2325
2326	],
2327	[gcc_pic_dw_cmpxchg_asm=yes
2328	 gcc_cmpxchg8b_pic_no_clobber_ebx=yes
2329	 gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=yes])
2330
2331        AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
2332      fi
2333
2334      if test $gcc_cflags_pic = yes; then
2335        gcc_dw_cmpxchg_asm=$gcc_pic_dw_cmpxchg_asm
2336      fi
2337
2338   fi
2339
2340    CFLAGS="$save_CFLAGS"
2341
2342    if test "$gcc_cmpxchg8b_pic_no_clobber_ebx" = "yes"; then
2343      AC_DEFINE(ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX, 1, [Define if gcc wont let you clobber ebx with cmpxchg8b and position independent code])
2344    fi
2345    if test "$gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage" = "yes"; then
2346      AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
2347    fi
2348    if test "$gcc_dw_cmpxchg_asm" = "yes"; then
2349      AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
2350    fi;;
2351  *)
2352    ;;
2353esac
2354
2355AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
2356[Define if you have all ethread defines])
2357
2358AC_SUBST(ETHR_X_LIBS)
2359AC_SUBST(ETHR_LIBS)
2360AC_SUBST(ETHR_LIB_NAME)
2361AC_SUBST(ETHR_DEFS)
2362AC_SUBST(ETHR_THR_LIB_BASE)
2363AC_SUBST(ETHR_THR_LIB_BASE_DIR)
2364AC_SUBST(ETHR_X86_SSE2_ASM)
2365
2366])
2367
2368
2369dnl ----------------------------------------------------------------------
2370dnl
2371dnl ERL_TIME_CORRECTION
2372dnl
2373dnl Check for primitives that can be used for implementing
2374dnl erts_os_monotonic_time() and erts_os_system_time()
2375dnl
2376
2377AC_DEFUN(ERL_TIME_CORRECTION,
2378[
2379
2380AC_ARG_WITH(clock-resolution,
2381AS_HELP_STRING([--with-clock-resolution=high|low|default],
2382               [specify wanted clock resolution]))
2383
2384AC_ARG_WITH(clock-gettime-realtime-id,
2385AS_HELP_STRING([--with-clock-gettime-realtime-id=CLOCKID],
2386               [specify clock id to use with clock_gettime() for realtime time)]))
2387
2388AC_ARG_WITH(clock-gettime-monotonic-id,
2389AS_HELP_STRING([--with-clock-gettime-monotonic-id=CLOCKID],
2390               [specify clock id to use with clock_gettime() for monotonic time)]))
2391
2392AC_ARG_ENABLE(prefer-elapsed-monotonic-time-during-suspend,
2393AS_HELP_STRING([--enable-prefer-elapsed-monotonic-time-during-suspend],
2394               [Prefer an OS monotonic time source with elapsed time during suspend])
2395AS_HELP_STRING([--disable-prefer-elapsed-monotonic-time-during-suspend],
2396               [Do not prefer an OS monotonic time source with elapsed time during suspend]),
2397[ case "$enableval" in
2398    yes) prefer_elapsed_monotonic_time_during_suspend=yes ;;
2399    *)  prefer_elapsed_monotonic_time_during_suspend=no ;;
2400  esac ], prefer_elapsed_monotonic_time_during_suspend=no)
2401
2402AC_ARG_ENABLE(gettimeofday-as-os-system-time,
2403	      AS_HELP_STRING([--enable-gettimeofday-as-os-system-time],
2404                             [Force usage of gettimeofday() for OS system time]),
2405[ case "$enableval" in
2406    yes) force_gettimeofday_os_system_time=yes ;;
2407    *)  force_gettimeofday_os_system_time=no ;;
2408  esac ], force_gettimeofday_os_system_time=no)
2409
2410case "$with_clock_resolution" in
2411   ""|no|yes)
2412     with_clock_resolution=default;;
2413   high|low|default)
2414     ;;
2415   *)
2416     AC_MSG_ERROR([Invalid wanted clock resolution: $with_clock_resolution])
2417     ;;
2418esac
2419
2420if test "$force_gettimeofday_os_system_time" = "yes"; then
2421
2422  AC_CHECK_FUNCS([gettimeofday])
2423  if test "$ac_cv_func_gettimeofday" = "yes"; then
2424    AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY,  [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
2425  else
2426    AC_MSG_ERROR([No gettimeofday() available])
2427  fi
2428
2429else # $force_gettimeofday_os_system_time != yes
2430
2431case "$with_clock_gettime_realtime_id" in
2432   ""|no)
2433     with_clock_gettime_realtime_id=no
2434     ;;
2435   CLOCK_*CPUTIME*)
2436     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])
2437     ;;
2438   CLOCK_MONOTONIC*|CLOCK_BOOTTIME*|CLOCK_UPTIME*|CLOCK_HIGHRES*)
2439     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])
2440     ;;
2441   CLOCK_*)
2442     ;;
2443   *)
2444     AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_realtime_id])
2445     ;;
2446esac
2447
2448case "$with_clock_resolution-$with_clock_gettime_realtime_id" in
2449  high-no)
2450	ERL_WALL_CLOCK(high_resolution);;
2451  low-no)
2452	ERL_WALL_CLOCK(low_resolution);;
2453  default-no)
2454	ERL_WALL_CLOCK(default_resolution);;
2455  *)
2456	ERL_WALL_CLOCK(custom_resolution, $with_clock_gettime_realtime_id);;
2457esac
2458
2459case "$erl_wall_clock_func-$erl_wall_clock_id-$with_clock_gettime_realtime_id" in
2460  *-*-no)
2461    ;;
2462  clock_gettime-$with_clock_gettime_realtime_id-$with_clock_gettime_realtime_id)
2463    ;;
2464  *)
2465    AC_MSG_ERROR([$with_clock_gettime_realtime_id as clock id to clock_gettime() doesn't compile])
2466    ;;
2467esac
2468
2469case $erl_wall_clock_func in
2470  none)
2471    AC_MSG_ERROR([No wall clock source found])
2472    ;;
2473  mach_clock_get_time)
2474    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()])
2475    ;;
2476  clock_gettime)
2477    AC_DEFINE(OS_SYSTEM_TIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_system_time() using clock_gettime()])
2478    ;;
2479  gettimeofday)
2480    AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY,  [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
2481    ;;
2482  *)
2483    ;;
2484esac
2485
2486if test "x$erl_wall_clock_id" != "x"; then
2487    AC_DEFINE_UNQUOTED(WALL_CLOCK_ID_STR, ["$erl_wall_clock_id"], [Define as a string of wall clock id to use])
2488    AC_DEFINE_UNQUOTED(WALL_CLOCK_ID, [$erl_wall_clock_id], [Define to wall clock id to use])
2489fi
2490
2491fi # $force_gettimeofday_os_system_time != yes
2492
2493case "$with_clock_gettime_monotonic_id" in
2494   ""|no)
2495     with_clock_gettime_monotonic_id=no
2496     ;;
2497   CLOCK_*CPUTIME*)
2498     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])
2499     ;;
2500   CLOCK_REALTIME*|CLOCK_TAI*)
2501     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])
2502     ;;
2503   CLOCK_*)
2504     ;;
2505   *)
2506     AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_monotonic_id])
2507     ;;
2508esac
2509
2510case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in
2511  high-no)
2512	ERL_MONOTONIC_CLOCK(high_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
2513  low-no)
2514	ERL_MONOTONIC_CLOCK(low_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
2515  default-no)
2516	ERL_MONOTONIC_CLOCK(default_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
2517  *)
2518	ERL_MONOTONIC_CLOCK(custom_resolution, $with_clock_gettime_monotonic_id, $prefer_elapsed_monotonic_time_during_suspend);;
2519esac
2520
2521case "$erl_monotonic_clock_func-$erl_monotonic_clock_id-$with_clock_gettime_monotonic_id" in
2522  *-*-no)
2523    ;;
2524  clock_gettime-$with_clock_gettime_monotonic_id-$with_clock_gettime_monotonic_id)
2525    ;;
2526  *)
2527    AC_MSG_ERROR([$with_clock_gettime_monotonic_id as clock id to clock_gettime() doesn't compile])
2528    ;;
2529esac
2530
2531case $erl_monotonic_clock_func in
2532  times)
2533    AC_DEFINE(OS_MONOTONIC_TIME_USING_TIMES, [1], [Define if you want to implement erts_os_monotonic_time() using times()])
2534    ;;
2535  mach_clock_get_time)
2536    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()])
2537    ;;
2538  clock_gettime)
2539    AC_DEFINE(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_monotonic_time() using clock_gettime()])
2540    ;;
2541  gethrtime)
2542    AC_DEFINE(OS_MONOTONIC_TIME_USING_GETHRTIME,  [1], [Define if you want to implement erts_os_monotonic_time() using gethrtime()])
2543    ;;
2544  *)
2545    ;;
2546esac
2547
2548if test $erl_corrected_monotonic_clock = yes; then
2549  AC_DEFINE(ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME, [1], [Define if OS monotonic clock is corrected])
2550fi
2551
2552if test $erl_monotonic_clock_low_resolution = yes; then
2553  AC_DEFINE(ERTS_HAVE_LOW_RESOLUTION_OS_MONOTONIC_LOW, [1], [Define if you have a low resolution OS monotonic clock])
2554fi
2555
2556xrtlib=
2557if test "$erl_monotonic_clock_lib" != ""; then
2558   xrtlib="$erl_monotonic_clock_lib"
2559fi
2560if test "$erl_wall_clock_lib" != ""; then
2561   xrtlib="$erl_wall_clock_lib"
2562fi
2563if test "x$erl_monotonic_clock_id" != "x"; then
2564    AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID_STR, ["$erl_monotonic_clock_id"], [Define as a string of monotonic clock id to use])
2565    AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID, [$erl_monotonic_clock_id], [Define to monotonic clock id to use])
2566fi
2567
2568if test $erl_cv_clock_gettime_monotonic_raw = yes; then
2569  AC_DEFINE(HAVE_CLOCK_GETTIME_MONOTONIC_RAW, [1], [Define if you have clock_gettime(CLOCK_MONOTONIC_RAW, _)])
2570fi
2571
2572ERL_MONOTONIC_CLOCK(high_resolution, undefined, no)
2573
2574case $erl_monotonic_clock_low_resolution-$erl_monotonic_clock_func in
2575  no-mach_clock_get_time)
2576    monotonic_hrtime=yes
2577    AC_DEFINE(SYS_HRTIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_hrtime() using mach clock_get_time()])
2578    ;;
2579  no-clock_gettime)
2580    monotonic_hrtime=yes
2581    AC_DEFINE(SYS_HRTIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_hrtime() using clock_gettime()])
2582    ;;
2583  no-gethrtime)
2584    monotonic_hrtime=yes
2585    AC_DEFINE(SYS_HRTIME_USING_GETHRTIME,  [1], [Define if you want to implement erts_os_hrtime() using gethrtime()])
2586    ;;
2587  *)
2588    monotonic_hrtime=no
2589    ;;
2590esac
2591
2592if test $monotonic_hrtime = yes; then
2593    AC_DEFINE(HAVE_MONOTONIC_ERTS_SYS_HRTIME, [1], [Define if you have a monotonic erts_os_hrtime() implementation])
2594fi
2595
2596if test "x$erl_monotonic_clock_id" != "x"; then
2597    AC_DEFINE_UNQUOTED(HRTIME_CLOCK_ID_STR, ["$erl_monotonic_clock_id"], [Define as a string of monotonic clock id to use])
2598    AC_DEFINE_UNQUOTED(HRTIME_CLOCK_ID, [$erl_monotonic_clock_id], [Define to monotonic clock id to use])
2599fi
2600
2601
2602dnl
2603dnl Check if gethrvtime is working, and if to use procfs ioctl
2604dnl or (yet to be written) write to the procfs ctl file.
2605dnl
2606
2607AC_MSG_CHECKING([if gethrvtime works and how to use it])
2608AC_TRY_RUN([
2609/* gethrvtime procfs ioctl test */
2610/* These need to be undef:ed to not break activation of
2611 * micro level process accounting on /proc/self
2612 */
2613#ifdef _LARGEFILE_SOURCE
2614#  undef _LARGEFILE_SOURCE
2615#endif
2616#ifdef _FILE_OFFSET_BITS
2617#  undef _FILE_OFFSET_BITS
2618#endif
2619#include <stdlib.h>
2620#include <unistd.h>
2621#include <string.h>
2622#include <stdio.h>
2623#include <sys/time.h>
2624#include <sys/types.h>
2625#include <sys/stat.h>
2626#include <sys/signal.h>
2627#include <sys/fault.h>
2628#include <sys/syscall.h>
2629#include <sys/procfs.h>
2630#include <fcntl.h>
2631
2632int main() {
2633    long msacct = PR_MSACCT;
2634    int fd;
2635    long long start, stop;
2636    int i;
2637    pid_t pid = getpid();
2638    char proc_self[30] = "/proc/";
2639
2640    sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
2641    if ( (fd = open(proc_self, O_WRONLY)) == -1)
2642	exit(1);
2643    if (ioctl(fd, PIOCSET, &msacct) < 0)
2644	exit(2);
2645    if (close(fd) < 0)
2646	exit(3);
2647    start = gethrvtime();
2648    for (i = 0; i < 100; i++)
2649	stop = gethrvtime();
2650    if (start == 0)
2651	exit(4);
2652    if (start == stop)
2653	exit(5);
2654    exit(0); return 0;
2655}
2656],
2657erl_gethrvtime=procfs_ioctl,
2658erl_gethrvtime=false,
2659[
2660case X$erl_xcomp_gethrvtime_procfs_ioctl in
2661    X)
2662	erl_gethrvtime=cross;;
2663    Xyes|Xno)
2664	if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
2665	    erl_gethrvtime=procfs_ioctl
2666	else
2667	    erl_gethrvtime=false
2668	fi;;
2669    *)
2670	AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
2671esac
2672])
2673
2674LIBRT=$xrtlib
2675case $erl_gethrvtime in
2676  procfs_ioctl)
2677	AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
2678		[define if gethrvtime() works and uses ioctl() to /proc/self])
2679	AC_MSG_RESULT(uses ioctl to procfs)
2680	;;
2681  *)
2682	if test $erl_gethrvtime = cross; then
2683	    erl_gethrvtime=false
2684	    AC_MSG_RESULT(cross)
2685	    AC_MSG_WARN([result 'not working' guessed because of cross compilation])
2686	else
2687	    AC_MSG_RESULT(not working)
2688	fi
2689
2690	dnl
2691	dnl Check if clock_gettime (linux) is working
2692	dnl
2693
2694	AC_MSG_CHECKING([if clock_gettime can be used to get thread CPU time])
2695	save_libs=$LIBS
2696	LIBS="-lrt"
2697	AC_TRY_RUN([
2698	#include <stdlib.h>
2699	#include <unistd.h>
2700	#include <string.h>
2701	#include <stdio.h>
2702	#include <time.h>
2703	int main() {
2704	    long long start, stop;
2705	    int i;
2706	    struct timespec tp;
2707
2708	    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp) < 0)
2709	      exit(1);
2710	    start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
2711	    for (i = 0; i < 100; i++)
2712	      clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
2713	    stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
2714	    if (start == 0)
2715	      exit(4);
2716	    if (start == stop)
2717	      exit(5);
2718	    exit(0); return 0;
2719	  }
2720	],
2721	erl_clock_gettime_cpu_time=yes,
2722	erl_clock_gettime_cpu_time=no,
2723	[
2724	case X$erl_xcomp_clock_gettime_cpu_time in
2725	    X) erl_clock_gettime_cpu_time=cross;;
2726	    Xyes|Xno) erl_clock_gettime_cpu_time=$erl_xcomp_clock_gettime_cpu_time;;
2727	    *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
2728	esac
2729	])
2730	LIBS=$save_libs
2731	AC_MSG_RESULT($erl_clock_gettime_cpu_time)
2732	case $erl_clock_gettime_cpu_time in
2733		yes)
2734			AC_DEFINE(HAVE_CLOCK_GETTIME_CPU_TIME,[],
2735				  [define if clock_gettime() works for getting thread time])
2736			LIBRT=-lrt
2737			;;
2738		cross)
2739			erl_clock_gettime_cpu_time=no
2740			AC_MSG_WARN([result no guessed because of cross compilation])
2741			;;
2742		*)
2743			;;
2744	esac
2745	;;
2746esac
2747AC_SUBST(LIBRT)
2748])dnl
2749
2750dnl ----------------------------------------------------------------------
2751dnl
2752dnl LM_TRY_ENABLE_CFLAG
2753dnl
2754dnl
2755dnl Tries a CFLAG and sees if it can be enabled without compiler errors
2756dnl $1: textual cflag to add
2757dnl $2: variable to store the modified CFLAG in
2758dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS])
2759dnl
2760dnl
2761AC_DEFUN([LM_TRY_ENABLE_CFLAG], [
2762    AC_MSG_CHECKING([if we can add $1 to $2 (via CFLAGS)])
2763    saved_CFLAGS=$CFLAGS;
2764    CFLAGS="$1 $$2";
2765    AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false)
2766    CFLAGS=$saved_CFLAGS;
2767    if test "X$can_enable_flag" = "Xtrue"; then
2768        AC_MSG_RESULT([yes])
2769        AS_VAR_SET($2, "$1 $$2")
2770    else
2771        AC_MSG_RESULT([no])
2772    fi
2773])
2774
2775AC_DEFUN([LM_CHECK_ENABLE_CFLAG], [
2776    AC_MSG_CHECKING([whether $CC accepts $1...])
2777    saved_CFLAGS=$CFLAGS;
2778    CFLAGS="$1 $CFLAGS";
2779    AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false)
2780    CFLAGS=$saved_CFLAGS;
2781    if test "X$can_enable_flag" = "Xtrue"; then
2782        AS_VAR_SET($2, true)
2783        AC_MSG_RESULT([yes])
2784    else
2785        AS_VAR_SET($2, false)
2786        AC_MSG_RESULT([no])
2787    fi
2788])
2789
2790dnl
2791dnl LM_CHECK_RUN_CFLAG
2792dnl
2793dnl As LM_CHECK_ENABLE_CFLAG but also runs the command. Required for testing
2794dnl profile-guided optimization, for which the "use" step may require that the
2795dnl binary created in the "generate" step runs.
2796dnl
2797AC_DEFUN([LM_CHECK_RUN_CFLAG], [
2798    AC_MSG_CHECKING([whether $CC accepts $1...])
2799    saved_CFLAGS=$CFLAGS;
2800    CFLAGS="$1 $CFLAGS";
2801    AC_TRY_RUN([],[return 0;],can_enable_flag=true,can_enable_flag=false)
2802    CFLAGS=$saved_CFLAGS;
2803    if test "X$can_enable_flag" = "Xtrue"; then
2804        AS_VAR_SET($2, true)
2805        AC_MSG_RESULT([yes])
2806    else
2807        AS_VAR_SET($2, false)
2808        AC_MSG_RESULT([no])
2809    fi
2810])
2811
2812dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
2813dnl                   [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
2814dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
2815dnl AC_LANG_JAVA instead...)
2816AC_DEFUN(ERL_TRY_LINK_JAVA,
2817[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
2818changequote(, )dnl
2819cat > conftest.java <<EOF
2820$1
2821class conftest { public static void main(String[] args) {
2822   $2
2823   ; return; }}
2824EOF
2825changequote([, ])dnl
2826if AC_TRY_EVAL(java_link) && test -s conftest.class; then
2827   ifelse([$3], , :, [rm -rf conftest*
2828   $3])
2829else
2830   echo "configure: failed program was:" 1>&AC_FD_CC
2831   cat conftest.java 1>&AC_FD_CC
2832   echo "configure: PATH was $PATH" 1>&AC_FD_CC
2833ifelse([$4], , , [  rm -rf conftest*
2834  $4
2835])dnl
2836fi
2837rm -f conftest*])
2838#define UNSAFE_MASK  0xc0000000 /* Mask for bits that must be constant */
2839
2840
2841dnl ----------------------------------------------------------------------
2842dnl
2843dnl LM_HARDWARE_ARCH
2844dnl
2845dnl Determine target hardware in ARCH
2846dnl
2847AC_DEFUN([LM_HARDWARE_ARCH], [
2848    AC_MSG_CHECKING([target hardware architecture])
2849    if test "x$host_alias" != "x" -a "x$host_cpu" != "x"; then
2850        chk_arch_=$host_cpu
2851    else
2852        chk_arch_=`uname -m`
2853    fi
2854
2855    case $chk_arch_ in
2856    sun4u)	ARCH=ultrasparc;;
2857    sparc64)	ARCH=sparc64;;
2858    sun4v)	ARCH=ultrasparc;;
2859    i86pc)	ARCH=x86;;
2860    i386)	ARCH=x86;;
2861    i486)	ARCH=x86;;
2862    i586)	ARCH=x86;;
2863    i686)	ARCH=x86;;
2864    x86_64)	ARCH=amd64;;
2865    amd64)	ARCH=amd64;;
2866    macppc)	ARCH=ppc;;
2867    powerpc)	ARCH=ppc;;
2868    ppc)	ARCH=ppc;;
2869    ppc64)	ARCH=ppc64;;
2870    ppc64le)	ARCH=ppc64le;;
2871    powerpc64)	ARCH=ppc64;;
2872    powerpc64le) ARCH=ppc64le;;
2873    "Power Macintosh")	ARCH=ppc;;
2874    arm64)	ARCH=arm64;;
2875    armv5b)	ARCH=arm;;
2876    armv5teb)	ARCH=arm;;
2877    armv5tel)	ARCH=arm;;
2878    armv5tejl)	ARCH=arm;;
2879    armv6l)	ARCH=arm;;
2880    armv6hl)	ARCH=arm;;
2881    armv7l)	ARCH=arm;;
2882    armv7hl)	ARCH=arm;;
2883    armv8*)	ARCH=arm;;
2884    aarch64)	ARCH=arm64;;
2885    aarch*)	ARCH=arm;;
2886    tile)	ARCH=tile;;
2887    e2k)        ARCH=e2k;;
2888    *)	 	ARCH=noarch;;
2889    esac
2890    AC_MSG_RESULT($ARCH)
2891
2892    dnl
2893    dnl Convert between x86 and amd64 based on the compiler's mode.
2894    dnl Ditto between ultrasparc and sparc64.
2895    dnl
2896    AC_MSG_CHECKING(whether compilation mode forces ARCH adjustment)
2897    case "$ARCH-$ac_cv_sizeof_void_p" in
2898    x86-8)
2899	AC_MSG_RESULT(yes: adjusting ARCH=x86 to ARCH=amd64)
2900	ARCH=amd64
2901	;;
2902    amd64-4)
2903	AC_MSG_RESULT(yes: adjusting ARCH=amd64 to ARCH=x86)
2904	ARCH=x86
2905	;;
2906    ultrasparc-8)
2907	AC_MSG_RESULT(yes: adjusting ARCH=ultrasparc to ARCH=sparc64)
2908	ARCH=sparc64
2909	;;
2910    sparc64-4)
2911	AC_MSG_RESULT(yes: adjusting ARCH=sparc64 to ARCH=ultrasparc)
2912	ARCH=ultrasparc
2913	;;
2914    ppc64-4)
2915	AC_MSG_RESULT(yes: adjusting ARCH=ppc64 to ARCH=ppc)
2916	ARCH=ppc
2917	;;
2918    ppc-8)
2919	AC_MSG_RESULT(yes: adjusting ARCH=ppc to ARCH=ppc64)
2920	ARCH=ppc64
2921	;;
2922    arm-8)
2923	AC_MSG_RESULT(yes: adjusting ARCH=arm to ARCH=arm64)
2924	ARCH=arm64
2925	;;
2926    *)
2927	AC_MSG_RESULT(no: ARCH is $ARCH)
2928	;;
2929    esac
2930
2931    AC_SUBST(ARCH)
2932])
2933
2934dnl
2935dnl--------------------------------------------------------------------
2936dnl Dynamic Erlang Drivers
2937dnl
2938dnl Linking to produce dynamic Erlang drivers to be loaded by Erlang's
2939dnl Dynamic Driver Loader and Linker (DDLL). Below the prefix DED is an
2940dnl abbreviation for `Dynamic Erlang Driver'.
2941dnl
2942dnl For DED we need something quite sloppy, which allows undefined references
2943dnl (notably driver functions) in the resulting shared library.
2944dnl Example of Makefile rule (and settings of macros):
2945dnl
2946dnl LIBS = @LIBS@
2947dnl LD = @DED_LD@
2948dnl LDFLAGS = @DED_LDFLAGS@
2949dnl soname = @ldsoname@
2950dnl
2951dnl my_drv.so:   my_drv.o my_utils.o
2952dnl              $(LD) $(LDFLAGS) $(soname) $@ -o $@ $^ -lc $(LIBS)
2953dnl
2954dnl--------------------------------------------------------------------
2955dnl
2956
2957AC_DEFUN(ERL_DED,
2958	[
2959
2960USER_LD=$LD
2961USER_LDFLAGS="$LDFLAGS"
2962
2963LM_CHECK_THR_LIB
2964
2965DED_CC=$CC
2966DED_GCC=$GCC
2967
2968DED_CFLAGS=
2969DED_OSTYPE=unix
2970case $host_os in
2971     linux*)
2972	DED_CFLAGS="-D_GNU_SOURCE" ;;
2973     win32)
2974	DED_CFLAGS="-D_WIN32_WINNT=0x0600 -DWINVER=0x0600"
2975        DED_OSTYPE=win32 ;;
2976     *)
2977        ;;
2978esac
2979
2980
2981DED_WARN_FLAGS="-Wall -Wstrict-prototypes"
2982case "$host_cpu" in
2983  tile*)
2984    # tile-gcc is a bit stricter with -Wmissing-prototypes than other gccs,
2985    # and too strict for our taste.
2986    ;;
2987  *)
2988    DED_WARN_FLAGS="$DED_WARN_FLAGS -Wmissing-prototypes";;
2989esac
2990
2991LM_TRY_ENABLE_CFLAG([-Wdeclaration-after-statement], [DED_WARN_FLAGS])
2992
2993LM_TRY_ENABLE_CFLAG([-Werror=return-type], [DED_WERRORFLAGS])
2994LM_TRY_ENABLE_CFLAG([-Werror=implicit], [DED_WERRORFLAGS])
2995LM_TRY_ENABLE_CFLAG([-Werror=undef], [DED_WERRORFLAGS])
2996
2997DED_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"
2998DED_INCLUDE=$DED_SYS_INCLUDE
2999
3000if test "$THR_DEFS" = ""; then
3001    DED_THR_DEFS="-D_THREAD_SAFE -D_REENTRANT"
3002else
3003    DED_THR_DEFS="$THR_DEFS"
3004fi
3005# DED_EMU_THR_DEFS=$EMU_THR_DEFS
3006DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
3007if test "x$GCC" = xyes; then
3008    # Use -fno-common for gcc, that is link error if multiple definitions of
3009    # global variables are encountered. This is ISO C compliant.
3010    # Until version 10, gcc has had -fcommon as default, which allows and merges
3011    # such dubious duplicates.
3012    LM_TRY_ENABLE_CFLAG([-fno-common], [DED_CFLAGS])
3013
3014    DED_STATIC_CFLAGS="$DED_CFLAGS"
3015    DED_CFLAGS="$DED_CFLAGS -fPIC"
3016    # Remove -fPIE and -fno-PIE
3017    DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
3018fi
3019
3020DED_EXT=so
3021case $host_os in
3022    win32) DED_EXT=dll;;
3023    darwin*)
3024	DED_CFLAGS="$DED_CFLAGS -fno-common"
3025	DED_STATIC_CFLAGS="$DED_STATIC_CFLAGS -fno-common";;
3026    *)
3027	;;
3028esac
3029
3030DED_STATIC_CFLAGS="$DED_STATIC_CFLAGS -DSTATIC_ERLANG_NIF -DSTATIC_ERLANG_DRIVER"
3031
3032if test "$CFLAG_RUNTIME_LIBRARY_PATH" = ""; then
3033
3034  CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-R"
3035  case $host_os in
3036    darwin*)
3037	CFLAG_RUNTIME_LIBRARY_PATH=
3038	;;
3039    win32)
3040	CFLAG_RUNTIME_LIBRARY_PATH=
3041	;;
3042    osf*)
3043	CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-rpath,"
3044	;;
3045    *)
3046	;;
3047  esac
3048
3049fi
3050
3051# If DED_LD is set in environment, we expect all DED_LD* variables
3052# to be specified (cross compiling)
3053if test "x$DED_LD" = "x"; then
3054
3055DED_LDFLAGS_CONFTEST=
3056
3057DED_LD_FLAG_RUNTIME_LIBRARY_PATH="-R"
3058case $host_os in
3059	win32)
3060		DED_LD="ld.sh"
3061		DED_LDFLAGS="-dll"
3062		DED_LD_FLAG_RUNTIME_LIBRARY_PATH=
3063	;;
3064	solaris2*|sysv4*)
3065		DED_LDFLAGS="-G"
3066		if test X${enable_m64_build} = Xyes; then
3067			DED_LDFLAGS="-64 $DED_LDFLAGS"
3068		fi
3069	;;
3070	aix*|os400*)
3071		DED_LDFLAGS="-G -bnoentry -bexpall"
3072	;;
3073	freebsd2*)
3074		# Non-ELF GNU linker
3075		DED_LDFLAGS="-Bshareable"
3076	;;
3077	darwin*)
3078		# Mach-O linker: a shared lib and a loadable
3079		# object file is not the same thing.
3080		DED_LDFLAGS="-bundle -bundle_loader ${ERL_TOP}/bin/$host/beam.smp"
3081		# DED_LDFLAGS_CONFTEST is for use in configure tests only. We
3082		# cannot use DED_LDFLAGS in configure tests since beam.smp has not
3083		# been built yet...
3084		DED_LDFLAGS_CONFTEST="-bundle"
3085		if test X${enable_m64_build} = Xyes; then
3086		  DED_LDFLAGS="-m64 $DED_LDFLAGS"
3087		else
3088		  if test X${enable_m32_build} = Xyes; then
3089		    DED_LDFLAGS="-m32 $DED_LDFLAGS"
3090		  else
3091		    AC_CHECK_SIZEOF(void *)
3092		    case "$ac_cv_sizeof_void_p" in
3093		      8)
3094			DED_LDFLAGS="-m64 $DED_LDFLAGS";;
3095		      *)
3096		        ;;
3097		    esac
3098		  fi
3099		fi
3100		DED_LD="$CC"
3101		DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
3102	;;
3103	linux*)
3104		DED_LD="$CC"
3105		DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
3106		DED_LDFLAGS="-shared -Wl,-Bsymbolic"
3107		if test X${enable_m64_build} = Xyes; then
3108			DED_LDFLAGS="-m64 $DED_LDFLAGS"
3109		fi;
3110		if test X${enable_m32_build} = Xyes; then
3111			DED_LDFLAGS="-m32 $DED_LDFLAGS"
3112		fi
3113	;;
3114	freebsd*|dragonfly*)
3115		DED_LD="$CC"
3116		DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
3117		DED_LDFLAGS="-shared"
3118		if test X${enable_m64_build} = Xyes; then
3119			DED_LDFLAGS="-m64 $DED_LDFLAGS"
3120		fi;
3121		if test X${enable_m32_build} = Xyes; then
3122			DED_LDFLAGS="-m32 $DED_LDFLAGS"
3123		fi
3124	;;
3125	openbsd*)
3126		DED_LD="$CC"
3127		DED_LD_FLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
3128		DED_LDFLAGS="-shared"
3129	;;
3130	osf*)
3131		# NOTE! Whitespace after -rpath is important.
3132		DED_LD_FLAG_RUNTIME_LIBRARY_PATH="-rpath "
3133		DED_LDFLAGS="-shared -expect_unresolved '*'"
3134	;;
3135	*)
3136		# assume GNU linker and ELF
3137		DED_LDFLAGS="-shared"
3138		# GNU linker has no option for 64bit build, should not propagate -m64
3139	;;
3140esac
3141
3142if test "$DED_LD" = "" && test "$USER_LD" != ""; then
3143    DED_LD="$USER_LD"
3144    DED_LDFLAGS="$USER_LDFLAGS $DED_LDFLAGS"
3145fi
3146
3147DED_LIBS=$LIBS
3148
3149fi # "x$DED_LD" = "x"
3150
3151test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
3152
3153AC_CHECK_TOOL(DED_LD, ld, false)
3154test "$DED_LD" != "false" || AC_MSG_ERROR([No linker found])
3155
3156AC_MSG_CHECKING(for static compiler flags)
3157DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
3158AC_MSG_RESULT([$DED_STATIC_CFLAGS])
3159AC_MSG_CHECKING(for basic compiler flags for loadable drivers)
3160DED_BASIC_CFLAGS=$DED_CFLAGS
3161AC_MSG_RESULT([$DED_CFLAGS])
3162AC_MSG_CHECKING(for compiler flags for loadable drivers)
3163DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
3164AC_MSG_RESULT([$DED_CFLAGS])
3165AC_MSG_CHECKING(for linker for loadable drivers)
3166AC_MSG_RESULT([$DED_LD])
3167AC_MSG_CHECKING(for linker flags for loadable drivers)
3168AC_MSG_RESULT([$DED_LDFLAGS])
3169AC_MSG_CHECKING(for 'runtime library path' linker flag)
3170if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
3171	AC_MSG_RESULT([$DED_LD_FLAG_RUNTIME_LIBRARY_PATH])
3172else
3173	AC_MSG_RESULT([not found])
3174fi
3175
3176AC_SUBST(DED_CC)
3177AC_SUBST(DED_GCC)
3178AC_SUBST(DED_EXT)
3179AC_SUBST(DED_SYS_INCLUDE)
3180AC_SUBST(DED_INCLUDE)
3181AC_SUBST(DED_BASIC_CFLAGS)
3182AC_SUBST(DED_CFLAGS)
3183AC_SUBST(DED_STATIC_CFLAGS)
3184AC_SUBST(DED_WARN_FLAGS)
3185AC_SUBST(DED_WERRORFLAGS)
3186AC_SUBST(DED_LD)
3187AC_SUBST(DED_LDFLAGS)
3188AC_SUBST(DED_LD_FLAG_RUNTIME_LIBRARY_PATH)
3189AC_SUBST(DED_LIBS)
3190AC_SUBST(DED_THR_DEFS)
3191AC_SUBST(DED_OSTYPE)
3192
3193])
3194