Changeset View
Changeset View
Standalone View
Standalone View
b/src/posix-lock.c
Context not available. | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#if USE_POSIX_THREADS | |||||
# include <pthread.h> | # include <pthread.h> | ||||
#endif | |||||
#include "gpg-error.h" | #include "gpg-error.h" | ||||
#include "lock.h" | #include "lock.h" | ||||
#include "posix-lock-obj.h" | //#include "posix-lock-obj.h" | ||||
#define gpgrt_lock_t pthread_mutex_t | |||||
#define GPGRT_LOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER | |||||
/* | /* | ||||
Context not available. | |||||
static void (*post_lock_func)(void); | static void (*post_lock_func)(void); | ||||
#if USE_POSIX_THREADS | |||||
# if USE_POSIX_THREADS_WEAK | |||||
/* On ELF systems it is easy to use pthreads using weak | |||||
references. Take care not to test the address of a weak | |||||
referenced function we actually use; some GCC versions have a | |||||
bug were &foo != NULL is always evaluated to true in PIC mode. */ | |||||
# pragma weak pthread_cancel | |||||
# pragma weak pthread_mutex_init | |||||
# pragma weak pthread_mutex_lock | |||||
# pragma weak pthread_mutex_trylock | |||||
# pragma weak pthread_mutex_unlock | |||||
# pragma weak pthread_mutex_destroy | |||||
# if ! PTHREAD_IN_USE_DETECTION_HARD | |||||
# define use_pthread_p() (!!pthread_cancel) | |||||
# endif | |||||
# else /*!USE_POSIX_THREADS_WEAK*/ | |||||
# if ! PTHREAD_IN_USE_DETECTION_HARD | |||||
# define use_pthread_p() (1) | |||||
# endif | |||||
# endif /*!USE_POSIX_THREADS_WEAK*/ | |||||
# if PTHREAD_IN_USE_DETECTION_HARD | |||||
/* The function to be executed by a dummy thread. */ | |||||
static void * | |||||
dummy_thread_func (void *arg) | |||||
{ | |||||
return arg; | |||||
} | |||||
static int | |||||
use_pthread_p (void) | |||||
{ | |||||
static int tested; | |||||
static int result; /* 1: linked with -lpthread, 0: only with libc */ | |||||
if (!tested) | |||||
{ | |||||
pthread_t thread; | |||||
if (pthread_create (&thread, NULL, dummy_thread_func, NULL)) | |||||
result = 0; /* Thread creation failed. */ | |||||
else | |||||
{ | |||||
/* Thread creation works. */ | |||||
void *retval; | |||||
if (pthread_join (thread, &retval) != 0) | |||||
{ | |||||
assert (!"pthread_join"); | |||||
abort (); | |||||
} | |||||
result = 1; | |||||
} | |||||
tested = 1; | |||||
} | |||||
return result; | |||||
} | |||||
#endif /*PTHREAD_IN_USE_DETECTION_HARD*/ | |||||
#endif /*USE_POSIX_THREADS*/ | |||||
/* Helper to set the clamp functions. This is called as a helper from | /* Helper to set the clamp functions. This is called as a helper from | ||||
* _gpgrt_set_syscall_clamp to keep the function pointers local. */ | * _gpgrt_set_syscall_clamp to keep the function pointers local. */ | ||||
void | void | ||||
Context not available. | |||||
post_lock_func = post; | post_lock_func = post; | ||||
} | } | ||||
static _gpgrt_lock_t * | |||||
get_lock_object (gpgrt_lock_t *lockhd) | |||||
{ | |||||
_gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; | |||||
if (lock->vers != LOCK_ABI_VERSION) | |||||
{ | |||||
assert (!"lock ABI version"); | |||||
abort (); | |||||
} | |||||
if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) | |||||
{ | |||||
assert (!"sizeof lock obj"); | |||||
abort (); | |||||
} | |||||
return lock; | |||||
} | |||||
gpg_err_code_t | gpg_err_code_t | ||||
_gpgrt_lock_init (gpgrt_lock_t *lockhd) | _gpgrt_lock_init (gpgrt_lock_t *lockhd) | ||||
{ | { | ||||
_gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; | int rc = pthread_mutex_init (lockhd, NULL); | ||||
int rc; | if (rc) | ||||
/* If VERS is zero we assume that no static initialization has been | |||||
done, so we setup our ABI version right here. The caller might | |||||
have called us to test whether lock support is at all available. */ | |||||
if (!lock->vers) | |||||
{ | |||||
if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) | |||||
{ | |||||
assert (!"sizeof lock obj"); | |||||
abort (); | |||||
} | |||||
lock->vers = LOCK_ABI_VERSION; | |||||
} | |||||
else /* Run the usual check. */ | |||||
lock = get_lock_object (lockhd); | |||||
#if USE_POSIX_THREADS | |||||
if (use_pthread_p()) | |||||
{ | |||||
rc = pthread_mutex_init (&lock->u.mtx, NULL); | |||||
if (rc) | |||||
rc = gpg_err_code_from_errno (rc); | rc = gpg_err_code_from_errno (rc); | ||||
} | return rc; | ||||
else | |||||
rc = 0; /* Threads are not used. */ | |||||
#else /* Unknown thread system. */ | |||||
rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; | |||||
#endif /* Unknown thread system. */ | |||||
return rc; | |||||
} | } | ||||
gpg_err_code_t | gpg_err_code_t | ||||
_gpgrt_lock_lock (gpgrt_lock_t *lockhd) | _gpgrt_lock_lock (gpgrt_lock_t *lockhd) | ||||
{ | { | ||||
_gpgrt_lock_t *lock = get_lock_object (lockhd); | int rc; | ||||
int rc; | if (pre_lock_func) | ||||
pre_lock_func (); | |||||
#if USE_POSIX_THREADS | rc = pthread_mutex_lock (lockhd); | ||||
if (use_pthread_p()) | if (rc) | ||||
{ | rc = gpg_err_code_from_errno (rc); | ||||
if (pre_lock_func) | if (post_lock_func) | ||||
pre_lock_func (); | post_lock_func (); | ||||
rc = pthread_mutex_lock (&lock->u.mtx); | |||||
if (rc) | |||||
rc = gpg_err_code_from_errno (rc); | |||||
if (post_lock_func) | |||||
post_lock_func (); | |||||
} | |||||
else | |||||
rc = 0; /* Threads are not used. */ | |||||
#else /* Unknown thread system. */ | |||||
rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; | |||||
#endif /* Unknown thread system. */ | |||||
return rc; | return rc; | ||||
} | } | ||||
Context not available. | |||||
gpg_err_code_t | gpg_err_code_t | ||||
_gpgrt_lock_trylock (gpgrt_lock_t *lockhd) | _gpgrt_lock_trylock (gpgrt_lock_t *lockhd) | ||||
{ | { | ||||
_gpgrt_lock_t *lock = get_lock_object (lockhd); | |||||
int rc; | int rc; | ||||
rc = pthread_mutex_trylock (lockhd); | |||||
#if USE_POSIX_THREADS | |||||
if (use_pthread_p()) | |||||
{ | |||||
rc = pthread_mutex_trylock (&lock->u.mtx); | |||||
if (rc) | if (rc) | ||||
rc = gpg_err_code_from_errno (rc); | rc = gpg_err_code_from_errno (rc); | ||||
} | |||||
else | |||||
rc = 0; /* Threads are not used. */ | |||||
#else /* Unknown thread system. */ | |||||
rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; | |||||
#endif /* Unknown thread system. */ | |||||
return rc; | return rc; | ||||
} | } | ||||
Context not available. | |||||
gpg_err_code_t | gpg_err_code_t | ||||
_gpgrt_lock_unlock (gpgrt_lock_t *lockhd) | _gpgrt_lock_unlock (gpgrt_lock_t *lockhd) | ||||
{ | { | ||||
_gpgrt_lock_t *lock = get_lock_object (lockhd); | |||||
int rc; | int rc; | ||||
#if USE_POSIX_THREADS | rc = pthread_mutex_unlock (lockhd); | ||||
if (use_pthread_p()) | |||||
{ | |||||
rc = pthread_mutex_unlock (&lock->u.mtx); | |||||
if (rc) | if (rc) | ||||
rc = gpg_err_code_from_errno (rc); | rc = gpg_err_code_from_errno (rc); | ||||
} | |||||
else | |||||
rc = 0; /* Threads are not used. */ | |||||
#else /* Unknown thread system. */ | |||||
rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; | |||||
#endif /* Unknown thread system. */ | |||||
return rc; | return rc; | ||||
} | } | ||||
Context not available. | |||||
gpg_err_code_t | gpg_err_code_t | ||||
_gpgrt_lock_destroy (gpgrt_lock_t *lockhd) | _gpgrt_lock_destroy (gpgrt_lock_t *lockhd) | ||||
{ | { | ||||
_gpgrt_lock_t *lock = get_lock_object (lockhd); | |||||
int rc; | int rc; | ||||
rc = pthread_mutex_destroy (lockhd); | |||||
#if USE_POSIX_THREADS | |||||
if (use_pthread_p()) | |||||
{ | |||||
rc = pthread_mutex_destroy (&lock->u.mtx); | |||||
if (rc) | if (rc) | ||||
rc = gpg_err_code_from_errno (rc); | rc = gpg_err_code_from_errno (rc); | ||||
else | else | ||||
{ | { | ||||
/* Re-init the mutex so that it can be re-used. */ | /* Re-init the mutex so that it can be re-used. */ | ||||
/* XXX UB ? */ | |||||
gpgrt_lock_t tmp = GPGRT_LOCK_INITIALIZER; | gpgrt_lock_t tmp = GPGRT_LOCK_INITIALIZER; | ||||
memcpy (lockhd, &tmp, sizeof tmp); | memcpy (lockhd, &tmp, sizeof tmp); | ||||
} | } | ||||
} | |||||
else | |||||
rc = 0; /* Threads are not used. */ | |||||
#else /* Unknown thread system. */ | |||||
rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; | |||||
#endif /* Unknown thread system. */ | |||||
return rc; | return rc; | ||||
} | } | ||||
Context not available. |