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