From 94683b7acb62a5d99b8b4d66283e6d6dd0007f7a Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 25 Sep 2017 12:04:42 +1000 Subject: [PATCH] Add a CRYPTO_atomic_read call which allows an int variable to be read in an atomic fashion. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/4414) --- crypto/threads_none.c | 6 ++++++ crypto/threads_pthread.c | 19 +++++++++++++++++++ crypto/threads_win.c | 6 ++++++ doc/man3/CRYPTO_THREAD_run_once.pod | 10 +++++++++- include/openssl/crypto.h | 1 + util/libcrypto.num | 1 + 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crypto/threads_none.c b/crypto/threads_none.c index ffad7576b1..7e9ec2d151 100644 --- a/crypto/threads_none.c +++ b/crypto/threads_none.c @@ -125,6 +125,12 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ + *ret = *val; + return 1; +} + int openssl_init_fork_handlers(void) { return 0; diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c index 9644c25aea..3f8ada2c37 100644 --- a/crypto/threads_pthread.c +++ b/crypto/threads_pthread.c @@ -169,6 +169,25 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) + if (__atomic_is_lock_free(sizeof(*val), val)) { + __atomic_load(val, ret, __ATOMIC_ACQUIRE); + return 1; + } +# endif + if (!CRYPTO_THREAD_write_lock(lock)) + return 0; + + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + # ifdef OPENSSL_SYS_UNIX static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT; diff --git a/crypto/threads_win.c b/crypto/threads_win.c index 512e19f5f3..6f9c7b1bd3 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -133,6 +133,12 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ + InterlockedCompareExchange(val, 0, 0); + return 1; +} + int openssl_init_fork_handlers(void) { return 0; diff --git a/doc/man3/CRYPTO_THREAD_run_once.pod b/doc/man3/CRYPTO_THREAD_run_once.pod index 9a4df1992c..bf4a2f2cef 100644 --- a/doc/man3/CRYPTO_THREAD_run_once.pod +++ b/doc/man3/CRYPTO_THREAD_run_once.pod @@ -4,7 +4,8 @@ CRYPTO_THREAD_run_once, CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock, -CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free, CRYPTO_atomic_add - OpenSSL thread support +CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free, CRYPTO_atomic_add, +CRYPTO_atomic_read - OpenSSL thread support =head1 SYNOPSIS @@ -20,6 +21,7 @@ CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free, CRYPTO_atomic_add - OpenSSL threa void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); + int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock); =head1 DESCRIPTION @@ -74,6 +76,12 @@ operations are supported on the specific platform. Because of this, if a variable is modified by CRYPTO_atomic_add() then CRYPTO_atomic_add() must be the only way that the variable is modified. +=item * + +CRYPTO_atomic_read() atomically reads B and returns the result of +the operation in B. B will be locked, unless atomic operations +are supported on the specific platform. + =back =head1 RETURN VALUES diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index 9fc0663233..a9f080d53c 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -74,6 +74,7 @@ int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock); void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); +int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock); /* * The following can be used to detect memory leaks in the library. If diff --git a/util/libcrypto.num b/util/libcrypto.num index 48e97ff135..68f89b6302 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4398,3 +4398,4 @@ EVP_PKEY_meth_set_check 4341 1_1_1 EXIST::FUNCTION: EVP_PKEY_meth_get_check 4342 1_1_1 EXIST::FUNCTION: EVP_PKEY_meth_remove 4343 1_1_1 EXIST::FUNCTION: OPENSSL_sk_reserve 4344 1_1_1 EXIST::FUNCTION: +CRYPTO_atomic_read 4345 1_1_1 EXIST::FUNCTION: -- 2.25.1