dnl OpenLDAP Autoconf thread check dnl dnl This work is part of OpenLDAP Software . dnl dnl Copyright 1998-2010 The OpenLDAP Foundation. dnl All rights reserved. dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted only as authorized by the OpenLDAP dnl Public License. dnl dnl A copy of this license is available in the file LICENSE-OPENLDAP in dnl this directory of the distribution or, alternatively, at dnl . dnl dnl -------------------------------------------------------------------- dnl This file is a fragment of OpenLDAP's build/openldap.m4 and some dnl fragments of OpenLDAP's configure.ac . # OL_THREAD_CHECK([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) AC_DEFUN([OL_THREAD_CHECK], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG([C]) OL_ARG_WITH(threads,[ --with-threads with threads], auto, [auto nt posix mach pth lwp yes no manual] ) case "$ol_with_threads$host" in auto*-*-solaris2.[[0-6]]) dnl signals sometimes delivered to wrong thread with Solaris 2.6 ol_with_threads=no ;; esac dnl AIX Thread requires we use cc_r or xlc_r. dnl But only do this IF AIX and CC is not set dnl and threads are auto|yes|posix. dnl dnl If we find cc_r|xlc_r, force pthreads and assume dnl pthread_create is in $LIBS (ie: don't bring in dnl any additional thread libraries) dnl If we do not find cc_r|xlc_r, disable threads ol_aix_threads=no case "$host" in *-*-aix*) dnl all AIX is not a good idea. if test -z "$CC" ; then case "$ol_with_threads" in auto | yes | posix) ol_aix_threads=yes ;; esac fi ;; esac if test $ol_aix_threads = yes ; then if test -z "${CC}" ; then AC_CHECK_PROGS(CC,cc_r xlc_r cc) if test "$CC" = cc ; then dnl no CC! don't allow --with-threads if test $ol_with_threads != auto ; then AC_MSG_ERROR([--with-threads requires cc_r (or other suitable compiler) on AIX]) else AC_MSG_WARN([disabling threads, no cc_r on AIX]) fi ol_with_threads=no fi fi case ${CC} in cc_r | xlc_r) ol_with_threads=posix ol_cv_pthread_create=yes ;; esac fi dnl ---------------------------------------------------------------- dnl Threads? ol_link_threads=no dnl ol_with_yielding_select=${ol_with_yielding_select:-auto} OL_ARG_WITH(yielding_select,[ --with-yielding-select with yielding select], auto, [auto yes no manual] ) case $ol_with_threads in auto | yes | nt) OL_NT_THREADS if test "$ol_cv_nt_threads" = yes ; then ol_link_threads=nt ol_with_threads=found ol_with_yielding_select=yes AC_DEFINE([HAVE_NT_SERVICE_MANAGER], [1], [if you have NT Service Manager]) AC_DEFINE([HAVE_NT_EVENT_LOG], [1], [if you have NT Event Log]) fi if test $ol_with_threads = nt ; then AC_MSG_ERROR([could not locate NT Threads]) fi ;; esac case $ol_with_threads in auto | yes | posix) AC_CHECK_HEADERS(pthread.h) if test $ac_cv_header_pthread_h = yes ; then OL_POSIX_THREAD_VERSION if test $ol_cv_pthread_version != 0 ; then AC_DEFINE_UNQUOTED([HAVE_PTHREADS], [$ol_cv_pthread_version], [define to pthreads API spec revision]) else AC_MSG_ERROR([unknown pthread version]) fi # consider threads found ol_with_threads=found OL_HEADER_LINUX_THREADS OL_HEADER_GNU_PTH_PTHREAD_H if test $ol_cv_header_gnu_pth_pthread_h = no ; then AC_CHECK_HEADERS(sched.h) fi dnl Now the hard part, how to link? dnl dnl currently supported checks: dnl dnl Check for no flags dnl pthread_create() in $LIBS dnl dnl Check special pthread (final) flags dnl [skipped] pthread_create() with -mt (Solaris) [disabled] dnl pthread_create() with -kthread (FreeBSD) dnl pthread_create() with -pthread (FreeBSD/Digital Unix) dnl pthread_create() with -pthreads (?) dnl pthread_create() with -mthreads (AIX) dnl pthread_create() with -thread (?) dnl dnl Check pthread (final) libraries dnl pthread_mutex_unlock() in -lpthread -lmach -lexc -lc_r (OSF/1) dnl pthread_mutex_lock() in -lpthread -lmach -lexc (OSF/1) dnl [skipped] pthread_mutex_trylock() in -lpthread -lexc (OSF/1) dnl pthread_join() -Wl,-woff,85 -lpthread (IRIX) dnl pthread_create() in -lpthread (many) dnl pthread_create() in -lc_r (FreeBSD) dnl dnl Check pthread (draft4) flags (depreciated) dnl pthread_create() with -threads (OSF/1) dnl dnl Check pthread (draft4) libraries (depreciated) dnl pthread_mutex_unlock() in -lpthreads -lmach -lexc -lc_r (OSF/1) dnl pthread_mutex_lock() in -lpthreads -lmach -lexc (OSF/1) dnl pthread_mutex_trylock() in -lpthreads -lexc (OSF/1) dnl pthread_create() in -lpthreads (many) dnl dnl pthread_create in $LIBS AC_CACHE_CHECK([for pthread_create in default libraries], ol_cv_pthread_create,[ AC_RUN_IFELSE([OL_PTHREAD_TEST_PROGRAM], [ol_cv_pthread_create=yes], [ol_cv_pthread_create=no], [AC_TRY_LINK(OL_PTHREAD_TEST_INCLUDES,OL_PTHREAD_TEST_FUNCTION, [ol_cv_pthread_create=yes], [ol_cv_pthread_create=no])])]) if test $ol_cv_pthread_create != no ; then ol_link_threads=posix ol_link_pthreads="" fi dnl OL_PTHREAD_TRY([-mt], [ol_cv_pthread_mt]) OL_PTHREAD_TRY([-kthread], [ol_cv_pthread_kthread]) OL_PTHREAD_TRY([-pthread], [ol_cv_pthread_pthread]) OL_PTHREAD_TRY([-pthreads], [ol_cv_pthread_pthreads]) OL_PTHREAD_TRY([-mthreads], [ol_cv_pthread_mthreads]) OL_PTHREAD_TRY([-thread], [ol_cv_pthread_thread]) OL_PTHREAD_TRY([-lpthread -lmach -lexc -lc_r], [ol_cv_pthread_lpthread_lmach_lexc_lc_r]) OL_PTHREAD_TRY([-lpthread -lmach -lexc], [ol_cv_pthread_lpthread_lmach_lexc]) dnl OL_PTHREAD_TRY([-lpthread -lexc], dnl [ol_cv_pthread_lpthread_lexc]) OL_PTHREAD_TRY([-lpthread -Wl,-woff,85], [ol_cv_pthread_lib_lpthread_woff]) OL_PTHREAD_TRY([-lpthread], [ol_cv_pthread_lpthread]) OL_PTHREAD_TRY([-lc_r], [ol_cv_pthread_lc_r]) OL_PTHREAD_TRY([-threads], [ol_cv_pthread_threads]) OL_PTHREAD_TRY([-lpthreads -lmach -lexc -lc_r], [ol_cv_pthread_lpthreads_lmach_lexc_lc_r]) OL_PTHREAD_TRY([-lpthreads -lmach -lexc], [ol_cv_pthread_lpthreads_lmach_lexc]) OL_PTHREAD_TRY([-lpthreads -lexc], [ol_cv_pthread_lpthreads_lexc]) OL_PTHREAD_TRY([-lpthreads],[ol_cv_pthread_lib_lpthreads]) AC_MSG_NOTICE([ol_link_threads: <$ol_link_threads> ol_link_pthreads <$ol_link_pthreads>]) if test $ol_link_threads != no ; then LTHREAD_LIBS="$LTHREAD_LIBS $ol_link_pthreads" dnl save flags save_CPPFLAGS="$CPPFLAGS" save_LIBS="$LIBS" LIBS="$LTHREAD_LIBS $LIBS" dnl All POSIX Thread (final) implementations should have dnl sched_yield instead of pthread yield. dnl check for both, and thr_yield for Solaris AC_CHECK_FUNCS(sched_yield pthread_yield thr_yield) if test $ac_cv_func_sched_yield = no && test $ac_cv_func_pthread_yield = no && test $ac_cv_func_thr_yield = no ; then dnl Digital UNIX has sched_yield() in -lrt AC_CHECK_LIB(rt, sched_yield, [LTHREAD_LIBS="$LTHREAD_LIBS -lrt" AC_DEFINE([HAVE_SCHED_YIELD], [1], [Define if you have the sched_yield function.]) ac_cv_func_sched_yield=yes], [ac_cv_func_sched_yield=no]) fi if test $ac_cv_func_sched_yield = no && test $ac_cv_func_pthread_yield = no && test "$ac_cv_func_thr_yield" = no ; then AC_MSG_WARN([could not locate sched_yield() or pthread_yield()]) fi dnl Check functions for compatibility AC_CHECK_FUNCS(pthread_kill) dnl Check for pthread_rwlock_destroy with dnl as pthread_rwlock_t may not be defined. AC_CACHE_CHECK([for pthread_rwlock_destroy with ], [ol_cv_func_pthread_rwlock_destroy], [ dnl save the flags AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include pthread_rwlock_t rwlock; ]], [[pthread_rwlock_destroy(&rwlock);]])],[ol_cv_func_pthread_rwlock_destroy=yes],[ol_cv_func_pthread_rwlock_destroy=no]) ]) if test $ol_cv_func_pthread_rwlock_destroy = yes ; then AC_DEFINE([HAVE_PTHREAD_RWLOCK_DESTROY], [1], [define if you have pthread_rwlock_destroy function]) fi dnl Check for pthread_detach with inclusion dnl as it's symbol may have been mangled. AC_CACHE_CHECK([for pthread_detach with ], [ol_cv_func_pthread_detach], [ dnl save the flags AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #ifndef NULL #define NULL (void*)0 #endif ]], [[pthread_detach(NULL);]])],[ol_cv_func_pthread_detach=yes],[ol_cv_func_pthread_detach=no]) ]) if test $ol_cv_func_pthread_detach = no ; then AC_MSG_ERROR([could not locate pthread_detach()]) fi AC_DEFINE([HAVE_PTHREAD_DETACH], [1], [define if you have pthread_detach function]) dnl Check for setconcurreny functions AC_CHECK_FUNCS( \ pthread_setconcurrency \ pthread_getconcurrency \ thr_setconcurrency \ thr_getconcurrency \ ) OL_SYS_LINUX_THREADS OL_LINUX_THREADS if test $ol_cv_linux_threads = error; then AC_MSG_ERROR([LinuxThreads header/library mismatch]); fi AC_CACHE_CHECK([if pthread_create() works], ol_cv_pthread_create_works,[ AC_RUN_IFELSE([OL_PTHREAD_TEST_PROGRAM], [ol_cv_pthread_create_works=yes], [ol_cv_pthread_create_works=no], [dnl assume yes ol_cv_pthread_create_works=yes])]) if test $ol_cv_pthread_create_works = no ; then AC_MSG_ERROR([pthread_create is not usable, check environment settings]) fi ol_replace_broken_yield=no dnl case "$host" in dnl *-*-linux*) dnl AC_CHECK_FUNCS(nanosleep) dnl ol_replace_broken_yield=yes dnl ;; dnl esac if test $ol_replace_broken_yield = yes ; then AC_DEFINE([REPLACE_BROKEN_YIELD], [1], [define if sched_yield yields the entire process]) fi dnl Check if select causes an yield if test x$ol_with_yielding_select = xauto ; then AC_CACHE_CHECK([if select yields when using pthreads], ol_cv_pthread_select_yields,[ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include #include #ifndef NULL #define NULL (void*) 0 #endif static int fildes[2]; static void *task(p) void *p; { int i; struct timeval tv; fd_set rfds; tv.tv_sec=10; tv.tv_usec=0; FD_ZERO(&rfds); FD_SET(fildes[0], &rfds); /* we're not interested in any fds */ i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); if(i < 0) { perror("select"); exit(10); } exit(0); /* if we exit here, the select blocked the whole process */ } int main(argc, argv) int argc; char **argv; { pthread_t t; /* create a pipe to select */ if(pipe(&fildes[0])) { perror("select"); exit(1); } #ifdef HAVE_PTHREAD_SETCONCURRENCY (void) pthread_setconcurrency(2); #else #ifdef HAVE_THR_SETCONCURRENCY /* Set Solaris LWP concurrency to 2 */ thr_setconcurrency(2); #endif #endif #if HAVE_PTHREADS < 6 pthread_create(&t, pthread_attr_default, task, NULL); #else pthread_create(&t, NULL, task, NULL); #endif /* make sure task runs first */ #ifdef HAVE_THR_YIELD thr_yield(); #elif defined( HAVE_SCHED_YIELD ) sched_yield(); #elif defined( HAVE_PTHREAD_YIELD ) pthread_yield(); #endif exit(2); }]])],[ol_cv_pthread_select_yields=no],[ol_cv_pthread_select_yields=yes],[ol_cv_pthread_select_yields=cross])]) if test $ol_cv_pthread_select_yields = cross ; then AC_MSG_ERROR([crossing compiling: use --with-yielding-select=yes|no|manual]) fi if test $ol_cv_pthread_select_yields = yes ; then ol_with_yielding_select=yes fi fi dnl restore flags CPPFLAGS="$save_CPPFLAGS" LIBS="$save_LIBS" else AC_MSG_ERROR([could not locate usable POSIX Threads]) fi fi if test $ol_with_threads = posix ; then AC_MSG_ERROR([could not locate POSIX Threads]) fi ;; esac case $ol_with_threads in auto | yes | mach) dnl check for Mach CThreads AC_CHECK_HEADERS(mach/cthreads.h cthreads.h) if test $ac_cv_header_mach_cthreads_h = yes ; then ol_with_threads=found dnl check for cthreads support in current $LIBS AC_CHECK_FUNC(cthread_fork,[ol_link_threads=yes]) if test $ol_link_threads = no ; then dnl try -all_load dnl this test needs work AC_CACHE_CHECK([for cthread_fork with -all_load], [ol_cv_cthread_all_load], [ dnl save the flags save_LIBS="$LIBS" LIBS="-all_load $LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ cthread_fork((void *)0, (void *)0); ]])],[ol_cv_cthread_all_load=yes],[ol_cv_cthread_all_load=no]) dnl restore the LIBS LIBS="$save_LIBS" ]) if test $ol_cv_cthread_all_load = yes ; then LTHREAD_LIBS="$LTHREAD_LIBS -all_load" ol_link_threads=mach ol_with_threads=found fi fi elif test $ac_cv_header_cthreads_h = yes ; then dnl Hurd variant of Mach Cthreads dnl uses and -lthreads ol_with_threads=found dnl save the flags save_LIBS="$LIBS" LIBS="$LIBS -lthreads" AC_CHECK_FUNC(cthread_fork,[ol_link_threads=yes]) LIBS="$save_LIBS" if test $ol_link_threads = yes ; then LTHREAD_LIBS="-lthreads" ol_link_threads=mach ol_with_threads=found else AC_MSG_ERROR([could not link with Mach CThreads]) fi elif test $ol_with_threads = mach ; then AC_MSG_ERROR([could not locate Mach CThreads]) fi if test $ol_link_threads = mach ; then AC_DEFINE([HAVE_MACH_CTHREADS], [1], [define if you have Mach Cthreads]) elif test $ol_with_threads = found ; then AC_MSG_ERROR([could not link with Mach CThreads]) fi ;; esac case $ol_with_threads in auto | yes | pth) AC_CHECK_HEADERS(pth.h) if test $ac_cv_header_pth_h = yes ; then AC_CHECK_LIB(pth, pth_version, [have_pth=yes], [have_pth=no]) if test $have_pth = yes ; then AC_DEFINE([HAVE_GNU_PTH], [1], [if you have GNU Pth]) LTHREAD_LIBS="$LTHREAD_LIBS -lpth" ol_link_threads=pth ol_with_threads=found if test x$ol_with_yielding_select = xauto ; then ol_with_yielding_select=yes fi fi fi ;; esac case $ol_with_threads in auto | yes | lwp) dnl check for SunOS5 LWP AC_CHECK_HEADERS(thread.h synch.h) if test $ac_cv_header_thread_h = yes && test $ac_cv_header_synch_h = yes ; then AC_CHECK_LIB(thread, thr_create, [have_thr=yes], [have_thr=no]) if test $have_thr = yes ; then AC_DEFINE([HAVE_THR], [1], [if you have Solaris LWP (thr) package]) LTHREAD_LIBS="$LTHREAD_LIBS -lthread" ol_link_threads=thr if test x$ol_with_yielding_select = xauto ; then ol_with_yielding_select=yes fi dnl Check for setconcurrency functions AC_CHECK_FUNCS( \ thr_setconcurrency \ thr_getconcurrency \ ) fi fi dnl check for SunOS4 LWP AC_CHECK_HEADERS(lwp/lwp.h) if test $ac_cv_header_lwp_lwp_h = yes ; then AC_CHECK_LIB(lwp, lwp_create, [have_lwp=yes], [have_lwp=no]) if test $have_lwp = yes ; then AC_DEFINE([HAVE_LWP], [1], [if you have SunOS LWP package]) LTHREAD_LIBS="$LTHREAD_LIBS -llwp" ol_link_threads=lwp if test x$ol_with_yielding_select = xauto ; then ol_with_yielding_select=no fi fi fi ;; esac if test $ol_with_yielding_select = yes ; then AC_DEFINE([HAVE_YIELDING_SELECT], [1], [define if select implicitly yields]) fi if test $ol_with_threads = manual ; then dnl User thinks he can manually configure threads. ol_link_threads=yes AC_MSG_WARN([thread defines and link options must be set manually]) AC_CHECK_HEADERS(pthread.h sched.h) AC_CHECK_FUNCS(sched_yield pthread_yield) OL_HEADER_LINUX_THREADS AC_CHECK_HEADERS(mach/cthreads.h) AC_CHECK_HEADERS(lwp/lwp.h) AC_CHECK_HEADERS(thread.h synch.h) fi if test $ol_link_threads != no && test $ol_link_threads != nt ; then dnl needed to get reentrant/threadsafe versions dnl AC_DEFINE([REENTRANT], [1], [enable thread safety]) AC_DEFINE([_REENTRANT], [1], [enable thread safety]) AC_DEFINE([THREAD_SAFE], [1], [enable thread safety]) AC_DEFINE([_THREAD_SAFE], [1], [enable thread safety]) AC_DEFINE([THREADSAFE], [1], [enable thread safety]) AC_DEFINE([_THREADSAFE], [1], [enable thread safety]) AC_DEFINE([_SGI_MP_SOURCE], [1], [enable thread safety]) dnl The errno declaration may dependent upon _REENTRANT. dnl If it does, we must link with thread support. AC_CACHE_CHECK([for thread specific errno], [ol_cv_errno_thread_specific], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[errno = 0;]])],[ol_cv_errno_thread_specific=yes],[ol_cv_errno_thread_specific=no]) ]) dnl The h_errno declaration may dependent upon _REENTRANT. dnl If it does, we must link with thread support. AC_CACHE_CHECK([for thread specific h_errno], [ol_cv_h_errno_thread_specific], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[h_errno = 0;]])],[ol_cv_h_errno_thread_specific=yes],[ol_cv_h_errno_thread_specific=no]) ]) if test $ol_cv_errno_thread_specific != yes || test $ol_cv_h_errno_thread_specific != yes ; then LIBS="$LTHREAD_LIBS $LIBS" LTHREAD_LIBS="" fi dnl When in thread environment, use dnl #if defined( HAVE_REENTRANT_FUNCTIONS ) || defined( HAVE_FUNC_R ) dnl func_r(...); dnl #else dnl # if defined( HAVE_THREADS ) dnl /* lock */ dnl # endif dnl func(...); dnl # if defined( HAVE_THREADS ) dnl /* unlock */ dnl # endif dnl #endif dnl dnl HAVE_REENTRANT_FUNCTIONS is derived from: dnl _POSIX_REENTRANT_FUNCTIONS dnl _POSIX_THREAD_SAFE_FUNCTIONS dnl _POSIX_THREADSAFE_FUNCTIONS dnl dnl and is currently defined in dnl dnl HAVE_THREADS is defined by iff -UNO_THREADS dnl dnl libldap/*.c should only include iff dnl LDAP_R_COMPILE is defined. ie: dnl #ifdef LDAP_R_COMPILE dnl # include dnl #endif dnl dnl LDAP_R_COMPILE is defined by libldap_r/Makefile.in dnl specifically for compiling the threadsafe version of dnl the ldap library (-lldap_r). dnl dnl dnl check for reentrant/threadsafe functions dnl dnl dnl dnl note: these should only be used when linking dnl dnl with $LTHREAD_LIBS dnl dnl dnl save_CPPFLAGS="$CPPFLAGS" dnl save_LIBS="$LIBS" dnl LIBS="$LTHREAD_LIBS $LIBS" dnl AC_CHECK_FUNCS( \ dnl gmtime_r \ dnl gethostbyaddr_r gethostbyname_r \ dnl feof_unlocked unlocked_feof \ dnl putc_unlocked unlocked_putc \ dnl flockfile ftrylockfile \ dnl ) dnl CPPFLAGS="$save_CPPFLAGS" dnl LIBS="$save_LIBS" fi if test $ol_link_threads = no ; then if test $ol_with_threads = yes ; then AC_MSG_ERROR([no suitable thread support]) fi if test $ol_with_threads = auto ; then AC_MSG_WARN([no suitable thread support, disabling threads]) ol_with_threads=no fi AC_DEFINE([NO_THREADS], [1], [define if you have (or want) no threads]) LTHREAD_LIBS="" BUILD_THREAD=no else BUILD_THREAD=yes fi if test $ol_link_threads != no ; then AC_DEFINE([LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE], [1], [define to 1 if library is thread safe]) fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: case "$ol_with_threads" in no) ol_pthread_ok=no $2 ;; *) ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) ;; esac AC_LANG_RESTORE AC_SUBST(BUILD_THREAD) AC_SUBST(LTHREAD_LIBS) ])