diff --git a/Makefile.in b/Makefile.in index 572b30e..31c9b81 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,10 +92,10 @@ host_triplet = @host@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_namespace.m4 \ - $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ @@ -165,8 +165,8 @@ am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/ac/ar-lib \ $(top_srcdir)/ac/compile $(top_srcdir)/ac/config.guess \ $(top_srcdir)/ac/config.sub $(top_srcdir)/ac/install-sh \ $(top_srcdir)/ac/ltmain.sh $(top_srcdir)/ac/missing ac/ar-lib \ - ac/compile ac/config.guess ac/config.sub ac/depcomp \ - ac/install-sh ac/ltmain.sh ac/missing + ac/compile ac/config.guess ac/config.sub ac/install-sh \ + ac/ltmain.sh ac/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -295,6 +295,9 @@ PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ PACKAGE_VERSION_PATCH = @PACKAGE_VERSION_PATCH@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@ RANLIB = @RANLIB@ SED = @SED@ @@ -316,6 +319,7 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ diff --git a/aclocal.m4 b/aclocal.m4 index 3b60298..dae08a0 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1212,6 +1212,7 @@ AC_SUBST([am__untar]) m4_include([m4/ax_cxx_namespace.m4]) m4_include([m4/ax_numval.m4]) +m4_include([m4/ax_pthread.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) diff --git a/configure b/configure index 5142c35..84fb241 100755 --- a/configure +++ b/configure @@ -667,6 +667,10 @@ QUADMATH_LIBS UNICOWS_LIBS LTDL_LIBS DL_LIBS +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +ax_pthread_config LIBM WIN32_FALSE WIN32_TRUE @@ -17290,6 +17294,649 @@ esac LIBM=$LIBM + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + : +else + ax_pthread_ok=no + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + check some compiler builtins { $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memset" >&5 $as_echo_n "checking __builtin_memset... " >&6; } diff --git a/configure.ac b/configure.ac index a7624e6..c7aee5d 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,9 @@ dnl check the math library (check if -lm is needed) LT_LIB_M AC_SUBST(LIBM, $LIBM) +AX_PTHREAD() + + check some compiler builtins AC_MSG_CHECKING([__builtin_memset]) AC_COMPILE_IFELSE( diff --git a/lib/Makefile.am b/lib/Makefile.am index 2d330fe..d6e32b3 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,7 @@ AUTOMAKE_OPTIONS = nostdinc +AM_CFLAGS = $(PTHREAD_CFLAGS) + CPPFLAGS_ALL_COMMON = \ -I$(abs_builddir) \ -I$(abs_srcdir) \ @@ -67,8 +69,14 @@ libhcl_la_LDFLAGS = $(LDFLAGS_LIB_COMMON) libhcl_la_LIBADD = $(LIBADD_LIB_COMMON) libhcl_la_DEPENDENCIES = -if ENABLE_STATIC_MODULE +pkglib_LTLIBRARIES += libhcls.la +libhcls_la_SOURCES = hcl-s.c hcl-s.h +libhcls_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +libhcls_la_LDFLAGS = $(LDFLAGS_LIB_COMMON) +libhcls_la_LIBADD = $(LIBADD_LIB_COMMON) $(PTHREAD_LIBS) +libhcls_la_DEPENDENCIES = +if ENABLE_STATIC_MODULE libhcl_la_LIBADD += -lhcl-arr libhcl_la_DEPENDENCIES += $(abs_builddir)/../mod/libhcl-arr.la libhcl_la_LIBADD += -lhcl-dic @@ -77,18 +85,23 @@ libhcl_la_LIBADD += -lhcl-str libhcl_la_DEPENDENCIES += $(abs_builddir)/../mod/libhcl-str.la endif - bin_PROGRAMS = hcl -hcl_SOURCES = main.c main2.c +hcl_SOURCES = main.c hcl_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) hcl_LDFLAGS = $(LDFLAGS_LIB_COMMON) hcl_LDADD = $(LIBADD_LIB_COMMON) -lhcl #-ldyncall_s - if ENABLE_STATIC_MODULE hcl_DEPENDENCIES = libhcl.la endif - +bin_PROGRAMS += hcls +hcls_SOURCES = main2.c +hcls_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +hcls_LDFLAGS = $(LDFLAGS_LIB_COMMON) +hcls_LDADD = $(LIBADD_LIB_COMMON) $(PTHREAD_LIBS) -lhcl -lhcls #-ldyncall_s +if ENABLE_STATIC_MODULE +hcls_DEPENDENCIES = libhcl.la libhcls.la +endif install-data-hook: @echo "#ifndef _HCL_CFG_H_" > "$(DESTDIR)$(pkgincludedir)/hcl-cfg.h" diff --git a/lib/Makefile.in b/lib/Makefile.in index 04cb058..cfd9f27 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -95,15 +95,17 @@ host_triplet = @host@ @ENABLE_STATIC_MODULE_TRUE@am__append_4 = $(abs_builddir)/../mod/libhcl-arr.la \ @ENABLE_STATIC_MODULE_TRUE@ $(abs_builddir)/../mod/libhcl-dic.la \ @ENABLE_STATIC_MODULE_TRUE@ $(abs_builddir)/../mod/libhcl-str.la -bin_PROGRAMS = hcl$(EXEEXT) +bin_PROGRAMS = hcl$(EXEEXT) hcls$(EXEEXT) @ENABLE_STATIC_MODULE_FALSE@hcl_DEPENDENCIES = $(am__DEPENDENCIES_4) +@ENABLE_STATIC_MODULE_FALSE@hcls_DEPENDENCIES = $(am__DEPENDENCIES_4) \ +@ENABLE_STATIC_MODULE_FALSE@ $(am__DEPENDENCIES_1) subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_namespace.m4 \ - $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \ @@ -162,12 +164,22 @@ am__v_lt_1 = libhcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libhcl_la_LDFLAGS) $(LDFLAGS) -o $@ +am_libhcls_la_OBJECTS = libhcls_la-hcl-s.lo +libhcls_la_OBJECTS = $(am_libhcls_la_OBJECTS) +libhcls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libhcls_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) -am_hcl_OBJECTS = hcl-main.$(OBJEXT) hcl-main2.$(OBJEXT) +am_hcl_OBJECTS = hcl-main.$(OBJEXT) hcl_OBJECTS = $(am_hcl_OBJECTS) hcl_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(hcl_LDFLAGS) $(LDFLAGS) -o $@ +am_hcls_OBJECTS = hcls-main2.$(OBJEXT) +hcls_OBJECTS = $(am_hcls_OBJECTS) +hcls_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(hcls_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -202,8 +214,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libhcl_la_SOURCES) $(hcl_SOURCES) -DIST_SOURCES = $(libhcl_la_SOURCES) $(hcl_SOURCES) +SOURCES = $(libhcl_la_SOURCES) $(libhcls_la_SOURCES) $(hcl_SOURCES) \ + $(hcls_SOURCES) +DIST_SOURCES = $(libhcl_la_SOURCES) $(libhcls_la_SOURCES) \ + $(hcl_SOURCES) $(hcls_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -321,6 +335,9 @@ PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ PACKAGE_VERSION_PATCH = @PACKAGE_VERSION_PATCH@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@ RANLIB = @RANLIB@ SED = @SED@ @@ -342,6 +359,7 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -383,6 +401,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = nostdinc +AM_CFLAGS = $(PTHREAD_CFLAGS) CPPFLAGS_ALL_COMMON = \ -I$(abs_builddir) \ -I$(abs_srcdir) \ @@ -404,7 +423,7 @@ pkginclude_HEADERS = \ hcl-utl.h \ hcl.h -pkglib_LTLIBRARIES = libhcl.la +pkglib_LTLIBRARIES = libhcl.la libhcls.la libhcl_la_SOURCES = \ hcl-prv.h \ logfmtv.h \ @@ -434,11 +453,21 @@ libhcl_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) libhcl_la_LDFLAGS = $(LDFLAGS_LIB_COMMON) libhcl_la_LIBADD = $(LIBADD_LIB_COMMON) $(am__append_3) libhcl_la_DEPENDENCIES = $(am__append_4) -hcl_SOURCES = main.c main2.c +libhcls_la_SOURCES = hcl-s.c hcl-s.h +libhcls_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +libhcls_la_LDFLAGS = $(LDFLAGS_LIB_COMMON) +libhcls_la_LIBADD = $(LIBADD_LIB_COMMON) $(PTHREAD_LIBS) +libhcls_la_DEPENDENCIES = +hcl_SOURCES = main.c hcl_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) hcl_LDFLAGS = $(LDFLAGS_LIB_COMMON) hcl_LDADD = $(LIBADD_LIB_COMMON) -lhcl #-ldyncall_s @ENABLE_STATIC_MODULE_TRUE@hcl_DEPENDENCIES = libhcl.la +hcls_SOURCES = main2.c +hcls_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +hcls_LDFLAGS = $(LDFLAGS_LIB_COMMON) +hcls_LDADD = $(LIBADD_LIB_COMMON) $(PTHREAD_LIBS) -lhcl -lhcls #-ldyncall_s +@ENABLE_STATIC_MODULE_TRUE@hcls_DEPENDENCIES = libhcl.la libhcls.la all: hcl-cfg.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -526,6 +555,9 @@ clean-pkglibLTLIBRARIES: libhcl.la: $(libhcl_la_OBJECTS) $(libhcl_la_DEPENDENCIES) $(EXTRA_libhcl_la_DEPENDENCIES) $(AM_V_CCLD)$(libhcl_la_LINK) -rpath $(pkglibdir) $(libhcl_la_OBJECTS) $(libhcl_la_LIBADD) $(LIBS) + +libhcls.la: $(libhcls_la_OBJECTS) $(libhcls_la_DEPENDENCIES) $(EXTRA_libhcls_la_DEPENDENCIES) + $(AM_V_CCLD)$(libhcls_la_LINK) -rpath $(pkglibdir) $(libhcls_la_OBJECTS) $(libhcls_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ @@ -580,6 +612,10 @@ hcl$(EXEEXT): $(hcl_OBJECTS) $(hcl_DEPENDENCIES) $(EXTRA_hcl_DEPENDENCIES) @rm -f hcl$(EXEEXT) $(AM_V_CCLD)$(hcl_LINK) $(hcl_OBJECTS) $(hcl_LDADD) $(LIBS) +hcls$(EXEEXT): $(hcls_OBJECTS) $(hcls_DEPENDENCIES) $(EXTRA_hcls_DEPENDENCIES) + @rm -f hcls$(EXEEXT) + $(AM_V_CCLD)$(hcls_LINK) $(hcls_OBJECTS) $(hcls_LDADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -587,7 +623,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hcl-main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hcl-main2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hcls-main2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-bigint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-comp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-debug.Plo@am__quote@ @@ -608,6 +644,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-sym.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-utf8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-utl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcls_la-hcl-s.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -773,6 +810,13 @@ libhcl_la-utl.lo: utl.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhcl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhcl_la-utl.lo `test -f 'utl.c' || echo '$(srcdir)/'`utl.c +libhcls_la-hcl-s.lo: hcl-s.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhcls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhcls_la-hcl-s.lo -MD -MP -MF $(DEPDIR)/libhcls_la-hcl-s.Tpo -c -o libhcls_la-hcl-s.lo `test -f 'hcl-s.c' || echo '$(srcdir)/'`hcl-s.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhcls_la-hcl-s.Tpo $(DEPDIR)/libhcls_la-hcl-s.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hcl-s.c' object='libhcls_la-hcl-s.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhcls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhcls_la-hcl-s.lo `test -f 'hcl-s.c' || echo '$(srcdir)/'`hcl-s.c + hcl-main.o: main.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hcl-main.o -MD -MP -MF $(DEPDIR)/hcl-main.Tpo -c -o hcl-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hcl-main.Tpo $(DEPDIR)/hcl-main.Po @@ -787,19 +831,19 @@ hcl-main.obj: main.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hcl-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` -hcl-main2.o: main2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hcl-main2.o -MD -MP -MF $(DEPDIR)/hcl-main2.Tpo -c -o hcl-main2.o `test -f 'main2.c' || echo '$(srcdir)/'`main2.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hcl-main2.Tpo $(DEPDIR)/hcl-main2.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main2.c' object='hcl-main2.o' libtool=no @AMDEPBACKSLASH@ +hcls-main2.o: main2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcls_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hcls-main2.o -MD -MP -MF $(DEPDIR)/hcls-main2.Tpo -c -o hcls-main2.o `test -f 'main2.c' || echo '$(srcdir)/'`main2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hcls-main2.Tpo $(DEPDIR)/hcls-main2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main2.c' object='hcls-main2.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hcl-main2.o `test -f 'main2.c' || echo '$(srcdir)/'`main2.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcls_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hcls-main2.o `test -f 'main2.c' || echo '$(srcdir)/'`main2.c -hcl-main2.obj: main2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hcl-main2.obj -MD -MP -MF $(DEPDIR)/hcl-main2.Tpo -c -o hcl-main2.obj `if test -f 'main2.c'; then $(CYGPATH_W) 'main2.c'; else $(CYGPATH_W) '$(srcdir)/main2.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hcl-main2.Tpo $(DEPDIR)/hcl-main2.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main2.c' object='hcl-main2.obj' libtool=no @AMDEPBACKSLASH@ +hcls-main2.obj: main2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcls_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hcls-main2.obj -MD -MP -MF $(DEPDIR)/hcls-main2.Tpo -c -o hcls-main2.obj `if test -f 'main2.c'; then $(CYGPATH_W) 'main2.c'; else $(CYGPATH_W) '$(srcdir)/main2.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hcls-main2.Tpo $(DEPDIR)/hcls-main2.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main2.c' object='hcls-main2.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hcl-main2.obj `if test -f 'main2.c'; then $(CYGPATH_W) 'main2.c'; else $(CYGPATH_W) '$(srcdir)/main2.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hcls_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hcls-main2.obj `if test -f 'main2.c'; then $(CYGPATH_W) 'main2.c'; else $(CYGPATH_W) '$(srcdir)/main2.c'; fi` mostlyclean-libtool: -rm -f *.lo diff --git a/lib/hcl-cfg.h.in b/lib/hcl-cfg.h.in index 78cc570..99457aa 100644 --- a/lib/hcl-cfg.h.in +++ b/lib/hcl-cfg.h.in @@ -108,6 +108,12 @@ /* Define to 1 if you have the `powq' function. */ #undef HAVE_POWQ +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + /* Define to 1 if you have the `quadmath_snprintf' function. */ #undef HAVE_QUADMATH_SNPRINTF @@ -372,6 +378,10 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + /* The size of `char', as computed by sizeof. */ #undef SIZEOF_CHAR diff --git a/lib/hcl.c b/lib/hcl.c index 3c3edd2..93bee83 100644 --- a/lib/hcl.c +++ b/lib/hcl.c @@ -335,7 +335,7 @@ int hcl_setoption (hcl_t* hcl, hcl_option_t id, const void* value) return 0; case HCL_LOG_MASK: - hcl->option.log_mask = *(const int*)value; + hcl->option.log_mask = *(const unsigned int*)value; return 0; case HCL_LOG_MAXCAPA: @@ -390,7 +390,7 @@ int hcl_getoption (hcl_t* hcl, hcl_option_t id, void* value) return 0; case HCL_LOG_MASK: - *(int*)value = hcl->option.log_mask; + *(unsigned int*)value = hcl->option.log_mask; return 0; case HCL_LOG_MAXCAPA: diff --git a/lib/hcl.h b/lib/hcl.h index a7ae16a..7b80103 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1012,8 +1012,8 @@ struct hcl_t struct { - int trait; - int log_mask; + unsigned int trait; + unsigned int log_mask; hcl_oow_t log_maxcapa; hcl_oow_t dfl_symtab_size; hcl_oow_t dfl_sysdic_size; @@ -1036,8 +1036,8 @@ struct hcl_t hcl_ooch_t* ptr; hcl_oow_t len; hcl_oow_t capa; - int last_mask; - int default_type_mask; + unsigned int last_mask; + unsigned int default_type_mask; } log; /* ========================= */ diff --git a/lib/main.c b/lib/main.c index 0bcfb82..03367b3 100644 --- a/lib/main.c +++ b/lib/main.c @@ -142,7 +142,7 @@ struct xtn_t int vm_running; int logfd; - int logmask; + unsigned int logmask; int logfd_istty; int reader_istty; @@ -1557,7 +1557,7 @@ static void print_synerr (hcl_t* hcl) #define MIN_MEMSIZE 512000ul -static int main_tty (int argc, char* argv[]) +int main (int argc, char* argv[]) { hcl_t* hcl; xtn_t* xtn; @@ -1885,16 +1885,3 @@ oops: hcl_close (hcl); return -1; } - -int main_server (int argc, char* argv[]); - -int main (int argc, char* argv[]) -{ - - const char* base; - - base = get_base_name (argv[0]); - if (strcmp(base, "hcld") == 0) return main_server (argc, argv); - - return main_tty (argc, argv); -} diff --git a/lib/main2.c b/lib/main2.c index e6c1f7f..4982716 100644 --- a/lib/main2.c +++ b/lib/main2.c @@ -1,5 +1,3 @@ - - /* * $Id$ * @@ -26,8 +24,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "hcl-prv.h" +#include "hcl-s.h" #include "hcl-opt.h" +#include "hcl-utl.h" #include #include @@ -38,1083 +37,97 @@ #include -#if defined(_WIN32) -# include -# include -# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL) -# include -# define USE_LTDL -# endif -#elif defined(__OS2__) -# define INCL_DOSMODULEMGR -# define INCL_DOSPROCESS -# define INCL_DOSERRORS -# include -#elif defined(__MSDOS__) -# include +#if defined(HAVE_TIME_H) # include -#elif defined(macintosh) -# include -#else - -# if defined(HCL_ENABLE_LIBLTDL) -# include -# define USE_LTDL -# define sys_dl_error() lt_dlerror() -# define sys_dl_open(x) lt_dlopen(x) -# define sys_dl_openext(x) lt_dlopenext(x) -# define sys_dl_close(x) lt_dlclose(x) -# define sys_dl_getsym(x,n) lt_dlsym(x,n) -# elif defined(HAVE_DLFCN_H) -# include -# define USE_DLFCN -# define sys_dl_error() dlerror() -# define sys_dl_open(x) dlopen(x,RTLD_NOW) -# define sys_dl_openext(x) dlopen(x,RTLD_NOW) -# define sys_dl_close(x) dlclose(x) -# define sys_dl_getsym(x,n) dlsym(x,n) -# else -# error UNSUPPORTED DYNAMIC LINKER -# endif - -# if defined(HAVE_TIME_H) -# include -# endif -# if defined(HAVE_SYS_TIME_H) -# include -# endif -# if defined(HAVE_SIGNAL_H) -# include -# endif -# if defined(HAVE_SYS_MMAN_H) -# include -# endif - -# include -# include -# include - -# include -# include -# include -# include -# include -# include -# include +#endif +#if defined(HAVE_SYS_TIME_H) +# include +#endif +#if defined(HAVE_SIGNAL_H) +# include +#endif +#if defined(HAVE_SYS_MMAN_H) +# include #endif -#if !defined(HCL_DEFAULT_PFMODPREFIX) -# if defined(_WIN32) -# define HCL_DEFAULT_PFMODPREFIX "hcl-" -# elif defined(__OS2__) -# define HCL_DEFAULT_PFMODPREFIX "hcl" -# elif defined(__DOS__) -# define HCL_DEFAULT_PFMODPREFIX "hcl" -# else -# define HCL_DEFAULT_PFMODPREFIX "libhcl-" -# endif -#endif +#include +#include +#include -#if !defined(HCL_DEFAULT_PFMODPOSTFIX) -# if defined(_WIN32) -# define HCL_DEFAULT_PFMODPOSTFIX "" -# elif defined(__OS2__) -# define HCL_DEFAULT_PFMODPOSTFIX "" -# elif defined(__DOS__) -# define HCL_DEFAULT_PFMODPOSTFIX "" -# else -# if defined(USE_DLFCN) -# define HCL_DEFAULT_PFMODPOSTFIX ".so" -# else -# define HCL_DEFAULT_PFMODPOSTFIX "" -# endif -# endif -#endif +#include +#include +#include +#include -typedef union sck_addr_t sck_addr_t; -union sck_addr_t -{ - struct sockaddr_in in4; - struct sockaddr_in6 in6; -}; +/* ========================================================================= */ -typedef struct bb_t bb_t; -struct bb_t -{ - char buf[1024]; - hcl_oow_t pos; - hcl_oow_t len; - int fd; - hcl_bch_t* fn; -}; - -typedef struct server_proto_t server_proto_t; -typedef struct server_worker_t server_worker_t; -typedef struct server_t server_t; - -typedef struct xtn_t xtn_t; +typedef struct server_xtn_t server_xtn_t; struct xtn_t { - server_proto_t* proto; - int vm_running; - int logfd; - int logmask; + unsigned int logmask; int logfd_istty; }; -enum server_proto_token_type_t -{ - SERVER_PROTO_TOKEN_EOF, - SERVER_PROTO_TOKEN_NL, +/* ========================================================================= */ - SERVER_PROTO_TOKEN_BEGIN, - SERVER_PROTO_TOKEN_END, - SERVER_PROTO_TOKEN_SCRIPT, - SERVER_PROTO_TOKEN_EXIT, - - /*SERVER_PROTO_TOKEN_AUTH,*/ - SERVER_PROTO_TOKEN_KILL_WORKER, - SERVER_PROTO_TOKEN_SHOW_WORKERS, - - SERVER_PROTO_TOKEN_IDENT -}; - -typedef enum server_proto_token_type_t server_proto_token_type_t; - -typedef struct server_proto_token_t server_proto_token_t; -struct server_proto_token_t -{ - server_proto_token_type_t type; - hcl_ooch_t* ptr; - hcl_oow_t len; - hcl_oow_t capa; - hcl_ioloc_t loc; -}; - -enum server_proto_req_state_t -{ - SERVER_PROTO_REQ_IN_TOP_LEVEL, - SERVER_PROTO_REQ_IN_BLOCK_LEVEL -}; - -#define SERVER_PROTO_REPLY_BUF_SIZE 1300 - -enum server_proto_reply_type_t -{ - SERVER_PROTO_REPLY_SIMPLE = 0, - SERVER_PROTO_REPLY_CHUNKED -}; -typedef enum server_proto_reply_type_t server_proto_reply_type_t; - -struct server_proto_t -{ - server_worker_t* worker; - - hcl_t* hcl; - hcl_iolxc_t* lxc; - server_proto_token_t tok; - - struct - { - int state; - } req; - - struct - { - server_proto_reply_type_t type; - hcl_oow_t nchunks; - hcl_bch_t buf[SERVER_PROTO_REPLY_BUF_SIZE]; - hcl_oow_t len; - } reply; -}; - -enum server_worker_state_t -{ - SERVER_WORKER_STATE_DEAD = 0, - SERVER_WORKER_STATE_ALIVE = 1 -}; -typedef enum server_worker_state_t server_worker_state_t; - -struct server_worker_t -{ - pthread_t thr; - int sck; - /* TODO: peer address */ - - int claimed; - time_t time_created; - server_worker_state_t state; - - server_proto_t* proto; - - server_t* server; - server_worker_t* prev_worker; - server_worker_t* next_worker; -}; - -enum server_option_t -{ - SERVER_TRAIT, - SERVER_WORKER_STACK_SIZE -}; -typedef enum server_option_t server_option_t; - -enum server_trait_t -{ - SERVER_TRAIT_READABLE_PROTO = (1 << 0), - SERVER_TRAIT_USE_LARGE_PAGES = (1 << 1) -}; -typedef enum server_trait_t server_trait_t; - -struct server_t -{ - int stopreq; - - int logfd; - int logfd_istty; - - struct - { - hcl_oow_t memsize; /* hcl heap memory size */ - unsigned int dbgopt; - const char* logopt; - int logmask; - - unsigned int idle_timeout; /* idle timeout */ - size_t worker_stack_size; - - int trait; - } cfg; - - struct - { - server_worker_t* head; - server_worker_t* tail; - } worker_list[2]; - - pthread_mutex_t worker_mutex; - pthread_mutex_t log_mutex; -}; - - -int server_proto_feed_reply (server_proto_t* proto, const hcl_ooch_t* ptr, hcl_oow_t len, int escape); +static hcl_server_t* g_server = HCL_NULL; /* ========================================================================= */ -static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) +typedef void (*signal_handler_t) (int, siginfo_t*, void*); + +static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx) { - return malloc(size); + if (g_server) hcl_server_stop (g_server); } -static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) +static void set_signal (int sig, signal_handler_t handler) { - return realloc(ptr, size); + struct sigaction sa; + + memset (&sa, 0, sizeof(sa)); + /*sa.sa_handler = handler;*/ + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = handler; + sigemptyset (&sa.sa_mask); + + sigaction (sig, &sa, NULL); } -static void sys_free (hcl_mmgr_t* mmgr, void* ptr) +static void set_signal_to_ignore (int sig) { - free (ptr); + struct sigaction sa; + + memset (&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction (sig, &sa, NULL); } -static hcl_mmgr_t sys_mmgr = +static void set_signal_to_default (int sig) { - sys_alloc, - sys_realloc, - sys_free, - HCL_NULL -}; + struct sigaction sa; -/* ========================================================================= */ + memset (&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); - -#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) -# define IS_PATH_SEP(c) ((c) == '/' || (c) == '\\') -#else -# define IS_PATH_SEP(c) ((c) == '/') -#endif - -static const hcl_bch_t* get_base_name (const hcl_bch_t* path) -{ - const hcl_bch_t* p, * last = HCL_NULL; - - for (p = path; *p != '\0'; p++) - { - if (IS_PATH_SEP(*p)) last = p; - } - - return (last == HCL_NULL)? path: (last + 1); -} - -static HCL_INLINE int open_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - bb_t* bb = HCL_NULL; - -/* TOOD: support predefined include directory as well */ - if (arg->includer) - { - /* includee */ - hcl_oow_t ucslen, bcslen, parlen; - const hcl_bch_t* fn, * fb; - - #if defined(HCL_OOCH_IS_UCH) - if (hcl_convootobcstr (hcl, arg->name, &ucslen, HCL_NULL, &bcslen) <= -1) goto oops; - #else - bcslen = hcl_countbcstr (arg->name); - #endif - - fn = ((bb_t*)arg->includer->handle)->fn; - - fb = get_base_name (fn); - parlen = fb - fn; - - bb = (bb_t*)hcl_callocmem (hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (parlen + bcslen + 1))); - if (!bb) goto oops; - - bb->fn = (hcl_bch_t*)(bb + 1); - hcl_copybchars (bb->fn, fn, parlen); - #if defined(HCL_OOCH_IS_UCH) - hcl_convootobcstr (hcl, arg->name, &ucslen, &bb->fn[parlen], &bcslen); - #else - hcl_copybcstr (&bb->fn[parlen], bcslen + 1, arg->name); - #endif - - bb->fd = open(bb->fn, O_RDONLY, 0); - } - else - { - /* main stream */ - hcl_oow_t pathlen = 0; - bb = (bb_t*)hcl_callocmem (hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (pathlen + 1))); - if (!bb) goto oops; - - /*bb->fn = (hcl_bch_t*)(bb + 1); - hcl_copybcstr (bb->fn, pathlen + 1, "");*/ - - bb->fd = xtn->proto->worker->sck; - } - if (bb->fd <= -1) - { - hcl_seterrnum (hcl, HCL_EIOERR); - goto oops; - } - - arg->handle = bb; - return 0; - -oops: - if (bb) - { - if (bb->fd >= 0 && bb->fd != xtn->proto->worker->sck) close (bb->fd); - hcl_freemem (hcl, bb); - } - return -1; -} - -static HCL_INLINE int close_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - bb_t* bb; - - bb = (bb_t*)arg->handle; - HCL_ASSERT (hcl, bb != HCL_NULL && bb->fd >= 0); - - if (bb->fd != xtn->proto->worker->sck) close (bb->fd); - hcl_freemem (hcl, bb); - - arg->handle = HCL_NULL; - return 0; -} - - -static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - bb_t* bb; - hcl_oow_t bcslen, ucslen, remlen; - int x; - - bb = (bb_t*)arg->handle; - HCL_ASSERT (hcl, bb != HCL_NULL && bb->fd >= 0); - - if (bb->fd == xtn->proto->worker->sck) - { - ssize_t x; - - start_over: - while (1) - { - int n; - struct pollfd pfd; - - if (xtn->proto->worker->server->stopreq) - { - hcl_seterrbfmt (hcl, HCL_EGENERIC, "stop requested"); - return -1; - } - - pfd.fd = bb->fd; - pfd.events = POLLIN | POLLERR; - n = poll(&pfd, 1, 10000); /* TOOD: adjust this interval? */ - if (n <= -1) - { - if (errno == EINTR) goto start_over; - hcl_seterrwithsyserr (hcl, errno); - return -1; - } - else if (n >= 1) break; - -/* TOOD: idle timeout check - compute idling time and check it against server->cfg.idle_timeout */ - } - - x = recv(bb->fd, &bb->buf[bb->len], HCL_COUNTOF(bb->buf) - bb->len, 0); - if (x <= -1) - { - if (errno == EINTR) goto start_over; - hcl_seterrwithsyserr (hcl, errno); - return -1; - } - - bb->len += x; - } - else - { - ssize_t x; - x = read(bb->fd, &bb->buf[bb->len], HCL_COUNTOF(bb->buf) - bb->len); - if (x <= -1) - { - hcl_seterrnum (hcl, HCL_EIOERR); - return -1; - } - - bb->len += x; - } - -#if defined(HCL_OOCH_IS_UCH) - bcslen = bb->len; - ucslen = HCL_COUNTOF(arg->buf); - x = hcl_convbtooochars (hcl, bb->buf, &bcslen, arg->buf, &ucslen); - if (x <= -1 && ucslen <= 0) return -1; - /* if ucslen is greater than 0, i see that some characters have been - * converted properly */ -#else - bcslen = (bb->len < HCL_COUNTOF(arg->buf))? bb->len: HCL_COUNTOF(arg->buf); - ucslen = bcslen; - hcl_copybchars (arg->buf, bb->buf, bcslen); -#endif - - remlen = bb->len - bcslen; - if (remlen > 0) memmove (bb->buf, &bb->buf[bcslen], remlen); - bb->len = remlen; - - arg->xlen = ucslen; - return 0; -} - - -static int read_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) -{ - switch (cmd) - { - case HCL_IO_OPEN: - return open_input (hcl, (hcl_ioinarg_t*)arg); - - case HCL_IO_CLOSE: - return close_input (hcl, (hcl_ioinarg_t*)arg); - - case HCL_IO_READ: - return read_input (hcl, (hcl_ioinarg_t*)arg); - - default: - hcl_seterrnum (hcl, HCL_EINTERN); - return -1; - } -} - -static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) -{ - switch (cmd) - { - case HCL_IO_OPEN: - return 0; - - case HCL_IO_CLOSE: - return 0; - - case HCL_IO_WRITE: - { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - hcl_iooutarg_t* outarg = (hcl_iooutarg_t*)arg; - - if (server_proto_feed_reply(xtn->proto, outarg->ptr, outarg->len, 0) <= -1) - { - /* TODO: change error code and message. propagage the errormessage from proto */ - hcl_seterrbfmt (hcl, HCL_EIOERR, "failed to write message via proto"); - - /* writing failure on the socket is a critical failure. - * execution must get aborted */ - hcl_abort (hcl); - return -1; - } - outarg->xlen = outarg->len; - return 0; - } - - default: - hcl_seterrnum (hcl, HCL_EINTERN); - return -1; - } + sigaction (sig, &sa, NULL); } /* ========================================================================= */ -static void* alloc_heap (hcl_t* hcl, hcl_oow_t size) -{ -#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) && defined(MAP_ANONYMOUS) - /* It's called via hcl_makeheap() when HCL creates a GC heap. - * The heap is large in size. I can use a different memory allocation - * function instead of an ordinary malloc. - * upon failure, it doesn't require to set error information as hcl_makeheap() - * set the error number to HCL_EOOMEM. */ - -#if !defined(MAP_HUGETLB) && (defined(__amd64__) || defined(__x86_64__)) -# define MAP_HUGETLB 0x40000 -#endif - - hcl_oow_t* ptr; - int flags; - hcl_oow_t actual_size; - - flags = MAP_PRIVATE | MAP_ANONYMOUS; - - #if defined(MAP_HUGETLB) - flags |= MAP_HUGETLB; - #endif - - #if defined(MAP_UNINITIALIZED) - flags |= MAP_UNINITIALIZED; - #endif - - actual_size = HCL_SIZEOF(hcl_oow_t) + size; - actual_size = HCL_ALIGN_POW2(actual_size, 2 * 1024 * 1024); - ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0); - if (ptr == MAP_FAILED) - { - #if defined(MAP_HUGETLB) - flags &= ~MAP_HUGETLB; - ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0); - if (ptr == MAP_FAILED) return HCL_NULL; - #else - return HCL_NULL; - #endif - } - *ptr = actual_size; - - return (void*)(ptr + 1); - -#else - return HCL_MMGR_ALLOC(hcl->mmgr, size); -#endif -} - -static void free_heap (hcl_t* hcl, void* ptr) -{ -#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) - hcl_oow_t* actual_ptr; - actual_ptr = (hcl_oow_t*)ptr - 1; - munmap (actual_ptr, *actual_ptr); -#else - return HCL_MMGR_FREE(hcl->mmgr, ptr); -#endif -} - -static int write_all (int fd, const char* ptr, hcl_oow_t len) -{ - while (len > 0) - { - hcl_ooi_t wr; - - wr = write (fd, ptr, len); - - if (wr <= -1) - { - #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) - if (errno == EAGAIN) continue; - #else - # if defined(EAGAIN) - if (errno == EAGAIN) continue; - #elif defined(EWOULDBLOCK) - if (errno == EWOULDBLOCK) continue; - #endif - #endif - - #if defined(EINTR) - /* TODO: would this interfere with non-blocking nature of this VM? */ - if (errno == EINTR) continue; - #endif - return -1; - } - - ptr += wr; - len -= wr; - } - - return 0; -} - -static void __log_write (server_t* server, int mask, const void* vmsg, hcl_oow_t len, int force_bch) -{ - hcl_bch_t buf[256]; - hcl_oow_t ucslen, bcslen; - int n; - - int logfd; - - if (mask & HCL_LOG_STDERR) - { - /* the messages that go to STDERR don't get masked out */ - logfd = 2; - } - else - { - if (!(server->cfg.logmask & mask & ~HCL_LOG_ALL_LEVELS)) return; /* check log types */ - if (!(server->cfg.logmask & mask & ~HCL_LOG_ALL_TYPES)) return; /* check log levels */ - - if (mask & HCL_LOG_STDOUT) logfd = 1; - else - { - logfd = server->logfd; - if (logfd <= -1) return; - } - } - -/* TODO: beautify the log message. - * do classification based on mask. */ - if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR))) - { - time_t now; - char ts[32]; - size_t tslen; - struct tm tm, *tmp; - - now = time(NULL); - - tmp = localtime_r (&now, &tm); - #if defined(HAVE_STRFTIME_SMALL_Z) - tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); - #else - tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); - #endif - if (tslen == 0) - { - strcpy (ts, "0000-00-00 00:00:00 +0000"); - tslen = 25; - } - -/* TODO: less write system calls by having a buffer */ - write_all (logfd, ts, tslen); - -/* - * TODO: print IDs - //tslen = snprintf (ts, sizeof(ts), "[%d] ", xtn->proto->worker->sck); - //write_all (logfd, ts, tslen); -*/ - } - - if (server->logfd_istty) - { - if (mask & HCL_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7); - else if (mask & HCL_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7); - else if (mask & HCL_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7); - } - -#if defined(HCL_OOCH_IS_UCH) - if (force_bch) - { - const hcl_bch_t* msg = (const hcl_bch_t*)vmsg; - write_all (logfd, msg, len); - } - else - { - hcl_oow_t msgidx; - const hcl_ooch_t* msg = (const hcl_ooch_t*)vmsg; - - msgidx = 0; - while (len > 0) - { - ucslen = len; - bcslen = HCL_COUNTOF(buf); - - n = hcl_conv_oocsn_to_bcsn_with_cmgr(&msg[msgidx], &ucslen, buf, &bcslen, hcl_get_utf8_cmgr()); - if (n == 0 || n == -2) - { - /* n = 0: - * converted all successfully - * n == -2: - * buffer not sufficient. not all got converted yet. - * write what have been converted this round. */ - - /*HCL_ASSERT (hcl, ucslen > 0); */ /* if this fails, the buffer size must be increased */ - assert (ucslen > 0); - - /* attempt to write all converted characters */ - if (write_all(logfd, buf, bcslen) <= -1) break; - - if (n == 0) break; - else - { - msgidx += ucslen; - len -= ucslen; - } - } - else if (n <= -1) - { - /* conversion error */ - break; - } - } - } -#else - write_all (logfd, vmsg, len); -#endif - - if (server->logfd_istty) - { - if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); - } -} - -static void log_write (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - pthread_mutex_lock (&xtn->proto->worker->server->log_mutex); - __log_write (xtn->proto->worker->server, mask, msg, len, 0); - pthread_mutex_unlock (&xtn->proto->worker->server->log_mutex); -} - -static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len) -{ -#if defined(HAVE_STRERROR_R) - strerror_r (syserr, buf, len); -#else - /* this is not thread safe */ - hcl_copybcstr (buf, len, strerror(syserr)); -#endif -} - -/* ========================================================================= */ - -static void* dl_open (hcl_t* hcl, const hcl_ooch_t* name, int flags) -{ -#if defined(USE_LTDL) || defined(USE_DLFCN) - hcl_bch_t stabuf[128], * bufptr; - hcl_oow_t ucslen, bcslen, bufcapa; - void* handle; - - #if defined(HCL_OOCH_IS_UCH) - if (hcl_convootobcstr(hcl, name, &ucslen, HCL_NULL, &bufcapa) <= -1) return HCL_NULL; - /* +1 for terminating null. but it's not needed because HCL_COUNTOF(HCL_DEFAULT_PFMODPREFIX) - * and HCL_COUNTOF(HCL_DEFAULT_PFMODPOSTIFX) include the terminating nulls. Never mind about - * the extra 2 characters. */ - #else - bufcapa = hcl_countbcstr(name); - #endif - bufcapa += HCL_COUNTOF(HCL_DEFAULT_PFMODPREFIX) + HCL_COUNTOF(HCL_DEFAULT_PFMODPOSTFIX) + 1; - - if (bufcapa <= HCL_COUNTOF(stabuf)) bufptr = stabuf; - else - { - bufptr = (hcl_bch_t*)hcl_allocmem(hcl, bufcapa * HCL_SIZEOF(*bufptr)); - if (!bufptr) return HCL_NULL; - } - - if (flags & HCL_VMPRIM_OPENDL_PFMOD) - { - hcl_oow_t len, i, xlen; - - /* opening a primitive function module - mostly libhcl-xxxx */ - len = hcl_copybcstr(bufptr, bufcapa, HCL_DEFAULT_PFMODPREFIX); - - bcslen = bufcapa - len; - #if defined(HCL_OOCH_IS_UCH) - hcl_convootobcstr(hcl, name, &ucslen, &bufptr[len], &bcslen); - #else - bcslen = hcl_copybcstr(&bufptr[len], bcslen, name); - #endif - - /* length including the prefix and the name. but excluding the postfix */ - xlen = len + bcslen; - - for (i = len; i < xlen; i++) - { - /* convert a period(.) to a dash(-) */ - if (bufptr[i] == '.') bufptr[i] = '-'; - } - - retry: - hcl_copybcstr (&bufptr[xlen], bufcapa - xlen, HCL_DEFAULT_PFMODPOSTFIX); - - /* both prefix and postfix attached. for instance, libhcl-xxx */ - handle = sys_dl_openext(bufptr); - if (!handle) - { - HCL_DEBUG3 (hcl, "Failed to open(ext) DL %hs[%js] - %hs\n", bufptr, name, sys_dl_error()); - - /* try without prefix and postfix */ - bufptr[xlen] = '\0'; - handle = sys_dl_openext(&bufptr[len]); - if (!handle) - { - hcl_bch_t* dash; - const hcl_bch_t* dl_errstr; - dl_errstr = sys_dl_error(); - HCL_DEBUG3 (hcl, "Failed to open(ext) DL %hs[%js] - %hs\n", &bufptr[len], name, dl_errstr); - hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open(ext) DL %js - %hs", name, dl_errstr); - - dash = hcl_rfindbchar(bufptr, hcl_countbcstr(bufptr), '-'); - if (dash) - { - /* remove a segment at the back. - * [NOTE] a dash contained in the original name before - * period-to-dash transformation may cause extraneous/wrong - * loading reattempts. */ - xlen = dash - bufptr; - goto retry; - } - } - else - { - HCL_DEBUG3 (hcl, "Opened(ext) DL %hs[%js] handle %p\n", &bufptr[len], name, handle); - } - } - else - { - HCL_DEBUG3 (hcl, "Opened(ext) DL %hs[%js] handle %p\n", bufptr, name, handle); - } - } - else - { - /* opening a raw shared object without a prefix and/or a postfix */ - #if defined(HCL_OOCH_IS_UCH) - bcslen = bufcapa; - hcl_convootobcstr(hcl, name, &ucslen, bufptr, &bcslen); - #else - bcslen = hcl_copybcstr(bufptr, bufcapa, name); - #endif - - if (hcl_findbchar(bufptr, bcslen, '.')) - { - handle = sys_dl_open(bufptr); - if (!handle) - { - const hcl_bch_t* dl_errstr; - dl_errstr = sys_dl_error(); - HCL_DEBUG2 (hcl, "Failed to open DL %hs - %hs\n", bufptr, dl_errstr); - hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open DL %js - %hs", name, dl_errstr); - } - else HCL_DEBUG2 (hcl, "Opened DL %hs handle %p\n", bufptr, handle); - } - else - { - handle = sys_dl_openext(bufptr); - if (!handle) - { - const hcl_bch_t* dl_errstr; - dl_errstr = sys_dl_error(); - HCL_DEBUG2 (hcl, "Failed to open(ext) DL %hs - %s\n", bufptr, dl_errstr); - hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open(ext) DL %js - %hs", name, dl_errstr); - } - else HCL_DEBUG2 (hcl, "Opened(ext) DL %hs handle %p\n", bufptr, handle); - } - } - - if (bufptr != stabuf) hcl_freemem (hcl, bufptr); - return handle; - -#else - -/* TODO: support various platforms */ - /* TODO: implemenent this */ - HCL_DEBUG1 (hcl, "Dynamic loading not implemented - cannot open %js\n", name); - hcl_seterrnum (hcl, HCL_ENOIMPL, "dynamic loading not implemented - cannot open %js", name); - return HCL_NULL; -#endif -} - -static void dl_close (hcl_t* hcl, void* handle) -{ -#if defined(USE_LTDL) || defined(USE_DLFCN) - HCL_DEBUG1 (hcl, "Closed DL handle %p\n", handle); - sys_dl_close (handle); - -#else - /* TODO: implemenent this */ - HCL_DEBUG1 (hcl, "Dynamic loading not implemented - cannot close handle %p\n", handle); -#endif -} - -static void* dl_getsym (hcl_t* hcl, void* handle, const hcl_ooch_t* name) -{ -#if defined(USE_LTDL) || defined(USE_DLFCN) - hcl_bch_t stabuf[64], * bufptr; - hcl_oow_t bufcapa, ucslen, bcslen, i; - const hcl_bch_t* symname; - void* sym; - - #if defined(HCL_OOCH_IS_UCH) - if (hcl_convootobcstr(hcl, name, &ucslen, HCL_NULL, &bcslen) <= -1) return HCL_NULL; - #else - bcslen = hcl_countbcstr (name); - #endif - - if (bcslen >= HCL_COUNTOF(stabuf) - 2) - { - bufcapa = bcslen + 3; - bufptr = (hcl_bch_t*)hcl_allocmem(hcl, bufcapa * HCL_SIZEOF(*bufptr)); - if (!bufptr) return HCL_NULL; - } - else - { - bufcapa = HCL_COUNTOF(stabuf); - bufptr = stabuf; - } - - bcslen = bufcapa - 1; - #if defined(HCL_OOCH_IS_UCH) - hcl_convootobcstr (hcl, name, &ucslen, &bufptr[1], &bcslen); - #else - bcslen = hcl_copybcstr(&bufptr[1], bcslen, name); - #endif - - /* convert a period(.) to an underscore(_) */ - for (i = 1; i <= bcslen; i++) if (bufptr[i] == '.') bufptr[i] = '_'; - - symname = &bufptr[1]; /* try the name as it is */ - - sym = sys_dl_getsym(handle, symname); - if (!sym) - { - bufptr[0] = '_'; - symname = &bufptr[0]; /* try _name */ - sym = sys_dl_getsym(handle, symname); - if (!sym) - { - bufptr[bcslen + 1] = '_'; - bufptr[bcslen + 2] = '\0'; - - symname = &bufptr[1]; /* try name_ */ - sym = sys_dl_getsym(handle, symname); - - if (!sym) - { - symname = &bufptr[0]; /* try _name_ */ - sym = sys_dl_getsym(handle, symname); - if (!sym) - { - const hcl_bch_t* dl_errstr; - dl_errstr = sys_dl_error(); - HCL_DEBUG3 (hcl, "Failed to get module symbol %js from handle %p - %hs\n", name, handle, dl_errstr); - hcl_seterrbfmt (hcl, HCL_ENOENT, "unable to get module symbol %hs - %hs", symname, dl_errstr); - - } - } - } - } - - if (sym) HCL_DEBUG3 (hcl, "Loaded module symbol %js from handle %p - %hs\n", name, handle, symname); - if (bufptr != stabuf) hcl_freemem (hcl, bufptr); - return sym; - -#else - /* TODO: IMPLEMENT THIS */ - HCL_DEBUG2 (hcl, "Dynamic loading not implemented - Cannot load module symbol %js from handle %p\n", name, handle); - hcl_seterrbfmt (hcl, HCL_ENOIMPL, "dynamic loading not implemented - Cannot load module symbol %js from handle %p", name, handle); - return HCL_NULL; -#endif -} - -/* ========================================================================= */ - -static void vm_gettime (hcl_t* hcl, hcl_ntime_t* now) -{ -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) - struct timespec ts; - clock_gettime (CLOCK_MONOTONIC, &ts); - HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec); -#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - struct timespec ts; - clock_gettime (CLOCK_REALTIME, &ts); - HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec); -#else - struct timeval tv; - gettimeofday (&tv, HCL_NULL); - HCL_INITNTIME(now, tv.tv_sec, HCL_USEC_TO_NSEC(tv.tv_usec)); -#endif -} - -static void vm_sleep (hcl_t* hcl, const hcl_ntime_t* dur) -{ -#if defined(HAVE_NANOSLEEP) - struct timespec ts; - ts.tv_sec = dur->sec; - ts.tv_nsec = dur->nsec; - nanosleep (&ts, HCL_NULL); -#elif defined(HAVE_USLEEP) - usleep (HCL_SECNSEC_TO_USEC(dur->sec, dur->nsec)); -#else -# error UNSUPPORT SLEEP -#endif -} - -/* ========================================================================= */ - -static int vm_startup (hcl_t* hcl) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - xtn->vm_running = 1; - return 0; -} - -static void vm_cleanup (hcl_t* hcl) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - xtn->vm_running = 0; -} - -static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - - if (xtn->proto->worker->server->stopreq) hcl_abort(hcl); - /* TODO: check how to this vm has been running. too long? abort it */ - - /* TODO: check if the worker connection is ok? if not, abort it */ -} - -/* -static void gc_hcl (hcl_t* hcl) -{ -} -*/ - -static void fini_hcl (hcl_t* hcl) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - if (xtn->logfd >= 0) - { - close (xtn->logfd); - xtn->logfd = -1; - xtn->logfd_istty = 0; - } -} - -/* ========================================================================= */ - -static int handle_logopt (server_t* server, const hcl_bch_t* str) +static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) { hcl_bch_t* xstr = (hcl_bch_t*)str; hcl_bch_t* cm, * flt; + unsigned int logmask; + + hcl_server_getoption (server, HCL_SERVER_LOG_MASK, &logmask); cm = strchr(xstr, ','); if (cm) @@ -1138,25 +151,25 @@ static int handle_logopt (server_t* server, const hcl_bch_t* str) cm = strchr(flt, ','); if (cm) *cm = '\0'; - if (hcl_compbcstr(flt, "app") == 0) server->cfg.logmask |= HCL_LOG_APP; - else if (hcl_compbcstr(flt, "compiler") == 0) server->cfg.logmask |= HCL_LOG_COMPILER; - else if (hcl_compbcstr(flt, "vm") == 0) server->cfg.logmask |= HCL_LOG_VM; - else if (hcl_compbcstr(flt, "mnemonic") == 0) server->cfg.logmask |= HCL_LOG_MNEMONIC; - else if (hcl_compbcstr(flt, "gc") == 0) server->cfg.logmask |= HCL_LOG_GC; - else if (hcl_compbcstr(flt, "ic") == 0) server->cfg.logmask |= HCL_LOG_IC; - else if (hcl_compbcstr(flt, "primitive") == 0) server->cfg.logmask |= HCL_LOG_PRIMITIVE; + if (hcl_compbcstr(flt, "app") == 0) logmask |= HCL_LOG_APP; + else if (hcl_compbcstr(flt, "compiler") == 0) logmask |= HCL_LOG_COMPILER; + else if (hcl_compbcstr(flt, "vm") == 0) logmask |= HCL_LOG_VM; + else if (hcl_compbcstr(flt, "mnemonic") == 0) logmask |= HCL_LOG_MNEMONIC; + else if (hcl_compbcstr(flt, "gc") == 0) logmask |= HCL_LOG_GC; + else if (hcl_compbcstr(flt, "ic") == 0) logmask |= HCL_LOG_IC; + else if (hcl_compbcstr(flt, "primitive") == 0) logmask |= HCL_LOG_PRIMITIVE; - else if (hcl_compbcstr(flt, "fatal") == 0) server->cfg.logmask |= HCL_LOG_FATAL; - else if (hcl_compbcstr(flt, "error") == 0) server->cfg.logmask |= HCL_LOG_ERROR; - else if (hcl_compbcstr(flt, "warn") == 0) server->cfg.logmask |= HCL_LOG_WARN; - else if (hcl_compbcstr(flt, "info") == 0) server->cfg.logmask |= HCL_LOG_INFO; - else if (hcl_compbcstr(flt, "debug") == 0) server->cfg.logmask |= HCL_LOG_DEBUG; + else if (hcl_compbcstr(flt, "fatal") == 0) logmask |= HCL_LOG_FATAL; + else if (hcl_compbcstr(flt, "error") == 0) logmask |= HCL_LOG_ERROR; + else if (hcl_compbcstr(flt, "warn") == 0) logmask |= HCL_LOG_WARN; + else if (hcl_compbcstr(flt, "info") == 0) logmask |= HCL_LOG_INFO; + else if (hcl_compbcstr(flt, "debug") == 0) logmask |= HCL_LOG_DEBUG; - else if (hcl_compbcstr(flt, "fatal+") == 0) server->cfg.logmask |= HCL_LOG_FATAL; - else if (hcl_compbcstr(flt, "error+") == 0) server->cfg.logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR; - else if (hcl_compbcstr(flt, "warn+") == 0) server->cfg.logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN; - else if (hcl_compbcstr(flt, "info+") == 0) server->cfg.logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO; - else if (hcl_compbcstr(flt, "debug+") == 0) server->cfg.logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG; + else if (hcl_compbcstr(flt, "fatal+") == 0) logmask |= HCL_LOG_FATAL; + else if (hcl_compbcstr(flt, "error+") == 0) logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR; + else if (hcl_compbcstr(flt, "warn+") == 0) logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN; + else if (hcl_compbcstr(flt, "info+") == 0) logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO; + else if (hcl_compbcstr(flt, "debug+") == 0) logmask |= HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG; else { @@ -1167,16 +180,17 @@ static int handle_logopt (server_t* server, const hcl_bch_t* str) } while (cm); - - if (!(server->cfg.logmask & HCL_LOG_ALL_TYPES)) server->cfg.logmask |= HCL_LOG_ALL_TYPES; /* no types specified. force to all types */ - if (!(server->cfg.logmask & HCL_LOG_ALL_LEVELS)) server->cfg.logmask |= HCL_LOG_ALL_LEVELS; /* no levels specified. force to all levels */ + if (!(logmask & HCL_LOG_ALL_TYPES)) logmask |= HCL_LOG_ALL_TYPES; /* no types specified. force to all types */ + if (!(logmask & HCL_LOG_ALL_LEVELS)) logmask |= HCL_LOG_ALL_LEVELS; /* no levels specified. force to all levels */ } else { - server->cfg.logmask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES; + logmask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES; } - server->logfd = open (xstr, O_CREAT | O_WRONLY | O_APPEND , 0644); + hcl_server_setoption (server, HCL_SERVER_LOG_MASK, &logmask); + + server->logfd = open(xstr, O_CREAT | O_WRONLY | O_APPEND , 0644); if (server->logfd == -1) { fprintf (stderr, "ERROR: cannot open a log file %s\n", xstr); @@ -1223,955 +237,9 @@ static int parse_dbgopt (const char* str, unsigned int* dbgoptp) /* ========================================================================= */ -#define SERVER_PROTO_LOG_MASK (HCL_LOG_ERROR | HCL_LOG_APP) - -server_proto_t* server_proto_open (hcl_oow_t xtnsize, server_worker_t* worker) -{ - server_proto_t* proto; - hcl_vmprim_t vmprim; - hcl_cb_t hclcb; - xtn_t* xtn; - unsigned int trait; - - memset (&vmprim, 0, HCL_SIZEOF(vmprim)); - if (worker->server->cfg.trait & SERVER_TRAIT_USE_LARGE_PAGES) - { - vmprim.alloc_heap = alloc_heap; - vmprim.free_heap = free_heap; - } - vmprim.log_write = log_write; - vmprim.syserrstrb = syserrstrb; - vmprim.dl_open = dl_open; - vmprim.dl_close = dl_close; - vmprim.dl_getsym = dl_getsym; - vmprim.vm_gettime = vm_gettime; - vmprim.vm_sleep = vm_sleep; - - proto = (server_proto_t*)malloc(sizeof(*proto)); - if (!proto) return NULL; - - memset (proto, 0, sizeof(*proto)); - proto->worker = worker; - - proto->hcl = hcl_open(&sys_mmgr, HCL_SIZEOF(xtn_t), worker->server->cfg.memsize, &vmprim, HCL_NULL); - if (!proto->hcl) goto oops; - - xtn = (xtn_t*)hcl_getxtn(proto->hcl); - xtn->logfd = -1; - xtn->logfd_istty = 0; - xtn->proto = proto; - - hcl_getoption (proto->hcl, HCL_TRAIT, &trait); - trait |= proto->worker->server->cfg.dbgopt; - hcl_setoption (proto->hcl, HCL_TRAIT, &trait); - - memset (&hclcb, 0, HCL_SIZEOF(hclcb)); - hclcb.fini = fini_hcl; - /*hclcb.gc = gc_hcl;*/ - hclcb.vm_startup = vm_startup; - hclcb.vm_cleanup = vm_cleanup; - hclcb.vm_checkbc = vm_checkbc; - hcl_regcb (proto->hcl, &hclcb); - - if (hcl_ignite(proto->hcl) <= -1) goto oops; - if (hcl_addbuiltinprims(proto->hcl) <= -1) goto oops; - - if (hcl_attachio(proto->hcl, read_handler, print_handler) <= -1) goto oops; - return proto; - -oops: - if (proto) - { - if (proto->hcl) hcl_close (proto->hcl); - free (proto); - } - return NULL; -} - -void server_proto_close (server_proto_t* proto) -{ - if (proto->tok.ptr) free (proto->tok.ptr); - hcl_close (proto->hcl); - free (proto); -} - -static int write_reply_chunk (server_proto_t* proto) -{ - struct msghdr msg; - struct iovec iov[3]; - hcl_bch_t cl[16]; /* ensure that this is large enough for the chunk length string */ - int index = 0, count = 0; - - if (proto->reply.type == SERVER_PROTO_REPLY_CHUNKED) - { - if (proto->reply.nchunks <= 0) - { - /* this is the first chunk */ - iov[count].iov_base = ".OK\n.ENCODING chunked\n"; - iov[count++].iov_len = 22; - } - - iov[count].iov_base = cl, - iov[count++].iov_len = snprintf(cl, sizeof(cl), "%s%zu:", (((proto->worker->server->cfg.trait & SERVER_TRAIT_READABLE_PROTO) && proto->reply.nchunks > 0)? "\n": ""), proto->reply.len); - } - iov[count].iov_base = proto->reply.buf; - iov[count++].iov_len = proto->reply.len; - - while (1) - { - ssize_t nwritten; - - memset (&msg, 0, sizeof(msg)); - msg.msg_iov = (struct iovec*)&iov[index]; - msg.msg_iovlen = count - index; - nwritten = sendmsg(proto->worker->sck, &msg, 0); - /*nwritten = writev(proto->worker->sck, (const struct iovec*)&iov[index], count - index);*/ - if (nwritten <= -1) - { - char errbuf[128]; - strerror_r (errno, errbuf, HCL_COUNTOF(errbuf)); - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "sendmsg failure on %d - %hs\n", proto->worker->sck, errbuf); - return -1; - } - - while (index < count && (size_t)nwritten >= iov[index].iov_len) - nwritten -= iov[index++].iov_len; - - if (index == count) break; - - iov[index].iov_base = (void*)((hcl_uint8_t*)iov[index].iov_base + nwritten); - iov[index].iov_len -= nwritten; - } - - if (proto->reply.len <= 0) - { - /* this should be the last chunk */ - proto->reply.nchunks = 0; - } - else - { - proto->reply.nchunks++; - proto->reply.len = 0; - } - - return 0; -} - -void server_proto_start_reply (server_proto_t* proto) -{ - proto->reply.type = SERVER_PROTO_REPLY_CHUNKED; - proto->reply.nchunks = 0; - proto->reply.len = 0; -} - -int server_proto_feed_reply (server_proto_t* proto, const hcl_ooch_t* ptr, hcl_oow_t len, int escape) -{ -#if defined(HCL_OOCH_IS_BCH) - /* nothing */ -#else - hcl_oow_t bcslen, ucslen, donelen; - int x; -#endif - -#if defined(HCL_OOCH_IS_BCH) - while (len > 0) - { - if (escape && (*ptr == '\\' || *ptr == '\"')) - { - if (proto->reply.len >= HCL_COUNTOF(proto->reply.buf) && write_reply_chunk(proto) <=-1) return -1; - proto->reply.buf[proto->reply.len++] = '\\'; - } - - if (proto->reply.len >= HCL_COUNTOF(proto->reply.buf) && write_reply_chunk(proto) <=-1) return -1; - proto->reply.buf[proto->reply.len++] = *ptr++; - len--; - } - - return 0; -#else - donelen = 0; - while (donelen < len) - { - if (escape && (*ptr == '\\' || *ptr == '\"')) - { - /* i know that these characters don't need encoding conversion */ - if (proto->reply.len >= HCL_COUNTOF(proto->reply.buf) && write_reply_chunk(proto) <=-1) return -1; - proto->reply.buf[proto->reply.len++] = '\\'; - } - - bcslen = HCL_COUNTOF(proto->reply.buf) - proto->reply.len; - if (bcslen < HCL_BCSIZE_MAX) - { - if (write_reply_chunk(proto) <=-1) return -1; - bcslen = HCL_COUNTOF(proto->reply.buf) - proto->reply.len; - } - ucslen = len - donelen; - - x = hcl_convootobchars(proto->hcl, &ptr[donelen], &ucslen, &proto->reply.buf[proto->reply.len], &bcslen); - if (x <= -1 && ucslen <= 0) return -1; - - donelen += ucslen; - proto->reply.len += bcslen; - } -#endif - return 0; -} - -int server_proto_end_reply (server_proto_t* proto, const hcl_ooch_t* failmsg) -{ - HCL_ASSERT (proto->hcl, proto->reply.type == SERVER_PROTO_REPLY_CHUNKED); - - if (failmsg) - { - if (proto->reply.nchunks <= 0 && proto->reply.len <= 0) - { - static hcl_ooch_t err1[] = { '.','E','R','R','O','R',' ','\"' }; - static hcl_ooch_t err2[] = { '\"','\n' }; - proto->reply.type = SERVER_PROTO_REPLY_SIMPLE; /* switch to the simple mode forcibly */ - - simple_error: - if (server_proto_feed_reply(proto, err1, 8, 0) <= -1 || - server_proto_feed_reply(proto, failmsg, hcl_countoocstr(failmsg), 1) <= -1 || - server_proto_feed_reply(proto, err2, 2, 0) <= -1) return -1; - - if (write_reply_chunk(proto) <= -1) return -1; - } - else - { - /* some chunks have beed emitted. but at the end, an error has occurred. - * send -1: as the last chunk. the receiver must rub out the reply - * buffer received so far and expect the following .ERROR response */ - static hcl_ooch_t err0[] = { '-','1',':','\n' }; - if (proto->reply.len > 0 && write_reply_chunk(proto) <= -1) return -1; - - proto->reply.type = SERVER_PROTO_REPLY_SIMPLE; /* switch to the simple mode forcibly */ - proto->reply.nchunks = 0; - proto->reply.len = 0; - - if (server_proto_feed_reply(proto, err0, 4, 0) <= -1) return -1; - goto simple_error; - } - } - else - { - if (proto->reply.nchunks <= 0 && proto->reply.len <= 0) - { - /* in the chunked mode. but no output has been made so far */ - static hcl_ooch_t ok[] = { '.','O','K',' ','\"','\"','\n' }; - proto->reply.type = SERVER_PROTO_REPLY_SIMPLE; /* switch to the simple mode forcibly */ - if (server_proto_feed_reply(proto, ok, 7, 0) <= -1) return -1; - if (write_reply_chunk(proto) <= -1) return -1; - } - else - { - if (proto->reply.len > 0 && write_reply_chunk(proto) <= -1) return -1; - if (write_reply_chunk(proto) <= -1) return -1; /* write 0: */ - } - } - - return 0; -} - -static HCL_INLINE int is_spacechar (hcl_ooci_t c) -{ - /* TODO: handle other space unicode characters */ - switch (c) - { - case ' ': - case '\f': /* formfeed */ - case '\r': /* carriage return */ - case '\t': /* horizon tab */ - case '\v': /* vertical tab */ - return 1; - - default: - return 0; - } -} - -static HCL_INLINE int read_char (server_proto_t* proto) -{ - proto->lxc = hcl_readchar(proto->hcl); - if (!proto->lxc) return -1; - return 0; -} - -static HCL_INLINE int unread_last_char (server_proto_t* proto) -{ - return hcl_unreadchar(proto->hcl, proto->lxc); -} - -#define GET_CHAR_TO(proto,c) \ - do { \ - if (read_char(proto) <= -1) return -1; \ - c = (proto)->lxc->c; \ - } while(0) - -#define UNGET_LAST_CHAR(proto) \ - do { \ - if (unread_last_char(proto) <= -1) return -1; \ - } while (0) - -#define CLEAR_TOKEN_NAME(proto) ((proto)->tok.name.len = 0) -#define SET_TOKEN_TYPE(proto,tv) ((proto)->tok.type = (tv)) -#define ADD_TOKEN_CHAR(proto,c) \ - do { if (add_token_char(proto, c) <= -1) return -1; } while (0) - - -static HCL_INLINE int add_token_char (server_proto_t* proto, hcl_ooch_t c) -{ - if (proto->tok.len >= proto->tok.capa) - { - hcl_ooch_t* tmp; - hcl_oow_t capa; - - capa = HCL_ALIGN_POW2(proto->tok.len + 1, 64); - tmp = (hcl_ooch_t*)realloc(proto->tok.ptr, capa * sizeof(*tmp)); - if (!tmp) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "out of memory in allocating a token buffer\n"); - return -1; - } - - proto->tok.ptr = tmp; - proto->tok.capa = capa; - } - - proto->tok.ptr[proto->tok.len++] = c; - return 0; -} - -static HCL_INLINE int is_alphachar (hcl_ooci_t c) -{ -/* TODO: support full unicode */ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - -static void classify_current_ident_token (server_proto_t* proto) -{ - static struct cmd_t - { - server_proto_token_type_t type; - hcl_ooch_t name[32]; - } tab[] = - { - { SERVER_PROTO_TOKEN_BEGIN, { '.','B','E','G','I','N','\0' } }, - { SERVER_PROTO_TOKEN_END, { '.','E','N','D','\0' } }, - { SERVER_PROTO_TOKEN_SCRIPT, { '.','S','C','R','I','P','T','\0' } }, - { SERVER_PROTO_TOKEN_EXIT, { '.','E','X','I','T','\0' } }, - - { SERVER_PROTO_TOKEN_KILL_WORKER, { '.','K','I','L','L','-','W','O','R','K','E','R','\0' } }, - { SERVER_PROTO_TOKEN_SHOW_WORKERS, { '.','S','H','O','W','-','W','O','R','K','E','R','S','\0' } }, - /* TODO: add more */ - }; - hcl_oow_t i; - - for (i = 0; i < HCL_COUNTOF(tab); i++) - { - if (hcl_compoocharsoocstr(proto->tok.ptr, proto->tok.len, tab[i].name) == 0) - { - SET_TOKEN_TYPE (proto, tab[i].type); - break; - } - } -} - -static int get_token (server_proto_t* proto) -{ - hcl_ooci_t c; - - GET_CHAR_TO (proto, c); - - /* skip spaces */ - while (is_spacechar(c)) GET_CHAR_TO (proto, c); - - SET_TOKEN_TYPE (proto, SERVER_PROTO_TOKEN_EOF); /* is it correct? */ - proto->tok.len = 0; - proto->tok.loc = proto->hcl->c->lxc.l; /* set token location */ - - switch (c) - { - case HCL_OOCI_EOF: - SET_TOKEN_TYPE (proto, SERVER_PROTO_TOKEN_EOF); - break; - - case '\n': - SET_TOKEN_TYPE (proto, SERVER_PROTO_TOKEN_NL); - break; - - case '.': - SET_TOKEN_TYPE (proto, SERVER_PROTO_TOKEN_IDENT); - - ADD_TOKEN_CHAR(proto, c); - GET_CHAR_TO(proto, c); - if (!is_alphachar(c)) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "alphabetic character expected after a period\n"); - return -1; - } - - do - { - ADD_TOKEN_CHAR(proto, c); - GET_CHAR_TO(proto, c); - } - while (is_alphachar(c) || c == '-'); - - UNGET_LAST_CHAR (proto); - - classify_current_ident_token (proto); - break; - - default: - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "unrecognized character - [%jc]\n", c); - return -1; - } - return 0; -} - -int server_proto_handle_request (server_proto_t* proto) -{ - if (get_token(proto) <= -1) return -1; - - switch (proto->tok.type) - { - case SERVER_PROTO_TOKEN_NL: - /* ignore new lines */ - break; - - case SERVER_PROTO_TOKEN_EOF: - if (proto->req.state != SERVER_PROTO_REQ_IN_TOP_LEVEL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "unexpected EOF without .END\n"); - return -1; - } - - /* drop connection silently */ - return 0; - - case SERVER_PROTO_TOKEN_EXIT: - if (proto->req.state != SERVER_PROTO_REQ_IN_TOP_LEVEL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, ".EXIT allowed in the top level only\n"); - return -1; - } - - if (get_token(proto) <= -1) return -1; - if (proto->tok.type != SERVER_PROTO_TOKEN_NL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "no new line after .EXIT\n"); - return -1; - } - - server_proto_start_reply (proto); - if (server_proto_end_reply(proto, NULL) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot finalize reply for .EXIT\n"); - return -1; - } - return 0; - - case SERVER_PROTO_TOKEN_BEGIN: - if (proto->req.state != SERVER_PROTO_REQ_IN_TOP_LEVEL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, ".BEGIN not allowed to be nested\n"); - return -1; - } - - if (get_token(proto) <= -1) return -1; - if (proto->tok.type != SERVER_PROTO_TOKEN_NL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "no new line after .BEGIN\n"); - return -1; - } - - proto->req.state = SERVER_PROTO_REQ_IN_BLOCK_LEVEL; - hcl_reset (proto->hcl); - break; - - case SERVER_PROTO_TOKEN_END: - { - hcl_oop_t obj; - - if (proto->req.state != SERVER_PROTO_REQ_IN_BLOCK_LEVEL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, ".END without opening .BEGIN\n"); - return -1; - } - - if (get_token(proto) <= -1) return -1; - if (proto->tok.type != SERVER_PROTO_TOKEN_NL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "no new line after .BEGIN\n"); - return -1; - } - - server_proto_start_reply (proto); - obj = (hcl_getbclen(proto->hcl) > 0)? hcl_execute(proto->hcl): proto->hcl->_nil; - if (server_proto_end_reply(proto, (obj? NULL: hcl_geterrmsg(proto->hcl))) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot finalize reply for .END\n"); - return -1; - } - - proto->req.state = SERVER_PROTO_REQ_IN_TOP_LEVEL; - break; - } - - case SERVER_PROTO_TOKEN_SCRIPT: - { - hcl_oop_t obj; - - if (proto->req.state == SERVER_PROTO_REQ_IN_TOP_LEVEL) hcl_reset(proto->hcl); - - obj = hcl_read(proto->hcl); - if (!obj) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot read .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl)); - return -1; - } - - if (get_token(proto) <= -1) return -1; - if (proto->tok.type != SERVER_PROTO_TOKEN_NL) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "no new line after .SCRIPT contest\n"); - return -1; - } - - if (hcl_compile(proto->hcl, obj) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot compile .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl)); - return -1; - } - - if (proto->req.state == SERVER_PROTO_REQ_IN_TOP_LEVEL) - { - server_proto_start_reply (proto); - obj = hcl_execute(proto->hcl); - if (server_proto_end_reply(proto, (obj? NULL: hcl_geterrmsg(proto->hcl))) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot finalize reply for .SCRIPT\n"); - return -1; - } - } - break; - - } - - case SERVER_PROTO_TOKEN_SHOW_WORKERS: - server_proto_start_reply (proto); - - pthread_mutex_lock (&proto->worker->server->worker_mutex); - //print_server_workers (proto); - pthread_mutex_unlock (&proto->worker->server->worker_mutex); - - if (server_proto_end_reply(proto, NULL) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot finalize reply for .SHOW-WORKERS\n"); - return -1; - } - - break; - - case SERVER_PROTO_TOKEN_KILL_WORKER: - server_proto_start_reply (proto); - - pthread_mutex_lock (&proto->worker->server->worker_mutex); - //kill_server_worker (proto); - pthread_mutex_unlock (&proto->worker->server->worker_mutex); - - if (server_proto_end_reply(proto, NULL) <= -1) - { - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "cannot finalize reply for .KILL-WORKER\n"); - return -1; - } - break; - - default: - hcl_logbfmt (proto->hcl, SERVER_PROTO_LOG_MASK, "unknown token - %d - %.*js\n", (int)proto->tok.type, proto->tok.len, proto->tok.ptr); - return -1; - } - - return 1; -} - -/* ========================================================================= */ - -server_t* server_open (size_t xtnsize, hcl_oow_t memsize, const char* logopt, unsigned int dbgopt) -{ - server_t* server; - - server = (server_t*)malloc(sizeof(*server) + xtnsize); - if (!server) return NULL; - - memset (server, 0, sizeof(*server) + xtnsize); - - server->logfd = -1; - server->logfd_istty = 0; - - server->cfg.memsize = memsize; - server->cfg.logopt = logopt; - server->cfg.dbgopt = dbgopt; - server->cfg.worker_stack_size = 512000UL; /* TODO: make it configurable */ - server->cfg.trait = SERVER_TRAIT_READABLE_PROTO | SERVER_TRAIT_USE_LARGE_PAGES; /* TODO: make it configurable */ - - pthread_mutex_init (&server->worker_mutex, NULL); - pthread_mutex_init (&server->log_mutex, NULL); - - return server; -} - -void server_close (server_t* server) -{ - if (server->logfd >= 0) close (server->logfd); - pthread_mutex_destroy (&server->log_mutex); - pthread_mutex_destroy (&server->worker_mutex); - free (server); -} - -static server_worker_t* alloc_worker (server_t* server, int cli_sck) -{ - server_worker_t* worker; - - worker = (server_worker_t*)malloc(sizeof(*worker)); - if (!worker) return NULL; - - memset (worker, 0, sizeof(*worker)); - worker->sck = cli_sck; - worker->server = server; - return worker; -} - -static void free_worker (server_worker_t* worker) -{ - if (worker->sck >= 0) close (worker->sck); - free (worker); -} - -static void add_server_worker_to_server (server_t* server, server_worker_state_t wstate, server_worker_t* worker) -{ - assert (worker->server == server); - - if (server->worker_list[wstate].tail) - { - server->worker_list[wstate].tail->next_worker = worker; - worker->prev_worker = server->worker_list[wstate].tail; - server->worker_list[wstate].tail = worker; - worker->next_worker = NULL; - } - else - { - server->worker_list[wstate].tail = worker; - server->worker_list[wstate].head = worker; - worker->prev_worker = NULL; - worker->next_worker = NULL; - } - - worker->state = wstate; -} - -static void zap_worker_in_server (server_t* server, server_worker_t* worker) -{ - server_worker_state_t wstate; - - assert (worker->server == server); - - wstate = worker->state; - if (worker->prev_worker) worker->prev_worker->next_worker = worker->next_worker; - else server->worker_list[wstate].head = worker->next_worker; - if (worker->next_worker) worker->next_worker->prev_worker = worker->prev_worker; - else server->worker_list[wstate].tail = worker->prev_worker; - - worker->prev_worker = NULL; - worker->next_worker = NULL; -} - -static void* worker_main (void* ctx) -{ - server_worker_t* worker = (server_worker_t*)ctx; - server_t* server = worker->server; - sigset_t set; - - sigfillset (&set); - pthread_sigmask (SIG_BLOCK, &set, NULL); - - worker->thr = pthread_self(); - worker->proto = server_proto_open(0, worker); /* TODO: get this from argumen */ - if (!worker->proto) - { - free_worker (worker); - return NULL; - } - - pthread_mutex_lock (&server->worker_mutex); - add_server_worker_to_server (server, SERVER_WORKER_STATE_ALIVE, worker); - pthread_mutex_unlock (&server->worker_mutex); - - while (!server->stopreq) - { - if (server_proto_handle_request(worker->proto) <= 0) break; - } - - server_proto_close (worker->proto); - worker->proto = NULL; - - pthread_mutex_lock (&server->worker_mutex); - - /* close connection before free_client() is called */ - close (worker->sck); - worker->sck = -1; - - if (!worker->claimed) - { - zap_worker_in_server (server, worker); - add_server_worker_to_server (server, SERVER_WORKER_STATE_DEAD, worker); - } - pthread_mutex_unlock (&server->worker_mutex); - - return NULL; -} - -static void purge_all_workers (server_t* server, server_worker_state_t wstate) -{ - server_worker_t* worker; - - while (1) - { - pthread_mutex_lock (&server->worker_mutex); - worker = server->worker_list[wstate].head; - if (worker) - { - zap_worker_in_server (server, worker); - worker->claimed = 1; - - if (worker->sck >= 0) shutdown (worker->sck, SHUT_RDWR); - } - pthread_mutex_unlock (&server->worker_mutex); - if (!worker) break; - - pthread_join (worker->thr, NULL); - free_worker (worker); - } -} - -static void server_write_log (server_t* server, int mask, const char* fmt, ...) -{ - char esbuf[256]; - int eslen; - va_list ap; - - va_start (ap, fmt); - eslen = vsnprintf (esbuf, HCL_COUNTOF(esbuf), fmt, ap); - va_end (ap); - - if (eslen >= HCL_COUNTOF(esbuf)) eslen = HCL_COUNTOF(esbuf) - 1; - - pthread_mutex_lock (&server->log_mutex); - __log_write (server, mask, esbuf, eslen, 1); - pthread_mutex_unlock (&server->log_mutex); -} - -int server_start (server_t* server, const char* addrs) -{ - sck_addr_t srv_addr; - int srv_fd, sck_fam; - int optval; - socklen_t srv_len; - char errbuf[128]; - pthread_attr_t thr_attr; - -/* TODO: interprete 'addrs' as a command-separated address list - * 192.168.1.1:20,[::1]:20,127.0.0.1:345 - */ - memset (&srv_addr, 0, sizeof(srv_addr)); - if (inet_pton (AF_INET6, addrs, &srv_addr.in6.sin6_addr) != 1) - { - if (inet_pton (AF_INET, addrs, &srv_addr.in4.sin_addr) != 1) - { - fprintf (stderr, "cannot open convert server address %s - %s\n", addrs, strerror(errno)); - return -1; - } - else - { - srv_addr.in4.sin_family = AF_INET; - srv_addr.in4.sin_port = htons(8888); /* TODO: change it */ - srv_len = sizeof(srv_addr.in4); - sck_fam = AF_INET; - } - } - else - { - srv_addr.in6.sin6_family = AF_INET6; - srv_addr.in6.sin6_port = htons(8888); /* TODO: change it */ - srv_len = sizeof(srv_addr.in6); - sck_fam = AF_INET6; - } - - srv_fd = socket(sck_fam, SOCK_STREAM, 0); - if (srv_fd == -1) - { - strerror_r (errno, errbuf, HCL_COUNTOF(errbuf)); - server_write_log (server, SERVER_PROTO_LOG_MASK, "cannot open server socket - %s\n", errbuf); - return -1; - } - - optval = 1; - setsockopt (srv_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)); - - if (bind(srv_fd, (struct sockaddr*)&srv_addr, srv_len) == -1) - { - strerror_r (errno, errbuf, HCL_COUNTOF(errbuf)); - server_write_log (server, SERVER_PROTO_LOG_MASK, "cannot bind server socket %d - %s\n", srv_fd, errbuf); - close (srv_fd); - return -1; - } - - if (listen (srv_fd, 128) == -1) - { - strerror_r (errno, errbuf, HCL_COUNTOF(errbuf)); - server_write_log (server, SERVER_PROTO_LOG_MASK, "cannot listen on server socket %d - %s\n", srv_fd, errbuf); - close (srv_fd); - return -1; - } - - pthread_attr_init (&thr_attr); - pthread_attr_setstacksize (&thr_attr, server->cfg.worker_stack_size); - - server->stopreq = 0; - while (!server->stopreq) - { - sck_addr_t cli_addr; - int cli_fd; - socklen_t cli_len; - pthread_t thr; - - server_worker_t* worker; - - purge_all_workers (server, SERVER_WORKER_STATE_DEAD); - - cli_len = sizeof(cli_addr); - cli_fd = accept(srv_fd, (struct sockaddr*)&cli_addr, &cli_len); - if (cli_fd == -1) - { - if (errno != EINTR || !server->stopreq) - { - strerror_r (errno, errbuf, HCL_COUNTOF(errbuf)); - server_write_log (server, SERVER_PROTO_LOG_MASK, "cannot accept worker on socket %d - %s\n", srv_fd, errbuf); - } - break; - } - - worker = alloc_worker(server, cli_fd); - - if (pthread_create(&thr, &thr_attr, worker_main, worker) != 0) - { - free_worker (worker); - } - } - - purge_all_workers (server, SERVER_WORKER_STATE_ALIVE); - purge_all_workers (server, SERVER_WORKER_STATE_DEAD); - - pthread_attr_destroy (&thr_attr); - return 0; -} - -void server_stop (server_t* server) -{ - server->stopreq = 1; -} - -int server_setoption (server_t* server, server_option_t id, const void* value) -{ - switch (id) - { - case SERVER_TRAIT: - server->cfg.trait = *(const unsigned int*)value; - return 0; - - case SERVER_WORKER_STACK_SIZE: - server->cfg.worker_stack_size = *(hcl_oow_t*)value; - return 0; -// TODO: add more options - } - - //server_seterrnum (server, SERVER_EINVAL); - return -1; -} - -int server_getoption (server_t* server, server_option_t id, void* value) -{ - switch (id) - { - case SERVER_TRAIT: - *(unsigned int*)value = server->cfg.trait; - return 0; - - case SERVER_WORKER_STACK_SIZE: - *(hcl_oow_t*)value = server->cfg.worker_stack_size; - return 0; - }; - - //server_seterrnum (server, SERVER_EINVAL); - return -1; -} - - -/* ========================================================================= */ - -static server_t* g_server = HCL_NULL; - -/* ========================================================================= */ - -typedef void (*signal_handler_t) (int, siginfo_t*, void*); - -static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx) -{ - if (g_server) g_server->stopreq = 1; -} - -static void set_signal (int sig, signal_handler_t handler) -{ - struct sigaction sa; - - memset (&sa, 0, sizeof(sa)); - /*sa.sa_handler = handler;*/ - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = handler; - sigemptyset (&sa.sa_mask); - - sigaction (sig, &sa, NULL); -} - -static void set_signal_to_ignore (int sig) -{ - struct sigaction sa; - - memset (&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; - sigemptyset (&sa.sa_mask); - - sigaction (sig, &sa, NULL); -} - -static void set_signal_to_default (int sig) -{ - struct sigaction sa; - - memset (&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_DFL; - sa.sa_flags = 0; - sigemptyset (&sa.sa_mask); - - sigaction (sig, &sa, NULL); -} - -/* ========================================================================= */ - #define MIN_MEMSIZE 512000ul -int main_server (int argc, char* argv[]) +int main (int argc, char* argv[]) { hcl_bci_t c; static hcl_bopt_lng_t lopt[] = @@ -2190,7 +258,8 @@ int main_server (int argc, char* argv[]) lopt }; - server_t* server; + hcl_server_t* server; + server_xtn_t* xtn; int n; const char* logopt = HCL_NULL; @@ -2252,34 +321,42 @@ int main_server (int argc, char* argv[]) if (opt.ind >= argc) goto print_usage; - server = server_open(0, memsize, logopt, dbgopt); + server = hcl_server_open(HCL_SIZEOF(xtn_t), dbgopt); if (!server) { fprintf (stderr, "cannot open server\n"); return -1; } - + + xtn = (server_xtn_t*)hcl_server_getxtn(server); + xtn->logfd = -1; + xtn->logfd_istty = 0; + if (handle_logopt(server, logopt) <= -1) goto oops; - server_getoption (server, SERVER_TRAIT, &trait); - if (large_pages) trait |= SERVER_TRAIT_USE_LARGE_PAGES; - else trait &= SERVER_TRAIT_USE_LARGE_PAGES; - server_setoption (server, SERVER_TRAIT, &trait); + hcl_server_getoption (server, HCL_SERVER_TRAIT, &trait); + if (large_pages) trait |= HCL_SERVER_TRAIT_USE_LARGE_PAGES; + else trait &= HCL_SERVER_TRAIT_USE_LARGE_PAGES; + hcl_server_setoption (server, HCL_SERVER_TRAIT, &trait); + + /*hcl_server_setoption (server, HCL_SERVER_WORKER_STACK_SIZE, ???);*/ + hcl_server_setoption (server, HCL_SERVER_ACTOR_HEAP_SIZE, &memsize); + /*hcl_server_setoption (server, HCL_SERVER_ACTOR_DEBUG, &memsize);*/ g_server = server; set_signal (SIGINT, handle_sigint); set_signal_to_ignore (SIGPIPE); - n = server_start(server, argv[opt.ind]); + n = hcl_server_start(server, argv[opt.ind]); set_signal_to_default (SIGINT); set_signal_to_default (SIGPIPE); g_server = NULL; - server_close (server); + hcl_server_close (server); return n; - + oops: - if (server) server_close (server); + if (server) hcl_server_close (server); return -1; } diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 0000000..5fbf9fe --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,485 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 24 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/mod/Makefile.in b/mod/Makefile.in index 79f3629..7ba8bd3 100644 --- a/mod/Makefile.in +++ b/mod/Makefile.in @@ -96,10 +96,10 @@ host_triplet = @host@ subdir = mod ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_namespace.m4 \ - $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -318,6 +318,9 @@ PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ PACKAGE_VERSION_PATCH = @PACKAGE_VERSION_PATCH@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ QUADMATH_LIBS = @QUADMATH_LIBS@ RANLIB = @RANLIB@ SED = @SED@ @@ -339,6 +342,7 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@