From 2b2b26788e7e46abb8fb340d49a088184fbc0b9b Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 21 Feb 2023 10:18:58 +0000 Subject: threading: Add ossl_crypto_condvar_wait_timeout Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/20348) --- crypto/thread/arch/thread_posix.c | 25 +++++++++++++++++++++++++ crypto/thread/arch/thread_win.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) (limited to 'crypto/thread') diff --git a/crypto/thread/arch/thread_posix.c b/crypto/thread/arch/thread_posix.c index b157435fd6..ae79fe579c 100644 --- a/crypto/thread/arch/thread_posix.c +++ b/crypto/thread/arch/thread_posix.c @@ -171,6 +171,31 @@ void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex) pthread_cond_wait(cv_p, mutex_p); } +void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex, + OSSL_TIME deadline) +{ + pthread_cond_t *cv_p = (pthread_cond_t *)cv; + pthread_mutex_t *mutex_p = (pthread_mutex_t *)mutex; + + if (ossl_time_is_infinite(deadline)) { + /* + * No deadline. Some pthread implementations allow + * pthread_cond_timedwait to work the same as pthread_cond_wait when + * abstime is NULL, but it is unclear whether this is POSIXly correct. + */ + pthread_cond_wait(cv_p, mutex_p); + } else { + struct timespec deadline_ts; + + deadline_ts.tv_sec + = ossl_time2seconds(deadline); + deadline_ts.tv_nsec + = (ossl_time2ticks(deadline) % OSSL_TIME_SECOND) / OSSL_TIME_NS; + + pthread_cond_timedwait(cv_p, mutex_p, &deadline_ts); + } +} + void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv) { pthread_cond_t *cv_p; diff --git a/crypto/thread/arch/thread_win.c b/crypto/thread/arch/thread_win.c index 5bef48458e..38a3e9a75b 100644 --- a/crypto/thread/arch/thread_win.c +++ b/crypto/thread/arch/thread_win.c @@ -162,6 +162,44 @@ void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex) SleepConditionVariableCS(cv_p, mutex_p, INFINITE); } +void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex, + OSSL_TIME deadline, int *timeout_expired) +{ + DWORD timeout; + CONDITION_VARIABLE *cv_p = (CONDITION_VARIABLE *)cv; + CRITICAL_SECTION *mutex_p = (CRITICAL_SECTION *)mutex; + + if (ossl_time_is_infinite(deadline)) { + timeout = INFINITE; + } else { + OSSL_TIME now = ossl_time_now(); + OSSL_TIME delta = ossl_time_subtract(deadline, now); + uint64_t ms; + + if (ossl_time_is_zero(delta)) { + if (timeout_expired != NULL) + *timeout_expired = 1; + + return; + } + + ms = ossl_time2ms(delta); + + /* + * Amount of time we want to wait is too long for the 32-bit argument to + * the Win32 API, so just wait as long as possible. + */ + if (ms > (uint64_t)(INFINITE - 1)) + timeout = INFINITE - 1; + else + timeout = (DWORD)ms; + } + + if (!SleepConditionVariableCS(cv_p, mutex_p, timeout) + && timeout_expired != NULL) + *timeout_expired = 1; +} + void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv) { CONDITION_VARIABLE *cv_p; -- cgit v1.2.1