From: Hugo Landau Date: Tue, 21 Feb 2023 10:18:58 +0000 (+0000) Subject: threading: Add ossl_crypto_condvar_wait_timeout X-Git-Tag: openssl-3.2.0-alpha1~1074 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b2b26788e7e46abb8fb340d49a088184fbc0b9b;p=thirdparty%2Fopenssl.git threading: Add ossl_crypto_condvar_wait_timeout Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/20348) --- diff --git a/crypto/thread/arch/thread_posix.c b/crypto/thread/arch/thread_posix.c index b157435fd67..ae79fe579c6 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 5bef48458e1..38a3e9a75bf 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; diff --git a/include/internal/thread_arch.h b/include/internal/thread_arch.h index bf000006061..c8607d50a4a 100644 --- a/include/internal/thread_arch.h +++ b/include/internal/thread_arch.h @@ -11,6 +11,7 @@ # define OSSL_INTERNAL_THREAD_ARCH_H # include # include +# include "internal/time.h" # if defined(_WIN32) # include @@ -44,6 +45,8 @@ void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex); CRYPTO_CONDVAR *ossl_crypto_condvar_new(void); void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex); +void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex, + OSSL_TIME deadline); void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv); void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv); diff --git a/include/internal/time.h b/include/internal/time.h index 604f9e06d9c..968ebbe6bdc 100644 --- a/include/internal/time.h +++ b/include/internal/time.h @@ -35,6 +35,9 @@ typedef struct { /* One microsecond. */ # define OSSL_TIME_US (OSSL_TIME_MS / 1000) +/* One nanosecond. */ +# define OSSL_TIME_NS (OSSL_TIME_US / 1000) + #define ossl_seconds2time(s) ossl_ticks2time((s) * OSSL_TIME_SECOND) #define ossl_time2seconds(t) (ossl_time2ticks(t) / OSSL_TIME_SECOND) #define ossl_ms2time(ms) ossl_ticks2time((ms) * OSSL_TIME_MS)