diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c index 71a489b271..a075aec4a7 100644 --- a/crypto/threads_pthread.c +++ b/crypto/threads_pthread.c @@ -464,9 +464,6 @@ void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) pthread_mutex_lock(&lock->prior_lock); while (lock->next_to_retire != curr_id) pthread_cond_wait(&lock->prior_signal, &lock->prior_lock); - lock->next_to_retire++; - pthread_cond_broadcast(&lock->prior_signal); - pthread_mutex_unlock(&lock->prior_lock); /* * wait for the reader count to reach zero @@ -479,6 +476,10 @@ void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) count = ATOMIC_LOAD_N(uint64_t, &qp->users, __ATOMIC_ACQUIRE); } while (count != (uint64_t)0); + lock->next_to_retire++; + pthread_cond_broadcast(&lock->prior_signal); + pthread_mutex_unlock(&lock->prior_lock); + retire_qp(lock, qp); /* handle any callbacks that we have */ diff --git a/crypto/threads_win.c b/crypto/threads_win.c index a20366ed6e..5907ddd379 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -383,15 +383,15 @@ void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) while (lock->next_to_retire != curr_id) ossl_crypto_condvar_wait(lock->prior_signal, lock->prior_lock); - lock->next_to_retire++; - ossl_crypto_condvar_broadcast(lock->prior_signal); - ossl_crypto_mutex_unlock(lock->prior_lock); - /* wait for the reader count to reach zero */ do { CRYPTO_atomic_load(&qp->users, &count, lock->rw_lock); } while (count != (uint64_t)0); + lock->next_to_retire++; + ossl_crypto_condvar_broadcast(lock->prior_signal); + ossl_crypto_mutex_unlock(lock->prior_lock); + retire_qp(lock, qp); /* handle any callbacks that we have */ diff --git a/test/threadstest.c b/test/threadstest.c index 71cdb37296..aba95b4032 100644 --- a/test/threadstest.c +++ b/test/threadstest.c @@ -434,7 +434,7 @@ static int _torture_rcu(void) writer2_done = 0; rcu_torture_result = 1; - rcu_lock = ossl_rcu_lock_new(1, NULL); + rcu_lock = ossl_rcu_lock_new(contention == 2 ? 4 : 1, NULL); if (rcu_lock == NULL) goto out; @@ -491,6 +491,12 @@ static int torture_rcu_high(void) contention = 1; return _torture_rcu(); } + +static int torture_rcu_high2(void) +{ + contention = 2; + return _torture_rcu(); +} #endif static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT; @@ -1329,6 +1335,7 @@ int setup_tests(void) ADD_TEST(torture_rw_high); ADD_TEST(torture_rcu_low); ADD_TEST(torture_rcu_high); + ADD_TEST(torture_rcu_high2); #endif ADD_TEST(test_once); ADD_TEST(test_thread_local);