Skip to content

Commit

Permalink
Retry for mingw statically initialized rwlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Apr 15, 2024
1 parent e12c8f5 commit 4116a9a
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions crypto/thread_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

// Ensure we can't call OPENSSL_malloc circularly.
#define _BORINGSSL_PROHIBIT_OPENSSL_MALLOC
#include <errno.h>

#include "internal.h"

#if defined(OPENSSL_PTHREADS)
Expand Down Expand Up @@ -64,14 +66,42 @@ void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
pthread_rwlock_destroy((pthread_rwlock_t *) lock);
}

// Some MinGW pthreads implementations might fail on first use of
// locks initialized using PTHREAD_RWLOCK_INITIALIZER.
// See: https://sourceforge.net/p/mingw-w64/bugs/883/
typedef int (*pthread_rwlock_func_ptr)(pthread_rwlock_t *);
static int rwlock_EINVAL_fallback_retry(const pthread_rwlock_func_ptr func_ptr, pthread_rwlock_t* lock) {
int result = EINVAL;
#ifdef __MINGW32__
const int MAX_ATTEMPTS = 10;
int attempt_num = 0;
do {
sched_yield();
attempt_num += 1;
result = func_ptr(lock);
} while(result == EINVAL && attempt_num < MAX_ATTEMPTS);
#endif
return result;
}

void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
if (pthread_rwlock_rdlock(&lock->lock) != 0) {
const int result = pthread_rwlock_rdlock(&lock->lock);
if (result != 0) {
if (result == EINVAL &&
0 == rwlock_EINVAL_fallback_retry(pthread_rwlock_rdlock, &lock->lock)) {
return;
}
abort();
}
}

void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
if (pthread_rwlock_wrlock(&lock->lock) != 0) {
const int result = pthread_rwlock_wrlock(&lock->lock);
if (result != 0) {
if (result == EINVAL &&
0 == rwlock_EINVAL_fallback_retry(pthread_rwlock_wrlock, &lock->lock)) {
return;
}
abort();
}
}
Expand Down

0 comments on commit 4116a9a

Please sign in to comment.