2004-03-10 Marcus Brinkmann <marcus@g10code.de> marcus-after-thread-cbs
authorMarcus Brinkmann <mb@g10code.com>
Thu, 11 Mar 2004 01:44:44 +0000 (01:44 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 11 Mar 2004 01:44:44 +0000 (01:44 +0000)
* configure.ac (LIBGCRYPT_CONFIG_LIBS_PTHREAD,
LIBGCRYPT_CONFIG_CFLAGS_PTHREAD, LIBGCRYPT_CONFIG_LIBS_PTH,
LIBGCRYPT_CONFIG_CFLAGS_PTH, have_pth, have_pthread, AC_CHECK_PTH,
AC_CHECK_LIB(pthread), HAVE_PTH, HAVE_PTHREAD): Removed.

doc/
2004-03-11  Marcus Brinkmann  <marcus@g10code.de>

* gcrypt.texi (Multi Threading): Partially document new thread
support.

src/
2004-03-10  Marcus Brinkmann  <marcus@g10code.de>

* Makefile.am (ltlib_libgcrypt_pthread, ltlib_libgcrypt_pth): Removed.
(lib_LTLIBRARIES): Remove those variables from here.
(libgcrypt_pthread_la_SOURCES, libgcrypt_pthread_la_LDFLAGS,
(libgcrypt_pthread_la_DEPENDENCIES, libgcrypt_pthread_la_LIBADD,
(libgcrypt_pth_la_SOURCES, libgcrypt_pth_la_LDFLAGS,
(libgcrypt_pth_la_DEPENDENCIES, libgcrypt_pth_la_LIBADD,
(noinst_LTLIBRARIES): Removed.
(libgcrypt_real_la_SOURCES): Merge with ...
(libgcrypt_la_SOURCES): ... likewise.
(libgcrypt_real_la_DEPENDENCIES): Merge with ...
(libgcrypt_la_DEPENDENCIES): ... this.
(libgcrypt_real_la_LIBADD): Merge with ...
(libgcrypt_la_LIBADD): ... this.
* libgcrypt-config.in (libs_pthread, libs_pth, cflags_pth)
(cflags_pthread, thread_module, thread_modules): Removed.
(Options): Remove --thread option from help output.  If the option
is specified, output an error and exit.
For --cflags and --libs option, remove pth and pthread from output.
* gcrypt.h: Include <sys/types.h> and <sys/socket.h>.
(enum gcry_ctl_cmds): Add GCRYCTL_SET_THREAD_CBS.
(gcry_thread_cbs): New struct.
* global.c (gcry_control): Implement GCRYCTL_SET_THREAD_CBS.
(global_init): Don't call ath_init here.
* ath.h: Rewritten.
* ath.c: Rewritten.

12 files changed:
ChangeLog
NEWS
configure.ac
doc/ChangeLog
doc/gcrypt.texi
src/ChangeLog
src/Makefile.am
src/ath.c
src/ath.h
src/gcrypt.h
src/global.c
src/libgcrypt-config.in

index bbc7674..bbf5169 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-03-10  Marcus Brinkmann  <marcus@g10code.de>
+
+       * configure.ac (LIBGCRYPT_CONFIG_LIBS_PTHREAD,
+       LIBGCRYPT_CONFIG_CFLAGS_PTHREAD, LIBGCRYPT_CONFIG_LIBS_PTH,
+       LIBGCRYPT_CONFIG_CFLAGS_PTH, have_pth, have_pthread, AC_CHECK_PTH,
+       AC_CHECK_LIB(pthread), HAVE_PTH, HAVE_PTHREAD): Removed.
+
 2004-03-06  Werner Koch  <wk@gnupg.org>
 
        Released 1.1.93.
diff --git a/NEWS b/NEWS
index 5c97f14..290aa67 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,24 @@
 Noteworthy changes in version 1.1.94
 -------------------------------------------------
 
+ * The support for multi-threaded users goes into its third
+   incarnation.  We removed compile time support for thread libraries.
+   To support the thread library of your choice, you have to set up
+   callback handlers at initialization time.  New data structures, a
+   new control command, and default initializers are provided for this
+   purpose.
+
+ * Interface changes relative to the 1.1.93 release:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+libgcrypt-config --thread      OBSOLETE
+libgcrypt-pth.la               REMOVED
+libgcrypt-pthread.la           REMOVED
+GCRYCTL_SET_THREAD_CBS         NEW
+struct gcrypt_thread_cbs       NEW
+enum gcry_thread_option                NEW
+GCRY_THREAD_OPTION_PTH_IMPL    NEW
+GCRY_THREAD_OPTION_PTHREAD_IMPL        NEW
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Noteworthy changes in version 1.1.93 (2004-03-06)
 -------------------------------------------------
index 61eced6..c07f53a 100644 (file)
@@ -85,10 +85,6 @@ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
 # Used by libgcrypt-config
 LIBGCRYPT_CONFIG_LIBS="-lgcrypt"
 LIBGCRYPT_CONFIG_CFLAGS=""
-LIBGCRYPT_CONFIG_LIBS_PTHREAD="-lgcrypt-pthread"
-LIBGCRYPT_CONFIG_CFLAGS_PTHREAD=""
-LIBGCRYPT_CONFIG_LIBS_PTH="-lgcrypt-pth"
-LIBGCRYPT_CONFIG_CFLAGS_PTH=""
 
 # Definitions for symmetric ciphers.
 available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268"
@@ -493,31 +489,6 @@ AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime)
 
 GNUPG_CHECK_MLOCK
 
-# Check which thread libraries are supported by the system.
-have_pth=no
-have_pthread=no
-
-AC_CHECK_PTH(1.2.0,,,no,have_pth=yes)
-if test "$have_pth" = yes; then
-  LIBGCRYPT_CONFIG_LIBS_PTH="$LIBGCRYPT_CONFIG_LIBS_PTH -lpth"
-  LIBGCRYPT_THREAD_MODULES="$LIBGCRYPT_THREAD_MODULES pth"
-  AC_DEFINE(HAVE_PTH, ,[Define if we have Pth.])
-fi
-
-AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
-if test "$have_pthread" = yes; then
-  LIBGCRYPT_CONFIG_LIBS_PTHREAD="$LIBGCRYPT_CONFIG_LIBS_PTHREAD -lpthread"
-else
-  AC_CHECK_LIB(c,pthread_create,have_pthread=yes)
-fi
-if test "$have_pthread" = yes; then
-  LIBGCRYPT_THREAD_MODULES="$LIBGCRYPT_THREAD_MODULES pthread"
-  AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.])
-fi
-
-AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
-AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
-
 # Check whether we can use Linux capabilities as requested.
 if test "$use_capabilities" = "yes" ; then
 use_capabilities=no
@@ -660,10 +631,6 @@ GNUPG_FIX_HDR_VERSION([src/gcrypt.h], GCRYPT_VERSION)
 AC_SUBST(LIBGCRYPT_CONFIG_API_VERSION)
 AC_SUBST(LIBGCRYPT_CONFIG_LIBS)
 AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS)
-AC_SUBST(LIBGCRYPT_CONFIG_LIBS_PTHREAD)
-AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS_PTHREAD)
-AC_SUBST(LIBGCRYPT_CONFIG_LIBS_PTH)
-AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS_PTH)
 AC_SUBST(LIBGCRYPT_THREAD_MODULES)
 
 AC_CONFIG_COMMANDS([gcrypt-conf],[[
index 3886999..085fca0 100644 (file)
@@ -1,3 +1,8 @@
+2004-03-11  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gcrypt.texi (Multi Threading): Partially document new thread
+       support.
+
 2004-02-24  Werner Koch  <wk@gnupg.org>
 
        * gcrypt.texi (Calculations): Typo fix.
index 6873f0f..63bc3a3 100644 (file)
@@ -256,9 +256,6 @@ different threads on the same handle, he has to take care of the
 serialisation of such functions himself.  If not described otherwise,
 every function is thread-safe.
 
-The library automagically detects whether an applications uses no
-threading, pthreads or GNU Pth.
-
 @acronym{Libgcrypt} depends on the library `libgpg-error', which
 contains common error handling related code for GnuPG components.
 
@@ -413,37 +410,51 @@ thread-safe if you adhere to the following requirements:
 
 @itemize @bullet
 @item
-@acronym{Libgcrypt} supports the thread libraries pthread and GNU Pth.
-The support for this has to be enabled at compile time.
-@acronym{Libgcrypt} will automatically detect the location in which the
-thread libraries are installed and activate the support for them at
-build time.
-
-Support for other thread libraries is very easy to add.  Please
-contact us if you have the need.
-
-@item
-If you want to use @acronym{Libgcrypt} with threads, you must link to
-the right version of the library.  The name of the right library is
-@code{libgcrypt-} followed by the name of the thread package you use.
-For example, if you use GNU Pth, the right name is
-@code{libgcrypt-pth}.  Use the Automake macros or
-@command{libgcrypt-config} program for simplicity.
+If your application is multi-threaded, you must set the thread support
+callbacks with the @code{GCRYCTL_SET_THREAD_CBS} command
+@strong{before} any other function in the library.
+
+This is easy enough if you are indeed writing an application using
+libgcrypt.  It is rather problematic if you are writing a library
+instead.  Here are some tips what to do if you are writing a library:
+
+If your library requires a certain thread package, just initialize
+gcrypt to use this thread package.  If your library supports multiple
+thread packages, but needs to be configured, you will have to
+implement a way to determine which thread package the application
+wants to use with your library anyway.  Then configure gcrypt to use
+this thread package.
+
+If your library is fully reentrant without any special support by a
+thread package, then you are lucky indeed.  Unfortunately, this does
+not relieve you from doing either of the two above, or use a third
+option.  The third option is to let the application initialize gcrypt
+for you.  Then you are not using gcrypt transparently, though.
+
+As if this was not difficult enough, a conflict may arise if two
+libraries try to initialize gcrypt independently of each others, and
+both such libraries are then linked into the same application.  To
+make it a bit simpler for you, this will probably work, but only if
+both libraries have the same requirement for the thread package.  This
+is currently only supported for the non-threaded case, GNU Pth and
+pthread.  Support for more thread packages is easy to add, so contact
+is if you require it.
 
 @item
 The function @code{gcry_check_version} must be called before any other
-function in the library, because it initializes the thread support
-subsystem in @acronym{Libgcrypt}.  To achieve this in
-multi-threaded programs, you must synchronize the memory with respect
-to other threads that also want to use @acronym{Libgcrypt}.  For this, it
-is sufficient to call @code{gcry_check_version} before creating the
-other threads using @acronym{Libgcrypt}@footnote{At least this is true for
-POSIX threads, as @code{pthread_create} is a function that
-synchronizes memory with respects to other threads.  There are many
-functions which have this property, a complete list can be found in
-POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in the
-definition of the term ``Memory Synchronization''.  For other thread
-packages other, more relaxed or more strict rules may apply.}.
+function in the library, except the @code{GCRYCTL_SET_THREAD_CBS}
+command, because it initializes the thread support subsystem in
+@acronym{Libgcrypt}.  To achieve this in multi-threaded programs, you
+must synchronize the memory with respect to other threads that also
+want to use @acronym{Libgcrypt}.  For this, it is sufficient to call
+@code{gcry_check_version} before creating the other threads using
+@acronym{Libgcrypt}@footnote{At least this is true for POSIX threads,
+as @code{pthread_create} is a function that synchronizes memory with
+respects to other threads.  There are many functions which have this
+property, a complete list can be found in POSIX, IEEE Std 1003.1-2003,
+Base Definitions, Issue 6, in the definition of the term ``Memory
+Synchronization''.  For other thread packages, more relaxed or
+more strict rules may apply.}.
 
 @item
 As with the function @code{gpg_strerror}, @code{gcry_strerror} is not
@@ -469,8 +480,8 @@ thread safe.  You have to use @code{gpg_strerror_r} instead.
 @deftypefun gcry_error_t gcry_control (enum gcry_ctl_cmds @var{cmd}, ...)
 
 This function can be used to influence the general behaviour of
-@acronym{Libgcrypt} in several ways.  Depending on @var{cmd}, more arguments can
-or have to be provided.
+@acronym{Libgcrypt} in several ways.  Depending on @var{cmd}, more
+arguments can or have to be provided.
 
 @end deftypefun
 
index e4c20b6..426c809 100644 (file)
@@ -1,3 +1,31 @@
+2004-03-10  Marcus Brinkmann  <marcus@g10code.de>
+
+       * Makefile.am (ltlib_libgcrypt_pthread, ltlib_libgcrypt_pth): Removed.
+       (lib_LTLIBRARIES): Remove those variables from here.
+       (libgcrypt_pthread_la_SOURCES, libgcrypt_pthread_la_LDFLAGS,
+       (libgcrypt_pthread_la_DEPENDENCIES, libgcrypt_pthread_la_LIBADD,
+       (libgcrypt_pth_la_SOURCES, libgcrypt_pth_la_LDFLAGS,
+       (libgcrypt_pth_la_DEPENDENCIES, libgcrypt_pth_la_LIBADD,
+       (noinst_LTLIBRARIES): Removed.
+       (libgcrypt_real_la_SOURCES): Merge with ...
+       (libgcrypt_la_SOURCES): ... likewise.
+       (libgcrypt_real_la_DEPENDENCIES): Merge with ...
+       (libgcrypt_la_DEPENDENCIES): ... this.
+       (libgcrypt_real_la_LIBADD): Merge with ...
+       (libgcrypt_la_LIBADD): ... this.
+       * libgcrypt-config.in (libs_pthread, libs_pth, cflags_pth) 
+       (cflags_pthread, thread_module, thread_modules): Removed.
+       (Options): Remove --thread option from help output.  If the option
+       is specified, output an error and exit.
+       For --cflags and --libs option, remove pth and pthread from output.
+       * gcrypt.h: Include <sys/types.h> and <sys/socket.h>.
+       (enum gcry_ctl_cmds): Add GCRYCTL_SET_THREAD_CBS.
+       (gcry_thread_cbs): New struct.
+       * global.c (gcry_control): Implement GCRYCTL_SET_THREAD_CBS.
+       (global_init): Don't call ath_init here.
+       * ath.h: Rewritten.
+       * ath.c: Rewritten.
+
 2004-03-06  Werner Koch  <wk@gnupg.org>
 
        * libgcrypt-config.in: s/--soname-number/--api-version/
index 9c198be..e6bb418 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
 #
 # This file is part of Libgcrypt.
 #
@@ -24,21 +24,7 @@ m4datadir = $(datadir)/aclocal
 m4data_DATA = libgcrypt.m4
 include_HEADERS = gcrypt.h gcrypt-module.h
 
-# Enable thread-library-specific versions of the library.
-if HAVE_PTHREAD
-  ltlib_libgcrypt_pthread = libgcrypt-pthread.la
-else
-  ltlib_libgcrypt_pthread =
-endif
-if HAVE_PTH
-  ltlib_libgcrypt_pth = libgcrypt-pth.la
-else
-  ltlib_libgcrypt_pth =
-endif
-
-noinst_LTLIBRARIES = libgcrypt-real.la
-lib_LTLIBRARIES = libgcrypt.la \
-       $(ltlib_libgcrypt_pthread) $(ltlib_libgcrypt_pth)
+lib_LTLIBRARIES = libgcrypt.la
 
 if HAVE_LD_VERSION_SCRIPT
   libgcrypt_version_script_cmd = -Wl,--version-script=$(srcdir)/libgcrypt.vers
@@ -46,49 +32,16 @@ else
   libgcrypt_version_script_cmd = 
 endif
 
-libgcrypt_real_la_SOURCES = \
-g10lib.h types.h cipher.h \
-misc.c  \
-global.c \
-sexp.c \
-stdmem.c stdmem.h \
-secmem.c secmem.h \
-mpi.h \
-missing-string.c \
-module.c
-
-libgcrypt_real_la_DEPENDENCIES = \
-       ../cipher/libcipher.la ../mpi/libmpi.la \
-       $(srcdir)/libgcrypt.vers
+libgcrypt_la_CFLAGS = @GPG_ERROR_CFLAGS@
+libgcrypt_la_SOURCES = g10lib.h types.h cipher.h \
+       misc.c global.c sexp.c \
+       stdmem.c stdmem.h secmem.c secmem.h \
+       mpi.h missing-string.c module.c \
+       ath.h ath.c
 
-libgcrypt_real_la_LIBADD = \
-       ../cipher/libcipher.la ../mpi/libmpi.la @GPG_ERROR_LIBS@
-
-AM_CFLAGS = @GPG_ERROR_CFLAGS@
-
-# The standard version.
-libgcrypt_la_SOURCES = ath.h ath.c
 libgcrypt_la_LDFLAGS = $(libgcrypt_version_script_cmd) -version-info \
-  @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@
-libgcrypt_la_DEPENDENCIES = libgcrypt-real.la \
-       @LTLIBOBJS@ $(srcdir)/libgcrypt.vers
-libgcrypt_la_LIBADD = libgcrypt-real.la @LTLIBOBJS@ \
-       @GPG_ERROR_LIBS@
-
-# The pthread version.
-libgcrypt_pthread_la_SOURCES = ath.h ath-pthread.c
-libgcrypt_pthread_la_LDFLAGS = $(libgcrypt_version_script_cmd) -version-info \
        @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@
-libgcrypt_pthread_la_DEPENDENCIES = libgcrypt-real.la \
-       @LTLIBOBJS@ $(srcdir)/libgcrypt.vers
-libgcrypt_pthread_la_LIBADD = libgcrypt-real.la @LTLIBOBJS@ \
-       -lpthread @GPG_ERROR_LIBS@
-
-# The pth version.
-libgcrypt_pth_la_SOURCES = ath.h ath-pth.c
-libgcrypt_pth_la_LDFLAGS = $(libgcrypt_version_script_cmd) -version-info \
-       @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@
-libgcrypt_pth_la_DEPENDENCIES = libgcrypt-real.la \
-       @LTLIBOBJS@ $(srcdir)/libgcrypt.vers
-libgcrypt_pth_la_LIBADD = libgcrypt-real.la @LTLIBOBJS@ \
-       @PTH_LIBS@ @GPG_ERROR_LIBS@
+libgcrypt_la_DEPENDENCIES = ../cipher/libcipher.la ../mpi/libmpi.la \
+       $(srcdir)/libgcrypt.vers
+libgcrypt_la_LIBADD = ../cipher/libcipher.la ../mpi/libmpi.la \
+       @LTLIBOBJS@ @GPG_ERROR_LIBS@
index 67cab31..6788bba 100644 (file)
--- a/src/ath.c
+++ b/src/ath.c
@@ -1,5 +1,5 @@
 /* ath.c - Thread-safeness library.
-   Copyright (C) 2002, 2003 g10 Code GmbH
+   Copyright (C) 2002, 2003, 2004 g10 Code GmbH
 
    This file is part of Libgcrypt.
  
 #endif
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <errno.h>
 
 #include "ath.h"
 
+\f
+/* The interface table.  */
+static struct ath_ops ops;
 
+/* True if we should use the external callbacks.  */
+static int ops_set;
+
+
+/* For the dummy interface.  */
 #define MUTEX_UNLOCKED ((ath_mutex_t) 0)
 #define MUTEX_LOCKED   ((ath_mutex_t) 1)
 #define MUTEX_DESTROYED        ((ath_mutex_t) 2)
 
 
-void
+\f
+/* The lock we take while checking for lazy lock initialization.  */
+static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER;
+
+int
 ath_init (void)
 {
-  /* Nothing to do.  */
+  int err = 0;
+
+  if (ops_set)
+    {
+      if (ops.init)
+       err = (*ops.init) ();
+      if (err)
+       return err;
+      err = (*ops.mutex_init) (&check_init_lock);
+    }
+  return err;
+}
+
+
+/* Initialize the locking library.  Returns 0 if the operation was
+   successful, EINVAL if the operation table was invalid and EBUSY if
+   we already were initialized.  */
+gpg_err_code_t
+ath_install (struct ath_ops *ath_ops, int check_only)
+{
+  if (check_only)
+    {
+      enum ath_thread_option option = ATH_THREAD_OPTION_DEFAULT;
+      
+      /* Check if the requested thread option is compatible to the
+        thread option we are already committed to.  */
+      if (ath_ops)
+       option = ath_ops->option;
+
+      if (!ops_set && option)
+       return GPG_ERR_NOT_SUPPORTED;
+
+      if (ops.option == ATH_THREAD_OPTION_USER
+         || option == ATH_THREAD_OPTION_USER
+         || ops.option != option)
+       return GPG_ERR_NOT_SUPPORTED;
+
+      return 0;
+    }
+    
+  if (ath_ops)
+    {
+      /* It is convenient to not require DESTROY.  */
+      if (!ath_ops->mutex_init || !ath_ops->mutex_lock
+         || !ath_ops->mutex_unlock)
+       return GPG_ERR_INV_ARG;
+
+      ops = *ath_ops;
+      ops_set = 1;
+    }
+  else
+    ops_set = 0;
+
+  return 0;
+}
+
+
+static int
+mutex_init (ath_mutex_t *lock, int just_check)
+{
+  int err = 0;
+
+  if (just_check)
+    (*ops.mutex_lock) (&check_init_lock);
+  if (*lock == ATH_MUTEX_INITIALIZER || !just_check)
+    err = (*ops.mutex_init) (lock);
+  if (just_check)
+    (*ops.mutex_unlock) (&check_init_lock);
+  return err;
 }
 
 
 int
 ath_mutex_init (ath_mutex_t *lock)
 {
+  if (ops_set)
+    return mutex_init (lock, 0);
+
 #ifndef NDEBUG
   *lock = MUTEX_UNLOCKED;
 #endif
@@ -60,6 +144,19 @@ ath_mutex_init (ath_mutex_t *lock)
 int
 ath_mutex_destroy (ath_mutex_t *lock)
 {
+  if (ops_set)
+    {
+      int err = mutex_init (lock, 1);
+
+      if (err)
+       return err;
+
+      if (ops.mutex_destroy)
+       return (*ops.mutex_destroy) (lock);
+      else
+       return 0;
+    }
+
 #ifndef NDEBUG
   assert (*lock == MUTEX_UNLOCKED);
 
@@ -72,6 +169,14 @@ ath_mutex_destroy (ath_mutex_t *lock)
 int
 ath_mutex_lock (ath_mutex_t *lock)
 {
+  if (ops_set)
+    {
+      int ret = mutex_init (lock, 1);
+      if (ret)
+       return ret;
+      return (*ops.mutex_lock) (lock);
+    }
+
 #ifndef NDEBUG
   assert (*lock == MUTEX_UNLOCKED);
 
@@ -84,6 +189,14 @@ ath_mutex_lock (ath_mutex_t *lock)
 int
 ath_mutex_unlock (ath_mutex_t *lock)
 {
+  if (ops_set)
+    {
+      int ret = mutex_init (lock, 1);
+      if (ret)
+       return ret;
+      return (*ops.mutex_unlock) (lock);
+    }
+
 #ifndef NDEBUG
   assert (*lock == MUTEX_LOCKED);
 
@@ -96,14 +209,20 @@ ath_mutex_unlock (ath_mutex_t *lock)
 ssize_t
 ath_read (int fd, void *buf, size_t nbytes)
 {
-  return read (fd, buf, nbytes);
+  if (ops_set && ops.read)
+    return (*ops.read) (fd, buf, nbytes);
+  else
+    return read (fd, buf, nbytes);
 }
 
 
 ssize_t
 ath_write (int fd, const void *buf, size_t nbytes)
 {
-  return write (fd, buf, nbytes);
+  if (ops_set && ops.write)
+    return (*ops.write) (fd, buf, nbytes);
+  else
+    return write (fd, buf, nbytes);
 }
 
 
@@ -111,40 +230,58 @@ ssize_t
 ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
            struct timeval *timeout)
 {
-  return select (nfd, rset, wset, eset, timeout);
+  if (ops_set && ops.select)
+    return (*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)
 {
-  return waitpid (pid, status, options);
+  if (ops_set && ops.waitpid)
+    return (*ops.waitpid) (pid, status, options);
+  else
+    return waitpid (pid, status, options);
 }
 
 
 int
 ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
 {
-  return accept (s, addr, length_ptr);
+  if (ops_set && ops.accept)
+    return (*ops.accept) (s, addr, length_ptr);
+  else
+    return accept (s, addr, length_ptr);
 }
 
 
 int
 ath_connect (int s, struct sockaddr *addr, socklen_t length)
 {
-  return connect (s, addr, length);
+  if (ops_set && ops.connect)
+    return (*ops.connect) (s, addr, length);
+  else
+    return connect (s, addr, length);
 }
 
 
 int
 ath_sendmsg (int s, const struct msghdr *msg, int flags)
 {
-  return sendmsg (s, msg, flags);
+  if (ops_set && ops.sendmsg)
+    return (*ops.sendmsg) (s, msg, flags);
+  else
+    return sendmsg (s, msg, flags);
 }
 
 
 int
 ath_recvmsg (int s, struct msghdr *msg, int flags)
 {
-  return recvmsg (s, msg, flags);
+  if (ops_set && ops.recvmsg)
+    return (*ops.recvmsg) (s, msg, flags);
+  else
+    return recvmsg (s, msg, flags);
 }
index 752441c..d492c2a 100644 (file)
--- a/src/ath.h
+++ b/src/ath.h
@@ -1,5 +1,5 @@
 /* ath.h - Thread-safeness library.
-   Copyright (C) 2002, 2003 g10 Code GmbH
+   Copyright (C) 2002, 2003, 2004 g10 Code GmbH
 
    This file is part of Libgcrypt.
  
@@ -30,6 +30,7 @@ typedef int pid_t;
 #include <sys/types.h>
 #include <sys/socket.h>
 #endif
+#include <gpg-error.h>
 
 #include <config.h>
 
@@ -42,6 +43,8 @@ typedef int pid_t;
 #define _ATH_PREFIX1(x,y) x ## y
 #define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y)
 #define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x)
+#define ath_install _ATH_PREFIX(ath_install)
+#define ath_init _ATH_PREFIX(ath_init)
 #define ath_mutex_init _ATH_PREFIX(ath_mutex_init)
 #define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy)
 #define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock)
@@ -57,15 +60,47 @@ typedef int pid_t;
 #endif
 
 \f
+enum ath_thread_option
+  {
+    ATH_THREAD_OPTION_DEFAULT = 0,
+    ATH_THREAD_OPTION_USER = 1,
+    ATH_THREAD_OPTION_PTH = 2,
+    ATH_THREAD_OPTION_PTHREAD = 3
+  };
+
+struct ath_ops
+{
+  enum ath_thread_option option;
+  int (*init) (void);
+  int (*mutex_init) (void **priv);
+  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);
+  int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr);
+  int (*connect) (int s, struct sockaddr *addr, socklen_t length);
+  int (*sendmsg) (int s, const struct msghdr *msg, int flags);
+  int (*recvmsg) (int s, struct msghdr *msg, int flags);
+};
+
+gpg_err_code_t ath_install (struct ath_ops *ath_ops, int check_only);
+int ath_init (void);
+
+
+/* Functions for mutual exclusion.  */
 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);
@@ -75,41 +110,7 @@ ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
 ssize_t ath_waitpid (pid_t pid, int *status, int options);
 int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
 int ath_connect (int s, struct sockaddr *addr, socklen_t length);
-#ifndef _WIN32
 int ath_sendmsg (int s, const struct msghdr *msg, int flags);
 int ath_recvmsg (int s, struct msghdr *msg, int flags);
-#endif
-
-#define _ATH_COMPAT
-#ifdef _ATH_COMPAT
-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);
-  int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr);
-  int (*connect) (int s, struct sockaddr *addr, socklen_t length);
-#ifndef WIN32
-  int (*sendmsg) (int s, const struct msghdr *msg, int flags);
-  int (*recvmsg) (int s, struct msghdr *msg, int flags);
-#endif
-};
-
-/* Initialize the any-thread package.  */
-#define ath_init _ATH_PREFIX(ath_init)
-void ath_init (void);
-
-/* Used by ath_pkg_init.  */
-#define ath_pthread_available _ATH_PREFIX(ath_pthread_available)
-struct ath_ops *ath_pthread_available (void);
-#define ath_pth_available _ATH_PREFIX(ath_pth_available)
-struct ath_ops *ath_pth_available (void);
-#endif
 
 #endif /* ATH_H */
index 62b8261..babc248 100644 (file)
@@ -1,5 +1,5 @@
 /* gcrypt.h -  GNU cryptographic library interface
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
  *               2004  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
@@ -27,6 +27,9 @@
 
 #include <gpg-error.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+
 /* This is required for error code compatibility. */
 #define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
 
@@ -43,7 +46,7 @@ extern "C" {
    autoconf (using the AM_PATH_GCRYPT macro) check that this header
    matches the installed library.  Note: Do not edit the next line as
    configure may fix the string here.  */
-#define GCRYPT_VERSION "1.1.93"
+#define GCRYPT_VERSION "1.1.94-cvs"
 
 /* Internal: We can't use the convenience macros for the multi
    precision integer functions when building this library. */
@@ -147,6 +150,119 @@ gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err);
 /* Return an error value with the system error ERR.  */
 gcry_err_code_t gcry_error_from_errno (int err);
 
+\f
+enum gcry_thread_option
+  {
+    GCRY_THREAD_OPTION_DEFAULT = 0,
+    GCRY_THREAD_OPTION_USER = 1,
+    GCRY_THREAD_OPTION_PTH = 2,
+    GCRY_THREAD_OPTION_PTHREAD = 3
+  };
+
+/* Wrapper for struct ath_ops.  */
+struct gcry_thread_cbs
+{
+  enum gcry_thread_option option;
+  int (*init) (void);
+  int (*mutex_init) (void **priv);
+  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);
+  int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr);
+  int (*connect) (int s, struct sockaddr *addr, socklen_t length);
+  int (*sendmsg) (int s, const struct msghdr *msg, int flags);
+  int (*recvmsg) (int s, struct msghdr *msg, int flags);
+};
+
+#define GCRY_THREAD_OPTION_PTH_IMPL                                          \
+static int gcry_pth_init (void)                                                      \
+{ return (pth_init () == FALSE) ? errno : 0; }                               \
+static int gcry_pth_mutex_init (void **priv)                                 \
+{                                                                            \
+  int err = 0;                                                               \
+  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;                                                         \
+    }                                                                        \
+  return err;                                                                \
+}                                                                            \
+static int gcry_pth_mutex_destroy (void **lock)                                      \
+  { /* GNU Pth has no destructor function.  */ free (*lock); return 0; }      \
+static int gcry_pth_mutex_lock (void **lock)                                 \
+  { return ((pth_mutex_acquire (*lock, 0, NULL)) == FALSE)                   \
+      ? errno : 0; }                                                         \
+static int gcry_pth_mutex_unlock (void **lock)                               \
+  { return ((pth_mutex_release (*lock)) == FALSE)                            \
+      ? errno : 0; }                                                         \
+static ssize_t gcry_pth_read (int fd, void *buf, size_t nbytes)                      \
+  { return pth_read (fd, buf, nbytes); }                                     \
+static ssize_t gcry_pth_write (int fd, const void *buf, size_t nbytes)       \
+  { return pth_write (fd, buf, nbytes); }                                    \
+static ssize_t gcry_pth_select (int nfd, fd_set *rset, fd_set *wset,         \
+                               fd_set *eset, struct timeval *timeout)        \
+  { return pth_select (nfd, rset, wset, eset, timeout); }                    \
+static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options)        \
+  { return pth_waitpid (pid, status, options); }                             \
+static int gcry_pth_accept (int s, struct sockaddr *addr,                    \
+                           socklen_t *length_ptr)                            \
+  { return pth_accept (s, addr, length_ptr); }                               \
+static int gcry_pth_connect (int s, struct sockaddr *addr, socklen_t length)  \
+  { return pth_connect (s, addr, length); }                                  \
+                                                                             \
+/* FIXME: GNU Pth is missing pth_sendmsg and pth_recvmsg.  */                \
+static struct gcry_thread_cbs gcry_threads_pth = { GCRY_THREAD_OPTION_PTH,    \
+  gcry_pth_init, gcry_pth_mutex_init, gcry_pth_mutex_destroy,                \
+  gcry_pth_mutex_lock, gcry_pth_mutex_unlock, gcry_pth_read, gcry_pth_write,  \
+  gcry_pth_select, gcry_pth_waitpid, gcry_pth_accept, gcry_pth_connect }
+
+#define GCRY_THREAD_OPTION_PTHREAD_IMPL                                              \
+static int gcry_pthread_mutex_init (void **priv)                             \
+{                                                                            \
+  int err = 0;                                                               \
+  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;                                                         \
+    }                                                                        \
+  return err;                                                                \
+}                                                                            \
+static int gcry_pthread_mutex_destroy (void **lock)                          \
+  { int err = pthread_mutex_destroy (*lock);  free (*lock); return err; }     \
+static int gcry_pthread_mutex_lock (void **lock)                             \
+  { return pthread_mutex_lock (*lock); }                                     \
+static int gcry_pthread_mutex_unlock (void **lock)                           \
+  { return pthread_mutex_unlock (*lock); }                                   \
+                                                                             \
+static struct gcry_thread_cbs gcry_threads_pthread =                         \
+{ GCRY_THREAD_OPTION_PTHREAD, NULL,                                          \
+  gcry_pthread_mutex_init, gcry_pthread_mutex_destroy,                       \
+  gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock }
+
+\f
 /* The data object used to hold a multi precision integer.  */
 struct gcry_mpi;
 typedef struct gcry_mpi *gcry_mpi_t;
@@ -208,7 +324,8 @@ enum gcry_ctl_cmds
     GCRYCTL_SET_CTR = 43,
     GCRYCTL_ENABLE_QUICK_RANDOM = 44,
     GCRYCTL_SET_RANDOM_SEED_FILE = 45,
-    GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46
+    GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
+    GCRYCTL_SET_THREAD_CBS = 47
   };
 
 /* Perform various operations defined by CMD. */
index 56d8114..162e845 100644 (file)
@@ -63,8 +63,8 @@ global_init (void)
   if (any_init_done)
     return;
   any_init_done = 1;
-  ath_init ();
 
+  err = ath_init ();
   if (! err)
     _gcry_cipher_init ();
   if (! err)
@@ -274,6 +274,10 @@ gcry_control (enum gcry_ctl_cmds cmd, ...)
          }
         break;
 
+    case GCRYCTL_SET_THREAD_CBS:
+      err = ath_install (va_arg (arg_ptr, void *), any_init_done);
+      break;
+
     default:
       err = GPG_ERR_INV_OP;
     }
index 5bdbd08..3309b69 100644 (file)
 # General.
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
-thread_module=""
 version="@VERSION@"
 gpg_error_libs="@GPG_ERROR_LIBS@"
 gpg_error_cflags="@GPG_ERROR_CFLAGS@"
 
-# LIBS values.
+# libgcrypt values.
 libs="@LIBGCRYPT_CONFIG_LIBS@"
-libs_pthread="@LIBGCRYPT_CONFIG_LIBS_PTHREAD@"
-libs_pth="@LIBGCRYPT_CONFIG_LIBS_PTH@"
-
-# CFLAGS values.
 cflags="@LIBGCRYPT_CONFIG_CFLAGS@"
-cflags_pthread="@LIBGCRYPT_CONFIG_CFLAGS_PTHREAD@"
-cflags_pth="@LIBGCRYPT_CONFIG_CFLAGS_PTH@"
 
 # API info
 api_version="@LIBGCRYPT_CONFIG_API_VERSION@"
@@ -34,7 +27,6 @@ api_version="@LIBGCRYPT_CONFIG_API_VERSION@"
 symmetric_ciphers="@LIBGCRYPT_CIPHERS@"
 asymmetric_ciphers="@LIBGCRYPT_PUBKEY_CIPHERS@"
 digests="@LIBGCRYPT_DIGESTS@"
-thread_modules="@LIBGCRYPT_THREAD_MODULES@"
 
 # State variables.
 echo_libs=no
@@ -51,7 +43,6 @@ usage()
     cat <<EOF
 Usage: $0 [OPTIONS]
 Options:
-       [--thread={${thread_modules}}]
        [--prefix]
        [--exec-prefix]
        [--version]
@@ -81,14 +72,8 @@ while test $# -gt 0; do
 
     case $1 in
        --thread=*)
-           for thread_mod in $thread_modules; do
-               if test "$thread_mod" = "$optarg"; then
-                   thread_module="$optarg";
-               fi
-           done
-           if test "x$thread_module" = "x"; then
-               usage 1 1>&2
-           fi
+           echo "$0: --thread option obsolete: use the thread callback interface" 1>&2
+           exit 1
            ;;
         --prefix=*)
             # For compatibility reasons with old M4 macros, we ignore
@@ -145,17 +130,8 @@ if test "$echo_cflags" = "yes"; then
            fi
        done
     fi
-
     # Set up `cflags_final'.
-    case "$thread_module" in
-       pthread)
-           cflags_final=$cflags_pthread
-           ;;
-       pth)
-           cflags_final=$cflags_pth
-           ;;
-    esac
-    cflags_final="$cflags_final @GPG_ERROR_CFLAGS@"
+    cflags_final="@GPG_ERROR_CFLAGS@"
 
     echo "$includes $cflags_final"
 fi
@@ -175,15 +151,7 @@ if test "$echo_libs" = "yes"; then
     fi
 
     # Set up `libs_final'.
-    case "$thread_module" in
-       pthread)
-           libs_final=$libs_pthread
-           ;;
-       pth)
-           libs_final=$libs_pth
-           ;;
-    esac
-    libs_final="$libs_final @GPG_ERROR_LIBS@"
+    libs_final="@GPG_ERROR_LIBS@"
 
     echo "$libdirs $libs_final"
 fi