From: Marcus Brinkmann Date: Sun, 2 Jun 2002 19:19:25 +0000 (+0000) Subject: 2002-06-02 Marcus Brinkmann X-Git-Tag: gpgme-0-3-7~7 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ae0d104de2fd61408387f098d6fba96b274f29d0;p=gpgme.git 2002-06-02 Marcus Brinkmann * configure.ac: Add checks for Pth and pthreads. * acinclude.m4: Add slightly hacked check for pth (seems to be an autoconf version problem). gpgme/ 2002-06-02 Marcus Brinkmann * Makefile.am (ath_components): New variable. (ath_components_pthread): Likewise. (ath_components_pth): Likewise. (system_components): Add ath_componentes. * ath.h: New file. * ath.c: Likewise. * ath-pthread.c: Likewise. * ath-pth.c: Likewise. * posix-sema.c (_gpgme_sema_cs_enter): Rework to use the ATH interface. * mutex.h: Remove file. --- diff --git a/ChangeLog b/ChangeLog index 00aa55b..092e0c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-06-02 Marcus Brinkmann + + * configure.ac: Add checks for Pth and pthreads. + * acinclude.m4: Add slightly hacked check for pth (seems to be an + autoconf version problem). + 2002-05-21 Werner Koch * configure.ac (NEED_GPGSM_VERSION): We need gpgsm 0.3.7. diff --git a/acinclude.m4 b/acinclude.m4 index 7cbdb15..88f2e43 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -43,3 +43,407 @@ AC_DEFUN(GNUPG_CHECK_TYPEDEF, [Define to 1 if $1 is defined in the header file.]) fi ]) + +dnl ## +dnl ## GNU Pth - The GNU Portable Threads +dnl ## Copyright (c) 1999-2002 Ralf S. Engelschall +dnl ## +dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling +dnl ## library which can be found at http://www.gnu.org/software/pth/. +dnl ## +dnl ## This library is free software; you can redistribute it and/or +dnl ## modify it under the terms of the GNU Lesser General Public +dnl ## License as published by the Free Software Foundation; either +dnl ## version 2.1 of the License, or (at your option) any later version. +dnl ## +dnl ## This library is distributed in the hope that it will be useful, +dnl ## but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl ## Lesser General Public License for more details. +dnl ## +dnl ## You should have received a copy of the GNU Lesser General Public +dnl ## License along with this library; if not, write to the Free Software +dnl ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl ## USA, or contact Ralf S. Engelschall . +dnl ## +dnl ## pth.m4: Autoconf macro for locating GNU Pth from within +dnl ## configure.in of third-party software packages +dnl ## + +dnl ## +dnl ## Synopsis: +dnl ## AC_CHECK_PTH([MIN-VERSION [, # minimum Pth version, e.g. 1.2.0 +dnl ## DEFAULT-WITH-PTH [, # default value for --with-pth option +dnl ## DEFAULT-WITH-PTH-TEST [,# default value for --with-pth-test option +dnl ## EXTEND-VARS [, # whether CFLAGS/LDFLAGS/etc are extended +dnl ## ACTION-IF-FOUND [, # action to perform if Pth was found +dnl ## ACTION-IF-NOT-FOUND # action to perform if Pth was not found +dnl ## ]]]]]]) +dnl ## Examples: +dnl ## AC_CHECK_PTH(1.2.0) +dnl ## AC_CHECK_PTH(1.2.0,,,no,CFLAGS="$CFLAGS -DHAVE_PTH $PTH_CFLAGS") +dnl ## AC_CHECK_PTH(1.2.0,yes,yes,yes,CFLAGS="$CFLAGS -DHAVE_PTH") +dnl ## +dnl +dnl # auxilliary macros +AC_DEFUN(_AC_PTH_ERROR, [dnl +AC_MSG_RESULT([*FAILED*]) +dnl define(_ac_pth_line,dnl +dnl "+------------------------------------------------------------------------+") +dnl echo " _ac_pth_line" 1>&2 +cat <>/ /' 1>&2 +$1 +EOT +dnl echo " _ac_pth_line" 1>&2 +dnl undefine(_ac_pth_line) +exit 1 +]) +AC_DEFUN(_AC_PTH_VERBOSE, [dnl +if test ".$verbose" = .yes; then + AC_MSG_RESULT([ $1]) +fi +]) +dnl # the user macro +AC_DEFUN(AC_CHECK_PTH, [dnl +dnl +dnl # prerequisites +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +dnl +PTH_CPPFLAGS='' +PTH_CFLAGS='' +PTH_LDFLAGS='' +PTH_LIBS='' +AC_SUBST(PTH_CPPFLAGS) +AC_SUBST(PTH_CFLAGS) +AC_SUBST(PTH_LDFLAGS) +AC_SUBST(PTH_LIBS) +dnl # command line options +AC_MSG_CHECKING(for GNU Pth) +_AC_PTH_VERBOSE([]) +AC_ARG_WITH(pth,dnl +[ --with-pth[=ARG] Build with GNU Pth Library (default=]ifelse([$2],,yes,$2)[)],dnl +,dnl +with_pth="ifelse([$2],,yes,$2)" +)dnl +AC_ARG_WITH(pth-test,dnl +[ --with-pth-test Perform GNU Pth Sanity Test (default=]ifelse([$3],,yes,$3)[)],dnl +,dnl +with_pth_test="ifelse([$3],,yes,$3)" +)dnl +_AC_PTH_VERBOSE([+ Command Line Options:]) +_AC_PTH_VERBOSE([ o --with-pth=$with_pth]) +_AC_PTH_VERBOSE([ o --with-pth-test=$with_pth_test]) +dnl +dnl # configuration +if test ".$with_pth" != .no; then + _pth_subdir=no + _pth_subdir_opts='' + case "$with_pth" in + subdir:* ) + _pth_subdir=yes + changequote(, )dnl + _pth_subdir_opts=`echo $with_pth | sed -e 's/^subdir:[^ ]*[ ]*//'` + with_pth=`echo $with_pth | sed -e 's/^subdir:\([^ ]*\).*$/\1/'` + changequote([, ])dnl + ;; + esac + _pth_version="" + _pth_location="" + _pth_type="" + _pth_cppflags="" + _pth_cflags="" + _pth_ldflags="" + _pth_libs="" + if test ".$with_pth" = .yes; then + # via config script in $PATH + changequote(, )dnl + _pth_version=`(pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`pth-config --prefix` + _pth_type='installed' + _pth_cppflags=`pth-config --cflags` + _pth_cflags=`pth-config --cflags` + _pth_ldflags=`pth-config --ldflags` + _pth_libs=`pth-config --libs` + fi + elif test -d "$with_pth"; then + with_pth=`echo $with_pth | sed -e 's;/*$;;'` + _pth_found=no + # via locally included source tree + if test ".$_pth_subdir" = .yes; then + _pth_location="$with_pth" + _pth_type='local' + _pth_cppflags="-I$with_pth" + _pth_cflags="-I$with_pth" + if test -f "$with_pth/ltconfig"; then + _pth_ldflags="-L$with_pth/.libs" + else + _pth_ldflags="-L$with_pth" + fi + _pth_libs="-lpth" + changequote(, )dnl + _pth_version=`grep '^const char PTH_Hello' $with_pth/pth_vers.c |\ + sed -e 's;^.*Version[ ]*\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + changequote([, ])dnl + _pth_found=yes + ac_configure_args="$ac_configure_args --enable-subdir $_pth_subdir_opts" + with_pth_test=no + fi + # via config script under a specified directory + # (a standard installation, but not a source tree) + if test ".$_pth_found" = .no; then + for _dir in $with_pth/bin $with_pth; do + if test -f "$_dir/pth-config"; then + test -f "$_dir/pth-config.in" && continue # pth-config in source tree! + changequote(, )dnl + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`$_dir/pth-config --prefix` + _pth_type="installed" + _pth_cppflags=`$_dir/pth-config --cflags` + _pth_cflags=`$_dir/pth-config --cflags` + _pth_ldflags=`$_dir/pth-config --ldflags` + _pth_libs=`$_dir/pth-config --libs` + _pth_found=yes + break + fi + fi + done + fi + # in any subarea under a specified directory + # (either a special installation or a Pth source tree) + if test ".$_pth_found" = .no; then + changequote(, )dnl + _pth_found=0 + for _file in x `find $with_pth -name "pth.h" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + if test ".$_pth_version" = .; then + _pth_version=`grep '^#define PTH_VERSION_STR' $_file |\ + sed -e 's;^#define[ ]*PTH_VERSION_STR[ ]*"\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + fi + _pth_cppflags="-I$_dir" + _pth_cflags="-I$_dir" + _pth_found=`expr $_pth_found + 1` + done + for _file in x `find $with_pth -name "libpth.[aso]" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_ldflags="-L$_dir" + _pth_libs="-lpth" + _pth_found=`expr $_pth_found + 1` + done + changequote([, ])dnl + if test ".$_pth_found" = .2; then + _pth_location="$with_pth" + _pth_type="uninstalled" + else + _pth_version='' + fi + fi + fi + _AC_PTH_VERBOSE([+ Determined Location:]) + _AC_PTH_VERBOSE([ o path: $_pth_location]) + _AC_PTH_VERBOSE([ o type: $_pth_type]) + if test ".$_pth_version" = .; then + if test ".$with_pth" != .yes; then + _AC_PTH_ERROR([dnl + Unable to locate GNU Pth under $with_pth. + Please specify the correct path to either a GNU Pth installation tree + (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in + the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a + path to a pth-X.Y.Z/ directory; but make sure the package is already + built, i.e., the "configure; make" step was already performed there).]) + else + _AC_PTH_ERROR([dnl + Unable to locate GNU Pth in any system-wide location (see \$PATH). + Please specify the correct path to either a GNU Pth installation tree + (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in + the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a + path to a pth-X.Y.Z/ directory; but make sure the package is already + built, i.e., the "configure; make" step was already performed there).]) + fi + fi + dnl # + dnl # Check whether the found version is sufficiently new + dnl # + _req_version="ifelse([$1],,1.0.0,$1)" + for _var in _pth_version _req_version; do + eval "_val=\"\$${_var}\"" + _major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'` + _minor=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\2/'` + _rtype=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\3/'` + _micro=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\4/'` + case $_rtype in + "a" ) _rtype=0 ;; + "b" ) _rtype=1 ;; + "." ) _rtype=2 ;; + esac + _hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \ + "major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"` + eval "${_var}_hex=\"\$_hex\"" + done + _AC_PTH_VERBOSE([+ Determined Versions:]) + _AC_PTH_VERBOSE([ o existing: $_pth_version -> 0x$_pth_version_hex]) + _AC_PTH_VERBOSE([ o required: $_req_version -> 0x$_req_version_hex]) + _ok=0 + if test ".$_pth_version_hex" != .; then + if test ".$_req_version_hex" != .; then + if test $_pth_version_hex -ge $_req_version_hex; then + _ok=1 + fi + fi + fi + if test ".$_ok" = .0; then + _AC_PTH_ERROR([dnl + Found Pth version $_pth_version, but required at least version $_req_version. + Upgrade Pth under $_pth_location to $_req_version or higher first, please.]) + fi + dnl # + dnl # Perform Pth Sanity Compile Check + dnl # + if test ".$with_pth_test" = .yes; then + _ac_save_CPPFLAGS="$CPPFLAGS" + _ac_save_CFLAGS="$CFLAGS" + _ac_save_LDFLAGS="$LDFLAGS" + _ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + _AC_PTH_VERBOSE([+ Test Build Environment:]) + _AC_PTH_VERBOSE([ o CPPFLAGS=\"$CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o CFLAGS=\"$CFLAGS\"]) + _AC_PTH_VERBOSE([ o LDFLAGS=\"$LDFLAGS\"]) + _AC_PTH_VERBOSE([ o LIBS=\"$LIBS\"]) + cross_compile=no + define(_code1, [dnl + #include + #include + ]) + define(_code2, [dnl + int main(int argc, char *argv[]) + { + FILE *fp; + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "hmm"); + fclose(fp); + pth_init(); + pth_kill(); + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "yes"); + fclose(fp); + exit(0); + } + ]) + _AC_PTH_VERBOSE([+ Performing Sanity Checks:]) + _AC_PTH_VERBOSE([ o pre-processor test]) + AC_TRY_CPP(_code1, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity pre-processor check. This means + the GNU Pth header pth.h was not found. + We used the following build environment: + >> CPP="$CPP" + >> CPPFLAGS="$CPPFLAGS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o link check]) + AC_TRY_LINK(_code1, _code2, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity linker check. This means + the GNU Pth library libpth.a was not found. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o run-time check]) + AC_TRY_RUN(_code1 _code2, _ok=`cat conftestval`, _ok=no, _ok=no) + if test ".$_ok" != .yes; then + if test ".$_ok" = .no; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity execution check. This usually + means that the GNU Pth shared library libpth.so is present + but \$LD_LIBRARY_PATH is incomplete to execute a Pth test. + In this case either disable this test via --without-pth-test, + or extend \$LD_LIBRARY_PATH, or build GNU Pth as a static + library only via its --disable-shared Autoconf option. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + else + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity run-time check. This usually + means that the GNU Pth library failed to work and possibly + caused a core dump in the test program. In this case it + is strongly recommended that you re-install GNU Pth and this + time make sure that it really passes its "make test" procedure. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + fi + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" != .yes; then + CPPFLAGS="$_ac_save_CPPFLAGS" + CFLAGS="$_ac_save_CFLAGS" + LDFLAGS="$_ac_save_LDFLAGS" + LIBS="$_ac_save_LIBS" + fi + else + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" = .yes; then + if test ".$_pth_subdir" = .yes; then + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + fi + fi + fi + PTH_CPPFLAGS="$_pth_cppflags" + PTH_CFLAGS="$_pth_cflags" + PTH_LDFLAGS="$_pth_ldflags" + PTH_LIBS="$_pth_libs" + AC_SUBST(PTH_CPPFLAGS) + AC_SUBST(PTH_CFLAGS) + AC_SUBST(PTH_LDFLAGS) + AC_SUBST(PTH_LIBS) + _AC_PTH_VERBOSE([+ Final Results:]) + _AC_PTH_VERBOSE([ o PTH_CPPFLAGS=\"$PTH_CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_CFLAGS=\"$PTH_CFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LDFLAGS=\"$PTH_LDFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LIBS=\"$PTH_LIBS\"]) +fi +if test ".$with_pth" != .no; then + AC_MSG_RESULT([version $_pth_version, $_pth_type under $_pth_location]) + ifelse([$5], , :, [$5]) +else + AC_MSG_RESULT([no]) + ifelse([$6], , :, [$6]) +fi +]) + diff --git a/configure.ac b/configure.ac index 3e160e1..afdf4c9 100644 --- a/configure.ac +++ b/configure.ac @@ -99,12 +99,24 @@ case "${target}" in #component_system='COM+' ;; *) + AC_CHECK_PTH(1.2.0,,,no,have_pth=yes) + if test "$have_pth" = yes; then + AC_DEFINE(HAVE_PTH, ,[Define if we have Pth.]) + CFLAGS="$CFLAGS $PTH_CFLAGS" + fi + AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes) + if test "$have_pthread" = yes; then + AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.]) + fi + dnl # XXX: Probably use exec-prefix here? dnl GPG_DEFAULT='/usr/bin/gpg' dnl GPGSM_DEFAULT='/usr/bin/gpgsm' ;; esac AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = "yes") +AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") +AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes") dnl dnl Checks for libraries. diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 2cb8c77..f8bc8ec 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,18 @@ +2002-06-02 Marcus Brinkmann + + * Makefile.am (ath_components): New variable. + (ath_components_pthread): Likewise. + (ath_components_pth): Likewise. + (system_components): Add ath_componentes. + + * ath.h: New file. + * ath.c: Likewise. + * ath-pthread.c: Likewise. + * ath-pth.c: Likewise. + * posix-sema.c (_gpgme_sema_cs_enter): Rework to use the ATH + interface. + * mutex.h: Remove file. + 2002-05-30 Werner Koch * key.c (gpgme_key_get_string_attr): Return NULL when asking for diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 93341a1..42e43e8 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -35,10 +35,22 @@ AM_CPPFLAGS = -I$(top_srcdir)/assuan libgpgme_la_LIBADD = ../assuan/libassuan.la ../jnlib/libjnlib.la endif +if HAVE_PTHREAD +ath_components_pthread = ath-pthread.c +else +ath_components_pthread = +endif +if HAVE_PTH +ath_components_pth = ath-pth.c +else +ath_components_pth = +endif +ath_components = ath.h ath.c ${ath_components_pthread} ${ath_components_pth} + if HAVE_DOSISH_SYSTEM system_components = w32-util.c w32-sema.c w32-io.c else -system_components = posix-util.c posix-sema.c posix-io.c +system_components = ${ath_components} posix-util.c posix-sema.c posix-io.c endif libgpgme_la_SOURCES = \ diff --git a/gpgme/ath-pth.c b/gpgme/ath-pth.c new file mode 100644 index 0000000..cac414c --- /dev/null +++ b/gpgme/ath-pth.c @@ -0,0 +1,117 @@ +/* ath-pth.c - Pth module for self-adapting thread-safeness library + * Copyright (C) 2002 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include + +#include "ath.h" + +#pragma weak pth_mutex_init +#pragma weak pth_mutex_acquire +#pragma weak pth_mutex_release +#pragma weak pth_read +#pragma weak pth_write +#pragma weak pth_select +#pragma weak pth_waitpid + +/* The lock we take while checking for lazy lock initialization. */ +static pth_mutex_t check_init_lock = PTH_MUTEX_INIT; + +/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if + it is not already initialized. */ +static int +mutex_pth_init (void **priv, int just_check) +{ + int err = 0; + + if (just_check) + pth_mutex_acquire (&check_init_lock, 0, NULL); + if (!*priv || !just_check) + { + pth_mutex_t *lock = malloc (sizeof (pth_mutex_t)); + if (!lock) + err = ENOMEM; + if (!err) + { + err = pth_mutex_init (lock); + if (err == FALSE) + err = errno; + else + err = 0; + + if (err) + free (lock); + else + *priv = lock; + } + } + if (just_check) + pth_mutex_release (&check_init_lock); + return err; +} + + +static int +mutex_pth_destroy (void *priv) +{ + free (priv); + return 0; +} + + +static int +mutex_pth_lock (void *priv) +{ + int ret = pth_mutex_acquire ((pth_mutex_t *) priv, 0, NULL); + return ret == FALSE ? errno : 0; +} + + +static int +mutex_pth_unlock (void *priv) +{ + int ret = pth_mutex_release ((pth_mutex_t *) priv); + return ret == FALSE ? errno : 0; +} + + +static struct ath_ops ath_pth_ops = + { + mutex_pth_init, + mutex_pth_destroy, + mutex_pth_lock, + mutex_pth_unlock, + pth_read, + pth_write, + pth_select, + pth_waitpid + }; + + +struct ath_ops * +ath_pth_available (void) +{ + if (pth_mutex_init && pth_mutex_acquire && pth_mutex_release + && pth_read && pth_write && pth_select && pth_waitpid) + return &ath_pth_ops; + else + return 0; +} diff --git a/gpgme/ath-pthread.c b/gpgme/ath-pthread.c new file mode 100644 index 0000000..ec250d8 --- /dev/null +++ b/gpgme/ath-pthread.c @@ -0,0 +1,100 @@ +/* ath-pthread.c - pthread module for self-adapting thread-safeness library + * Copyright (C) 2002 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include + +#include "ath.h" + +/* Need to include pthread_create in our check, as the GNU C library + has the pthread_mutex_* functions in their public interface. */ +#pragma weak pthread_create +#pragma weak pthread_mutex_init +#pragma weak pthread_mutex_destroy +#pragma weak pthread_mutex_lock +#pragma weak pthread_mutex_unlock + +/* The lock we take while checking for lazy lock initialization. */ +static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER; + +/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if + it is not already initialized. */ +static int +mutex_pthread_init (void **priv, int just_check) +{ + int err = 0; + + if (just_check) + pthread_mutex_lock (&check_init_lock); + if (!*priv || !just_check) + { + pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t)); + if (!lock) + err = ENOMEM; + if (!err) + { + err = pthread_mutex_init (lock, NULL); + if (err) + free (lock); + else + *priv = lock; + } + } + if (just_check) + pthread_mutex_unlock (&check_init_lock); + return err; +} + + +static int +mutex_pthread_destroy (void *priv) +{ + int err = pthread_mutex_destroy ((pthread_mutex_t *) priv); + free (priv); + return err; +} + + +static struct ath_ops ath_pthread_ops = + { + mutex_pthread_init, + mutex_pthread_destroy, + (int (*) (void *)) pthread_mutex_lock, + (int (*) (void *)) pthread_mutex_unlock, + NULL, /* read */ + NULL, /* write */ + NULL, /* select */ + NULL /* waitpid */ + }; + + +struct ath_ops * +ath_pthread_available (void) +{ + /* Need to include pthread_create in our check, as the GNU C library + has the pthread_mutex_* functions in their public interface. */ + if (pthread_create + && pthread_mutex_init && pthread_mutex_destroy + && pthread_mutex_lock && pthread_mutex_unlock) + return &ath_pthread_ops; + else + return 0; +} diff --git a/gpgme/ath.c b/gpgme/ath.c new file mode 100644 index 0000000..e685031 --- /dev/null +++ b/gpgme/ath.c @@ -0,0 +1,141 @@ +/* ath.c - self-adapting thread-safeness library + * Copyright (C) 2002 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "ath.h" + +static struct ath_ops *ath_ops; + +void +ath_init (void) +{ +#ifdef HAVE_PTHREAD + if (!ath_ops) + ath_ops = ath_pthread_available (); +#endif +#ifdef HAVE_PTH + if (!ath_ops) + ath_ops = ath_pth_available (); +#endif +#ifdef HAVE_ATH_DUMMY + if (!ath_ops) + ath_ops = ath_dummy_available (); +#endif +} + + +int +ath_mutex_init (ath_mutex_t *lock) +{ + if (!ath_ops) + return 0; + + return ath_ops->mutex_init (lock, 0); +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ + int err; + if (!ath_ops) + return 0; + err = ath_ops->mutex_init (lock, 1); + if (!err) + err = ath_ops->mutex_destroy (*lock); + return err; +} + + +int +ath_mutex_lock (ath_mutex_t *lock) +{ + int err; + + if (!ath_ops) + return 0; + err = ath_ops->mutex_init (lock, 1); + if (!err) + err = ath_ops->mutex_lock (*lock); + return err; +} + + +int +ath_mutex_unlock (ath_mutex_t *lock) +{ + int err; + + if (!ath_ops) + return 0; + err = ath_ops->mutex_init (lock, 1); + if (!err) + err = ath_ops->mutex_unlock (*lock); + return err; +} + + +ssize_t +ath_read (int fd, void *buf, size_t nbytes) +{ + if (ath_ops && ath_ops->read) + return ath_ops->read (fd, buf, nbytes); + else + return read (fd, buf, nbytes); +} + + +ssize_t +ath_write (int fd, const void *buf, size_t nbytes) +{ + if (ath_ops && ath_ops->write) + return ath_ops->write (fd, buf, nbytes); + else + return write (fd, buf, nbytes); +} + + +ssize_t +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +{ + if (ath_ops && ath_ops->select) + return ath_ops->select (nfd, rset, wset, eset, timeout); + else + return select (nfd, rset, wset, eset, timeout); +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ + if (ath_ops && ath_ops->waitpid) + return ath_ops->waitpid (pid, status, options); + else + return waitpid (pid, status, options); +} diff --git a/gpgme/ath.h b/gpgme/ath.h new file mode 100644 index 0000000..c0a8e20 --- /dev/null +++ b/gpgme/ath.h @@ -0,0 +1,93 @@ +/* ath.h - interfaces for self-adapting thread-safeness library + * Copyright (C) 2002 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef ATH_H +#define ATH_H + +#include + +/* Define ATH_EXT_SYM_PREFIX if you want to give all external symbols + a prefix. */ +/* #define ATH_EXT_SYM_PREFIX _gpgme_ */ + +#ifdef ATH_EXT_SYM_PREFIX +#define ath_pkg_init MUTEX_EXT_SYM_PREFIX##ath_pkg_init +#define ath_mutex_init MUTEX_EXT_SYM_PREFIX##ath_mutex_init +#define ath_mutex_destroy MUTEX_EXT_SYM_PREFIX##ath_mutex_destroy +#define ath_mutex_lock MUTEX_EXT_SYM_PREFIX##ath_mutex_lock +#define ath_mutex_pthread_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_pthread_available +#define ath_mutex_pth_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_pth_available +#define ath_mutex_dummy_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_dummy_available +#define ath_read MUTEX_EXT_SYM##ath_read +#define ath_write MUTEX_EXT_SYM##ath_write +#define ath_select MUTEX_EXT_SYM##ath_select +#define ath_waitpid MUTEX_EXT_SYM##ath_waitpid +#define ath_mutex_pthread_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_pthread_available +#define ath_mutex_pthr_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_pthr_available +#define ath_mutex_dummy_available \ + MUTEX_EXT_SYM_PREFIX##ath_mutex_dummy_available +#endif + + +typedef void *ath_mutex_t; +#define ATH_MUTEX_INITIALIZER 0; + +/* Functions for mutual exclusion. */ +int ath_mutex_init (ath_mutex_t *mutex); +int ath_mutex_destroy (ath_mutex_t *mutex); +int ath_mutex_lock (ath_mutex_t *mutex); +int ath_mutex_unlock (ath_mutex_t *mutex); + +/* Replacement for the POSIX functions, which can be used to allow + other (user-level) threads to run. */ +ssize_t ath_read (int fd, void *buf, size_t nbytes); +ssize_t ath_write (int fd, const void *buf, size_t nbytes); +ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); + + +struct ath_ops +{ + int (*mutex_init) (void **priv, int just_check); + int (*mutex_destroy) (void *priv); + int (*mutex_lock) (void *priv); + int (*mutex_unlock) (void *priv); + ssize_t (*read) (int fd, void *buf, size_t nbytes); + ssize_t (*write) (int fd, const void *buf, size_t nbytes); + ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); + ssize_t (*waitpid) (pid_t pid, int *status, int options); +}; + +/* Initialize the any-thread package. */ +void ath_init (void); + +/* Used by ath_pkg_init. */ +struct ath_ops *ath_pthread_available (void); +struct ath_ops *ath_pth_available (void); +struct ath_ops *ath_dummy_available (void); + +#endif /* ATH_H */ diff --git a/gpgme/mutex.h b/gpgme/mutex.h deleted file mode 100644 index a1cf868..0000000 --- a/gpgme/mutex.h +++ /dev/null @@ -1,124 +0,0 @@ -/* mutex.h - Portable mutual exclusion, independent from any thread library. - * Copyright (C) 2002 g10 Code GmbH - * - * This file is part of GPGME. - * - * GPGME 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 2 of the License, or - * (at your option) any later version. - * - * GPGME 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#ifndef MUTEX_H -#define MUTEX_H - -/* Define MUTEX_FAKE before including the file to get stubs that don't - provide any locking at all. Define MUTEX_PTHREAD if you can link - against the posix thread library. */ - -#if defined(MUTEX_FAKE) - -typedef char mutex_t; -#define mutex_init(x) (0) -#define mutex_destroy(x) -#define mutex_lock(x) (0) -#define mutex_unlock(x) (0) - -#elif defined(MUTEX_PTHREAD) - -#include - -#define mutex_t pthread_mutex_t -#define mutex_init(x) pthread_mutex_init (&(x), 0) -#define mutex_destroy(x) pthread_mutex_destroy(&(x)) -#define mutex_lock(x) pthread_mutex_lock (&(x)) -#define mutex_unlock(x) pthread_mutex_unlock (&(x)) - -#else - -#include -#include -#include - -/* The type of a mutex. */ -typedef int mutex_t[2]; - -inline static int -set_close_on_exec (int fd) -{ - int flags = fcntl (fd, F_GETFD, 0); - if (flags == -1) - return errno; - flags |= FD_CLOEXEC; - if (fcntl (fd, F_SETFD, flags) == -1) - return errno; - return 0; -} - -/* Initialize the mutex variable MUTEX. */ -inline int -mutex_init (mutex_t mutex) -{ - ssize_t amount; - int err = 0; - - if (pipe (mutex)) - return errno; - - err = set_close_on_exec (mutex[0]); - if (!err) - err = set_close_on_exec (mutex[1]); - if (!err) - while ((amount = write (mutex[1], " ", 1)) < 0 && errno == EINTR) - ; - if (!err && amount != 1) - err = errno; - - if (err) - { - close (mutex[0]); - close (mutex[1]); - } - return err; -} - -/* Destroy the mutex variable MUTEX. */ -inline void -mutex_destroy (mutex_t mutex) -{ - close (mutex[0]); - close (mutex[1]); -} - -/* Take the mutex variable MUTEX. */ -inline int -mutex_lock (mutex_t mutex) -{ - char data; - int amount; - while ((amount = read (mutex[0], &data, 1)) < 0 && errno == EINTR) - ; - return (amount != 1) ? errno : 0; -} - -/* Release the mutex variable MUTEX. */ -inline int -mutex_unlock (mutex_t mutex) -{ - int amount; - while ((amount = write (mutex[1], " ", 1)) < 0 && errno == EINTR) - ; - return (amount != 1) ? errno : 0; -} - -#endif /* MUTEX_FAKE */ -#endif /* MUTEX_H */ diff --git a/gpgme/posix-sema.c b/gpgme/posix-sema.c index aff8bbc..bcb1339 100644 --- a/gpgme/posix-sema.c +++ b/gpgme/posix-sema.c @@ -35,7 +35,7 @@ #include "util.h" #include "sema.h" -#include "mutex.h" +#include "ath.h" static void sema_fatal (const char *text) @@ -44,76 +44,28 @@ sema_fatal (const char *text) abort (); } - -static void -critsect_init (struct critsect_s *s) -{ - static mutex_t init_lock; - static int initialized; - mutex_t *mp; - - if (!initialized) - { - /* The very first time we call this function, we assume that - only one thread is running, so that we can bootstrap the - semaphore code. */ - mutex_init (init_lock); - initialized = 1; - } - if (!s) - return; /* We just want to initialize ourself. */ - - /* First test whether it is really not initialized. */ - mutex_lock (init_lock); - if (s->private) - { - mutex_unlock (init_lock); - return; - } - /* Now initialize it. */ - mp = xtrymalloc (sizeof *mp); - if (!mp) - { - mutex_unlock (init_lock); - sema_fatal ("out of core while creating critical section lock"); - } - mutex_init (*mp); - s->private = mp; - mutex_unlock (init_lock); -} - - void _gpgme_sema_subsystem_init () { /* FIXME: we should check that there is only one thread running */ - critsect_init (NULL); + ath_init (); } - void _gpgme_sema_cs_enter (struct critsect_s *s) { - if (!s->private) - critsect_init (s); - mutex_lock (*((mutex_t *) s->private)); + ath_mutex_lock (&s->private); } void _gpgme_sema_cs_leave (struct critsect_s *s) { - if (!s->private) - critsect_init (s); - mutex_unlock (*((mutex_t *) s->private)); + ath_mutex_unlock (&s->private); } void _gpgme_sema_cs_destroy (struct critsect_s *s) { - if (s && s->private) - { - mutex_destroy (*((mutex_t *) s->private)); - xfree (s->private); - s->private = NULL; - } + ath_mutex_destroy (&s->private); + s->private = NULL; }