blob: 29c930da93213c6edd7a198b77dbd2adfe321d5b [file] [log] [blame]
dnl Defines the macro CAIRO_CONFIGURE_PTHREAD to find a suitable
dnl pthread implementation. There are two levels of pthread conformance
dnl we are looking for:
dnl
dnl a) A minimal level denoted by -DCAIRO_HAS_PTHREAD=1: This level
dnl requires mutex and recursive mutexattr support. If possible we try
dnl to use weakly linked stubs from libc over the real pthread library.
dnl This level is required by the cairo library proper. If the user
dnl invokes configure with --enable-pthread=yes or
dnl --enable-pthread=always then we avoid trying to use weak stubs.
dnl
dnl b) A full level denoted by -DCAIRO_HAS_REAL_PTHREAD=1: This level
dnl requires full support from a real pthread library, including thread
dnl creation, joins, thread attribtues, etc. This level is required by
dnl multithreaded applications using cairo, such as the test suite
dnl binaries and cairo utilities.
dnl
dnl Usage:
dnl CAIRO_ENABLE(pthread, pthread, <default yes|no|auto|always>,
dnl [CAIRO_CONFIGURE_PTHREAD])
dnl
dnl This should be invoked near the end of configure.ac so that
dnl the pthread specific CFLAGS and LIBS end up at the front
dnl of CAIRO_CFLAGS and CAIRO_LIBS -- this helps ensure that we
dnl really do get non-weak symbols from the actual pthread library
dnl rather than possible stubs in other libraries.
dnl
dnl The user can override the choices made by
dnl CAIRO_CONFIGURE_PTHREAD by using --enable-pthread=yes and
dnl giving PTHREAD_CFLAGS and PTHREAD_LIBS to configure.
dnl
dnl Sets environment variables:
dnl use_pthread="yes" | "no (<errmsg>)"
dnl have_pthread="yes" | "no (<errmsg)"
dnl have_real_pthread="yes" | "no (<errmsg)"
dnl pthread_{CFLAGS,LIBS,REQUIRES}
dnl real_pthread_{CFLAGS,LIBS}
dnl
dnl Autoconfigured defines in config.h (conditional):
dnl CAIRO_HAS_PTHREAD
dnl CAIRO_HAS_REAL_PTHREAD
dnl
dnl -----------------------------------------------------------------------
dnl A program to test all the pthread features we need to be able to
dnl compile libcairo itself. We could test the features independently,
dnl but we need all of them anyway.
m4_define([libcairo_pthread_program],[dnl
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* for PTHREAD_MUTEX_INITIALIZER under linux */
#endif
#include <pthread.h>
pthread_mutex_t test_mutex_initializer = PTHREAD_MUTEX_INITIALIZER;
int test_mutex (void)
{
int x = 0;
pthread_mutex_t mutex;
x |= pthread_mutex_init (&mutex, NULL);
x |= pthread_mutex_lock (&mutex);
x |= pthread_mutex_unlock (&mutex);
x |= pthread_mutex_destroy (&mutex);
return 0;
}
int test_mutex_attr (void)
{
int x = 0;
pthread_mutexattr_t attr;
pthread_mutex_t mutex;
x |= pthread_mutexattr_init (&attr);
x |= pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
x |= pthread_mutex_init (&mutex, &attr);
x |= pthread_mutex_lock (&mutex);
x |= pthread_mutex_unlock (&mutex);
x |= pthread_mutex_destroy (&mutex);
x |= pthread_mutexattr_destroy (&attr);
return x;
}])
dnl -----------------------------------------------------------------------
dnl A program to test all the features we want to be able to run the test
dnl suite or other thready cairo applications that want real threads.
m4_define([testsuite_pthread_program],[dnl
libcairo_pthread_program
pthread_once_t once_control = PTHREAD_ONCE_INIT;
void test_once_init (void) {}
int test_once (void)
{
return pthread_once (&once_control, test_once_init);
}
pthread_key_t test_specific_key;
int test_specific (void)
{
int x = 0;
x |= pthread_key_create (&test_specific_key, NULL);
x |= pthread_setspecific (test_specific_key, NULL);
x |= pthread_getspecific (test_specific_key) != NULL;
return x;
}
void cleaner (void *arg) { (void)arg; }
void *
test_thread_main (void *arg)
{
pthread_cleanup_push (cleaner, arg);
pthread_exit (arg);
pthread_cleanup_pop (1);
return arg;
}
int
test_threads (void)
{
int x = 0;
pthread_t thread;
pthread_attr_t attr;
void *arg = NULL;
x |= pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
x |= pthread_create (&thread, &attr, test_thread_main, arg);
x |= pthread_equal (pthread_self(), thread);
x |= pthread_join (thread, &arg);
x |= pthread_attr_destroy (&attr);
return x;
}])
dnl -----------------------------------------------------------------------
dnl CAIRO_CHECK_PTHREAD(tag, cflags, libs, program, true-action, false-action)
dnl Set <tag>_{CFLAGS,LIBS} to {<cflags>,<libs>} if we can compile and link
dnl <program> with the given flags and libs. Execute <true-action> on
dnl success and <false-action> on failure.
AC_DEFUN([CAIRO_CHECK_PTHREAD],[dnl
CAIRO_CC_TRY_LINK_WITH_ENV_SILENT(
[CFLAGS="$CFLAGS $2";
LIBS="$LIBS $3"],
[$4],
[$1_CFLAGS="$2";
$1_LIBS="$3";
$5],
[$1_CFLAGS="";
$1_LIBS="";
$6])
])
dnl CAIRO_CONFIGURE_PTHREADS(): Look for pthreads.
dnl
dnl If the user specifies PTHREAD_CFLAGS and PTHREAD_LIBS then we use
dnl those. Otherwise we try CFLAGS=-D_REENTRANT and LIBS=-lpthread for
dnl full pthread support, and look for stubs in libc for the minimal
dnl pthread support.
dnl
dnl CFLAGS=-D_REENTRANT LIBS=-lpthread has been tested to work on:
dnl
dnl Solaris 9 (5.9) Sun C 5.8 Patch 121015-04 2007/01/10
dnl OpenSolaris (5.11) Sun C 5.9 Patch 124868-08 2008/11/25
dnl OpenSolaris (5.11) clang version 1.1 (trunk 90017)
dnl Tru64/OSF1 V5.1 Compaq C V6.5-003
dnl Mac OS X 10.5.5 gcc 4.0.1 (Apple Inc. build 5465)
dnl Mac OS X 10.6 gcc 4.2.1 (Apple Inc. build 5659)
dnl FreeBSD 7.2 gcc 4.2
dnl OpenBSD 4.5 gcc 3.3.5 (propolice)
dnl Debian Linux (Etch) gcc 4.3
dnl
dnl Thread support is also in various libcs directly, so often using no
dnl flags at all works as well, but unfortunately Solaris 9 has
dnl practically _all_ of libpthread stubbed out in libc, so we cannot
dnl distinguish between a working libpthread and a stubbed out one by a
dnl link-only test.
dnl
dnl We also explicitly do not link to pthread-stubs or whatever other
dnl third-party stubs library, since that forces cairo clients to be
dnl extra careful when giving both libcairo and libpthread on the
dnl command line: the user would have to use "-lpthread -lcairo" rather
dnl than the more common "-lcairo -lpthread" to not accidentally use
dnl stubs pulled in by libcairo everywhere in the application. We
dnl might also need to have a way to teach pkg-config about library
dnl ordering constraints which aren't actual dependencies, and at this
dnl point it just starts doing my head in.
dnl
dnl If your unix-like doesn't work with the secret handshake
dnl -D_REENTRANT -lpthread and you can actually compile the rest of
dnl cairo just fine otherwise, please take a moment complain loudly
dnl to the cairo mailing list!
dnl
AC_DEFUN([CAIRO_CONFIGURE_PTHREAD],[dnl
dnl Try to use the user's PTHREAD_LIBS/CFLAGS
dnl if they're available.
if test "x$PTHREAD_CFLAGS" = "x"; then
PTHREAD_CFLAGS="-D_REENTRANT"
fi
if test "x$PTHREAD_LIBS" = "x"; then
PTHREAD_LIBS="-lpthread"
fi
dnl First try to find the real pthreads.
CAIRO_CHECK_PTHREAD(
[real_pthread], [$PTHREAD_CFLAGS], [$PTHREAD_LIBS],
[testsuite_pthread_program],
[have_real_pthread=yes],
[have_real_pthread=no])
if test "x$have_real_pthread" != "xyes"; then
dnl Give -pthread a go.
CAIRO_CHECK_PTHREAD(
[real_pthread], [-pthread], [],
[testsuite_pthread_program],
[have_real_pthread=yes],
[have_real_pthread="no (can't link with -lpthread or -pthread)"])
fi
PTHREAD_CFLAGS=
PTHREAD_LIBS=
dnl Check if we can use libc's stubs in libcairo.
dnl Only do this if the user hasn't explicitly enabled
dnl pthreads, but is relying on automatic configuration.
have_pthread="no"
if test "x$enable_pthread" != "xyes"; then
CAIRO_CHECK_PTHREAD(
[pthread], [-D_REENTRANT], [],
[libcairo_pthread_program],
[have_pthread=yes],
[])
fi
dnl Default to using the real pthreads for libcairo.
if test "x$have_pthread" != "xyes"; then
have_pthread="$have_real_pthread";
pthread_CFLAGS="$real_pthread_CFLAGS";
pthread_LIBS="$real_pthread_LIBS";
fi
dnl Tell autoconf about the results.
if test "x$have_real_pthread" = "xyes"; then
AC_DEFINE([CAIRO_HAS_REAL_PTHREAD], 1,
[Define to 1 if we have full pthread support])
fi
if test "x$have_pthread" = "xyes"; then
AC_DEFINE([CAIRO_HAS_PTHREAD], 1,
[Define to 1 f we have minimal pthread support])
fi
dnl Make sure we scored some pthreads.
if test "x$enable_pthread" = "xyes" -a "x$have_pthread" != "xyes"; then
AC_MSG_ERROR([pthread requested but not found])
fi
dnl Set the output variables for CAIRO_ENABLE.
use_pthread="$have_pthread"
pthread_REQUIRES=""
])