diff options
Diffstat (limited to 'libgcrypt-1.4.6/src/ath.c')
-rw-r--r-- | libgcrypt-1.4.6/src/ath.c | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/libgcrypt-1.4.6/src/ath.c b/libgcrypt-1.4.6/src/ath.c new file mode 100644 index 0000000..0c274cd --- /dev/null +++ b/libgcrypt-1.4.6/src/ath.c @@ -0,0 +1,345 @@ +/* ath.c - Thread-safeness library. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt 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 Lesser General Public + License along with Libgcrypt; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <assert.h> /* Right: We need to use assert and not gcry_assert. */ +#include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#else +# include <sys/time.h> +#endif +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/wait.h> +#endif +#include <errno.h> + +#include "ath.h" + + + +/* 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) + + +/* Return the thread type from the option field. */ +#define GET_OPTION(a) ((a) & 0xff) +/* Return the version number from the option field. */ +#define GET_VERSION(a) (((a) >> 8)& 0xff) + + + +/* The lock we take while checking for lazy lock initialization. */ +static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER; + +int +ath_init (void) +{ + 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) + { + unsigned int option = 0; + + /* 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 && GET_OPTION (option)) + return GPG_ERR_NOT_SUPPORTED; + + if (GET_OPTION (ops.option) == ATH_THREAD_OPTION_USER + || GET_OPTION (option) == ATH_THREAD_OPTION_USER + || GET_OPTION (ops.option) != GET_OPTION (option) + || GET_VERSION (ops.option) != GET_VERSION (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 + return 0; +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ + if (ops_set) + { + if (!ops.mutex_destroy) + return 0; + + (*ops.mutex_lock) (&check_init_lock); + if (*lock == ATH_MUTEX_INITIALIZER) + { + (*ops.mutex_unlock) (&check_init_lock); + return 0; + } + (*ops.mutex_unlock) (&check_init_lock); + return (*ops.mutex_destroy) (lock); + } + +#ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); + + *lock = MUTEX_DESTROYED; +#endif + return 0; +} + + +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); + + *lock = MUTEX_LOCKED; +#endif + return 0; +} + + +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); + + *lock = MUTEX_UNLOCKED; +#endif + return 0; +} + + +ssize_t +ath_read (int fd, void *buf, size_t 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) +{ + if (ops_set && ops.write) + return (*ops.write) (fd, buf, nbytes); + else + return write (fd, buf, nbytes); +} + + +ssize_t +#ifdef _WIN32 +ath_select (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout) +#else +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +#endif +{ + if (ops_set && ops.select) + return (*ops.select) (nfd, rset, wset, eset, timeout); + else +#ifdef _WIN32 + return -1; +#else + return select (nfd, rset, wset, eset, timeout); +#endif +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ + if (ops_set && ops.waitpid) + return (*ops.waitpid) (pid, status, options); + else +#ifdef _WIN32 + return -1; +#else + return waitpid (pid, status, options); +#endif +} + + +int +#ifdef _WIN32 +ath_accept (int s, void *addr, int *length_ptr) +#else +ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) +#endif +{ + if (ops_set && ops.accept) + return (*ops.accept) (s, addr, length_ptr); + else +#ifdef _WIN32 + return -1; +#else + return accept (s, addr, length_ptr); +#endif +} + + +int +#ifdef _WIN32 +ath_connect (int s, void *addr, int length) +#else +ath_connect (int s, struct sockaddr *addr, socklen_t length) +#endif +{ + if (ops_set && ops.connect) + return (*ops.connect) (s, addr, length); + else +#ifdef _WIN32 + return -1; +#else + return connect (s, addr, length); +#endif +} + + +int +#ifdef _WIN32 +ath_sendmsg (int s, const void *msg, int flags) +#else +ath_sendmsg (int s, const struct msghdr *msg, int flags) +#endif +{ + if (ops_set && ops.sendmsg) + return (*ops.sendmsg) (s, msg, flags); + else +#ifdef _WIN32 + return -1; +#else + return sendmsg (s, msg, flags); +#endif +} + + +int +#ifdef _WIN32 +ath_recvmsg (int s, void *msg, int flags) +#else +ath_recvmsg (int s, struct msghdr *msg, int flags) +#endif +{ + if (ops_set && ops.recvmsg) + return (*ops.recvmsg) (s, msg, flags); + else +#ifdef _WIN32 + return -1; +#else + return recvmsg (s, msg, flags); +#endif +} + |