1# -*- Mode: c-basic-offset:4 ; indent-tabs-mode:nil ; -*-
2#
3#  (C) 2008 by Argonne National Laboratory.
4#      See COPYRIGHT in top-level directory.
5#
6
7AC_PREREQ(2.62)
8
9AC_INIT([OpenPA], [1.0.3], [https://trac.mcs.anl.gov/projects/openpa/newticket])
10dnl Set the directory that contains support scripts such as install-sh and
11dnl config.guess.  It also contains autoconf macro files.
12AC_CONFIG_AUX_DIR(confdb)
13AC_CONFIG_MACRO_DIR([confdb])
14
15AM_INIT_AUTOMAKE([-Wall -Werror foreign color-tests 1.12.3])
16
17# automake 1.12 seems to require this, but automake 1.11 doesn't recognize it
18# must come before LT_INIT
19m4_ifdef([AM_PROG_AR],[AM_PROG_AR])
20
21LT_PREREQ([2.2.6])
22
23# Bug in libtool adds -O2 and -g by default
24save_cflags=$CFLAGS
25LT_INIT(disable-shared)
26CFLAGS=$save_cflags
27
28if test -s "$srcdir/VERSION" ; then
29   . $srcdir/VERSION
30   AC_SUBST([libopa_so_version])
31else
32   AC_MSG_ERROR([Version information not found. Configuration aborted.])
33fi
34
35dnl force configure to be re-run if $top_srcdir/VERSION changes
36AC_SUBST([CONFIG_STATUS_DEPENDENCIES],['$(top_srcdir)/VERSION'])
37
38# FIXME this header needs to end up in the installation include directory in some form,
39# so we probably need to change its name to something that won't collide in the
40# global namespace. [goodell@ 2009-02-19]
41AC_CONFIG_HEADER([src/config.h])
42AH_TOP([/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
43/*
44 *  (C) 2008 by Argonne National Laboratory.
45 *      See COPYRIGHT in top-level directory.
46 */
47])
48AH_BOTTOM([])
49
50dnl Preps an opa_config.h with prefixed macros from config.h for output at
51dnl AC_OUTPUT time.  This way we can safely include opa_config.h in the
52dnl installation and include it in installed headers.
53AX_PREFIX_CONFIG_H([src/opa_config.h],[OPA])
54
55# Non-verbose make
56m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
57
58########################################################################
59
60# check if we're cross compiling
61if test "$build_alias" = "$host_alias" ; then
62  CROSS_COMPILING="no"
63else
64  CROSS_COMPILING="yes"
65fi
66
67AC_PROG_CC
68
69AC_HEADER_ASSERT
70# do we need intrin.h in here since it's a windows file?
71AC_CHECK_HEADERS([pthread.h atomic.h intrin.h inttypes.h stdint.h stddef.h])
72
73AC_C_RESTRICT
74AC_C_INLINE
75
76# Not strictly needed (autoconf docs: This macro is obsolescent, as current C
77# compilers support const. New programs need not use this macro. )
78AC_C_CONST
79
80dnl Check for presence of the pthreads library.  This is needed by the test
81dnl suite.
82AC_CHECK_LIB(pthread, pthread_create)
83
84dnl Check for presence of pthread_yield.  If not present, check for sched_yield.
85dnl These are used by the test suite.
86AC_CHECK_FUNCS(pthread_yield,
87    ,
88    [AC_CHECK_HEADER(sched.h,
89        [AC_CHECK_FUNCS(sched_yield)]
90    )]
91)
92
93if test "$ac_cv_lib_pthread_pthread_create" = yes; then
94AC_MSG_CHECKING([if 100 threads can be run at once])
95AC_RUN_IFELSE([AC_LANG_PROGRAM([[
96    #include <stddef.h>
97    #include <pthread.h>
98    pthread_mutex_t mutexus_maximus;
99    void *thread_func(void *udata) {
100        pthread_mutex_lock(&mutexus_maximus);
101        pthread_mutex_unlock(&mutexus_maximus);
102        return NULL;
103    }
104]], [[
105    int i;
106    pthread_t threads[99];
107    pthread_mutex_init(&mutexus_maximus, NULL);
108    pthread_mutex_lock(&mutexus_maximus);
109    for(i=0; i<99; i++)
110        if(pthread_create(&threads[i], NULL, thread_func, NULL)) {
111            pthread_mutex_unlock(&mutexus_maximus);
112            return 1;
113        }
114    pthread_mutex_unlock(&mutexus_maximus);
115    return 0;
116]])],
117AC_MSG_RESULT([yes])
118AC_DEFINE(MAX_NTHREADS, 100, [define to the maximum number of simultaneous threads]),
119AC_MSG_RESULT([no])
120dnl We cannot run 100 threads, check if we can run 10
121    AC_MSG_CHECKING([if 10 threads can be run at once])
122    AC_RUN_IFELSE([AC_LANG_PROGRAM([[
123        #include <stddef.h>
124        #include <pthread.h>
125        pthread_mutex_t mutexus_maximus;
126        void *thread_func(void *udata) {
127            pthread_mutex_lock(&mutexus_maximus);
128            pthread_mutex_unlock(&mutexus_maximus);
129            return NULL;
130        }
131    ]], [[[
132        int i;
133        pthread_t threads[9];
134        pthread_mutex_init(&mutexus_maximus, NULL);
135        pthread_mutex_lock(&mutexus_maximus);
136        for(i=0; i<9; i++)
137            if(pthread_create(&threads[i], NULL, thread_func, NULL)) {
138                pthread_mutex_unlock(&mutexus_maximus);
139                return 1;
140            }
141        pthread_mutex_unlock(&mutexus_maximus);
142        return 0;
143    ]]])],
144    AC_MSG_RESULT([yes])
145    AC_DEFINE(MAX_NTHREADS, 10, [define to the maximum number of simultaneous threads]),
146    AC_MSG_RESULT([no])
147    AC_DEFINE(MAX_NTHREADS, 4, [define to the maximum number of simultaneous threads]),
148    AC_MSG_RESULT([N/A])),
149AC_MSG_RESULT([N/A]))
150fi
151
152AC_CHECK_SIZEOF([void *])
153AC_CHECK_SIZEOF([int])
154
155dnl Check for __attribute__ support.  This was originally taken from
156dnl the PAC_C_GNU_ATTRIBUTE macro in mpich2.
157dnl
158dnl We start by requiring Gcc.  Some other compilers accept __attribute__
159dnl but generate warning messages, or have different interpretations
160dnl (which seems to make __attribute__ just as bad as #pragma)
161dnl For example, the Intel icc compiler accepts __attribute__ and
162dnl __attribute__((pure)) but generates warnings for __attribute__((format...))
163if test "$GCC" = "yes" ; then
164    AC_CACHE_CHECK([whether __attribute__ allowed],
165pac_cv_gnu_attr_pure,[
166AC_TRY_COMPILE([int foo(int) __attribute__ ((pure));],[int a;],
167pac_cv_gnu_attr_pure=yes,pac_cv_gnu_attr_pure=no)])
168AC_CACHE_CHECK([whether __attribute__((format)) allowed],
169pac_cv_gnu_attr_format,[
170AC_TRY_COMPILE([int foo(char *,...) __attribute__ ((format(printf,1,2)));],[int a;],
171pac_cv_gnu_attr_format=yes,pac_cv_gnu_attr_format=no)])
172    if test "$pac_cv_gnu_attr_pure" = "yes" -a "$pac_cv_gnu_attr_format" = "yes" ; then
173        AC_DEFINE(HAVE_GCC_ATTRIBUTE,1,[Define if GNU __attribute__ is supported])
174    fi
175fi
176
177dnl Check to make sure that the compiler rejects bogus inline assembly
178dnl statements.  If it does not, then we need to be careful below when
179dnl we're checking which primitives header file to use.
180AC_MSG_CHECKING([if compiler rejects bogus asm statements])
181AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
182    __asm__ __volatile__ ("ILLEGAL_ASM_STMT");
183  ]])],
184  compiler_rejects_bogus_asm=no
185  AC_MSG_RESULT([no])
186  ,
187  compiler_rejects_bogus_asm=yes
188  AC_MSG_RESULT([yes])
189)
190
191AC_ARG_WITH([atomic-primitives], [AC_HELP_STRING([--with-atomic-primitives],
192    [Force OPA to use a specific atomic primitives implementation file (default
193     is auto).  A value of 'no' forces the use of locks to implement atomic
194     primitives.  A value of 'auto_allow_emulation' will attempt to detect
195     native primitives and will fall back to lock-based emulation if none are
196     available.  Note that using locks to implement atomic primitives will have
197     a substantial impact on performance and is intended for testing only.  A
198     value of 'unsafe' will use a non-atomic version of the primitives for performance
199     in single-threaded code and meta-testing.])],
200    [AS_IF([test "$with_atomic_primitives" = "yes"], [with_atomic_primitives=auto])],
201    [with_atomic_primitives=auto]
202)
203
204
205# is set to yes by the macro below if any test ever succeeds
206non_emulated_primitives_available=no
207# is set to yes in OPA_TRY_PRIMITIVE_HEADER when a primitive
208# matching $with_atomic_primitives is checked
209checked_specified_primitive=no
210
211AC_DEFUN([OPA_PRIMITIVE_TEST_PGM], [AC_LANG_PROGRAM([[
212#define OPA_SIZEOF_INT SIZEOF_INT
213#define OPA_SIZEOF_VOID_P SIZEOF_VOID_P
214#ifndef _opa_inline
215#define _opa_inline inline
216#endif
217#ifndef _opa_restrict
218#define _opa_restrict restrict
219#endif
220#ifndef _opa_const
221#define _opa_const const
222#endif
223#ifdef HAVE_GCC_ATTRIBUTE
224#define OPA_HAVE_GCC_ATTRIBUTE 1
225#endif
226#include "opa_util.h" /* for OPA_ATTRIBUTE and friends */
227#include "primitives/$1"
228    ]],[[
229    OPA_int_t a, b;
230    int c;
231
232    OPA_store_int(&a, 0);
233    OPA_store_int(&b, 1);
234    c = OPA_load_int(&a);
235
236    OPA_add_int(&a, 10);
237    OPA_incr_int(&a);
238    OPA_decr_int(&a);
239
240    c = OPA_decr_and_test_int(&a);
241    c = OPA_fetch_and_add_int(&a, 10);
242    c = OPA_fetch_and_incr_int(&a);
243    c = OPA_fetch_and_decr_int(&a);
244
245    c = OPA_cas_int(&a, 10, 11);
246    c = OPA_swap_int(&a, OPA_load_int(&b));
247
248    OPA_write_barrier();
249    OPA_read_barrier();
250    OPA_read_write_barrier();
251     ]])]
252)
253
254dnl OPA_TRY_PRIMITIVE_HEADER([header file from src/ dir], [HAVE_ macro suffix], [feature description])
255dnl Does an AC_LINK_IFELSE() to see if the header file works
256AC_DEFUN([OPA_TRY_PRIMITIVE_HEADER],[
257if test "$with_atomic_primitives" = "auto"                 || \
258   test "$with_atomic_primitives" = "auto_allow_emulation" || \
259   test "$with_atomic_primitives" = "$1"
260then
261    checked_specified_primitive=yes
262    AC_MSG_CHECKING([for support for $3])
263    SAVE_CFLAGS="$CFLAGS"
264    CFLAGS="$CFLAGS -I${srcdir}/src"
265    AC_LINK_IFELSE([OPA_PRIMITIVE_TEST_PGM([$1])],
266        [AC_DEFINE([HAVE_$2], [1], [define to 1 if we have support for $3])
267        non_emulated_primitives_available=yes]
268        [AC_MSG_RESULT([yes])]
269    ,
270        [AC_MSG_RESULT([no])]
271    )
272    CFLAGS="$SAVE_CFLAGS"
273fi
274])
275
276dnl OPA_TRY_RUN_PRIMITIVE_HEADER([header file from src/ dir], [HAVE_ macro suffix], [feature description])
277dnl Does an AC_RUN_IFELSE() to see if the header file works, but falls back to AC_LINK_IFELSE()
278dnl if we're cross-compiling
279AC_DEFUN([OPA_TRY_RUN_PRIMITIVE_HEADER],[
280if test "$with_atomic_primitives" = "auto"                 || \
281   test "$with_atomic_primitives" = "auto_allow_emulation" || \
282   test "$with_atomic_primitives" = "$1"
283then
284    checked_specified_primitive=yes
285    AC_MSG_CHECKING([for support for $3])
286    SAVE_CFLAGS="$CFLAGS"
287    CFLAGS="$CFLAGS -I${srcdir}/src"
288    AC_RUN_IFELSE([OPA_PRIMITIVE_TEST_PGM([$1])],[
289        AC_DEFINE([HAVE_$2], [1], [define to 1 if we have support for $3])
290        non_emulated_primitives_available=yes
291        AC_MSG_RESULT([yes])]
292    ,
293        [AC_MSG_RESULT([no])]
294    ,
295        [AC_LINK_IFELSE([OPA_PRIMITIVE_TEST_PGM([$1])],[
296            AC_DEFINE([HAVE_$2], [1], [define to 1 if we have support for $3])
297            non_emulated_primitives_available=yes
298            AC_MSG_RESULT([yes])]
299        ,
300            [AC_MSG_RESULT([no])]
301        )]
302    )
303    CFLAGS="$SAVE_CFLAGS"
304fi
305])
306
307using_emulated_primitives=no
308using_unsafe_primitives=no
309
310if test "$with_atomic_primitives" = "no" ; then
311    using_emulated_primitives=yes
312    # EXPLICIT_EMULATION becomes OPA_EXPLICIT_EMULATION in the installed opa_config.h
313    AC_DEFINE([EXPLICIT_EMULATION],[1],
314              [define if lock-based emulation was explicitly requested at
315               configure time via --with-atomic-primitives=no])
316elif test "$with_atomic_primitives" = "unsafe" ; then
317    using_unsafe_primitives=yes
318else
319dnl We currently test for support of each platform or implementation by
320dnl attempting to compile the associated primitives header file.  This doesn't
321dnl feel right, but it's actually pretty effective while being fairly easy to
322dnl implement as well.  The biggest problem with this strategy is that if we are
323dnl missing some little bit of compatibility code (a missing type or header for
324dnl which we have a workaround) we could end up selecting the wrong
325dnl implementation.
326dnl
327dnl If the compiler can't tell that it's getting bad assembly, we have
328dnl no hope of being able to check what asm statements are supported
329dnl without AC_TRY_RUN().
330    if test "$compiler_rejects_bogus_asm" = "yes"  ; then
331        # if we're cross compiling, don't try the gcc_intel_32_64
332        # test, since it uses fence operations which are not supported
333        # on pre Pentium 4 machines, but it may still compile and link
334        if test "$CROSS_COMPILING" = "no" ; then
335            OPA_TRY_RUN_PRIMITIVE_HEADER([opa_gcc_intel_32_64.h], [GCC_X86_32_64], [gcc x86/x86_64 primitives])
336        fi
337        OPA_TRY_RUN_PRIMITIVE_HEADER([opa_gcc_intel_32_64_p3.h], [GCC_X86_32_64_P3], [gcc x86 primitives for pre-Pentium 4])
338        OPA_TRY_PRIMITIVE_HEADER([opa_gcc_ia64.h], [GCC_AND_IA64_ASM], [gcc ia64 primitives])
339        OPA_TRY_PRIMITIVE_HEADER([opa_gcc_ppc.h], [GCC_AND_POWERPC_ASM], [gcc PowerPC atomics])
340        OPA_TRY_PRIMITIVE_HEADER([opa_gcc_sicortex.h], [GCC_AND_SICORTEX_ASM], [gcc SiCortex atomics])
341    fi
342
343    OPA_TRY_PRIMITIVE_HEADER([opa_gcc_intrinsics.h], [GCC_INTRINSIC_ATOMICS], [gcc atomic intrinsics])
344    OPA_TRY_PRIMITIVE_HEADER([opa_nt_intrinsics.h], [NT_INTRINSICS], [Windows NT atomic intrinsics])
345    OPA_TRY_PRIMITIVE_HEADER([opa_sun_atomic_ops.h], [SUN_ATOMIC_OPS], [Sun atomic operations library])
346
347    if test "$checked_specified_primitive" = "no" ; then
348        AC_MSG_ERROR([did not find specified atomic primitives file "$with_atomic_primitives"], 1)
349    fi
350
351    if test "$non_emulated_primitives_available" = "no" ; then
352        if test "$with_atomic_primitives" = "auto_allow_emulation" ; then
353            using_emulated_primitives=yes
354        else
355            AC_MSG_ERROR([
356=======================================================
357No native supported atomic primitives were detected.
358You can use "--with-atomic-primitives=no" to emulate
359the atomic primitives using locks, but note that doing
360this will result in a substantial performance
361penalty.
362=======================================================], 1)
363        fi
364    fi
365fi
366
367internal_pkg_config_libs=
368external_pkg_config_libs=
369if test "$using_emulated_primitives" = "yes" ; then
370    AC_MSG_WARN([
371===================================================
372Using locks to implement atomic primitives.  This
373will result in a substantial impact on performance.
374Use this only for testing.
375===================================================])
376    AC_DEFINE(USE_LOCK_BASED_PRIMITIVES, 1, [define to 1 to force using lock-based atomic primitives])
377    internal_pkg_config_libs="-lpthread $internal_pkg_config_libs"
378    external_pkg_config_libs="-lopa     $external_pkg_config_libs"
379fi
380
381AC_SUBST(internal_pkg_config_libs)
382AC_SUBST(external_pkg_config_libs)
383
384if test "$using_unsafe_primitives" = "yes" ; then
385    AC_MSG_WARN([
386===================================================
387Using *UNSAFE*, *NON-ATOMIC* primitive operations.
388Use this for only for testing or for performance
389reasons in non-concurrent code.
390
391Consider yourself warned!
392===================================================])
393    AC_DEFINE([USE_UNSAFE_PRIMITIVES],[1],[define to 1 if unsafe (non-atomic) primitives should be used])
394fi
395
396dnl Check to see if we should enable strict fairness checks
397AC_MSG_CHECKING([whether to enable strict fairness checks])
398AC_ARG_ENABLE(strict-fairness-checks,
399    [AC_HELP_STRING([--enable-strict-fairness-checks],
400        [Enable stricter checks of the "fairness" of atomic operations in the
401         test suite (default is no).  A value of 'yes' will remove the calls to
402         pthread_yield() from these test routines.])],
403    [strict_fairness_checks=$enableval],
404    [strict_fairness_checks=no])
405if test "${strict_fairness_checks}" = "yes"; then
406    AC_MSG_RESULT([yes])
407    AC_DEFINE([HAVE_STRICT_FAIRNESS_CHECKS], [1],
408        [Define if strict checking of atomic operation fairness is desired])
409else
410    AC_MSG_RESULT([no])
411fi
412
413## Enable creation of libtool-style versioning or no versioning
414AC_ARG_ENABLE(versioning,
415        [AC_HELP_STRING([--enable-versioning],[Enable library versioning])],,
416        [enable_versioning=yes])
417
418if test "$enable_versioning" = "yes" ; then
419   libopa_so_versionflags="-version-info \$(libopa_so_version)"
420else
421   libopa_so_versionflags="-avoid-version"
422fi
423export libopa_so_versionflags
424AC_SUBST(libopa_so_versionflags)
425
426
427AC_CONFIG_FILES([Makefile src/Makefile test/Makefile openpa.pc])
428AC_OUTPUT
429
430