From: Matt Caswell Date: Tue, 22 Dec 2020 17:43:07 +0000 (+0000) Subject: Add some more CRYPTO_atomic functions X-Git-Tag: openssl-3.0.0-alpha10~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5e742de653954bfae88f0e5f6c8f0a7a5f6c437;p=thirdparty%2Fopenssl.git Add some more CRYPTO_atomic functions We add an implementation for CRYPTO_atomic_or() and CRYPTO_atomic_load() Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/13733) --- diff --git a/crypto/threads_none.c b/crypto/threads_none.c index c12d5610aae..55d4b5f0f86 100644 --- a/crypto/threads_none.c +++ b/crypto/threads_none.c @@ -133,6 +133,22 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ + *val |= op; + *ret = *val; + + return 1; +} + +int CRYPTO_atomic_load(uint64_t *val, uint64_t *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 afc29b79614..22ba7931612 100644 --- a/crypto/threads_pthread.c +++ b/crypto/threads_pthread.c @@ -185,7 +185,7 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } # endif - if (!CRYPTO_THREAD_write_lock(lock)) + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) return 0; *val += amount; @@ -197,6 +197,54 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) + if (__atomic_is_lock_free(sizeof(*val), val)) { + *ret = __atomic_or_fetch(val, op, __ATOMIC_ACQ_REL); + return 1; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (ret != NULL) { + *ret = atomic_or_64_nv(val, op); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val |= op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + +int CRYPTO_atomic_load(uint64_t *val, uint64_t *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; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (ret != NULL) { + *ret = atomic_or_64_nv(val, 0); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) + return 0; + *ret = *val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} # ifndef FIPS_MODULE # ifdef OPENSSL_SYS_UNIX diff --git a/crypto/threads_win.c b/crypto/threads_win.c index a008831a3e7..ef68fe2d24a 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -66,9 +66,9 @@ void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) return; } -# define ONCE_UNINITED 0 -# define ONCE_ININIT 1 -# define ONCE_DONE 2 +# define ONCE_UNINITED 0 +# define ONCE_ININIT 1 +# define ONCE_DONE 2 /* * We don't use InitOnceExecuteOnce because that isn't available in WinXP which @@ -159,6 +159,19 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ + *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op; + return 1; +} + +int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) +{ + *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0); + return 1; +} + int openssl_init_fork_handlers(void) { return 0; diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in index 0641db3a44d..0b9aeefe048 100644 --- a/include/openssl/crypto.h.in +++ b/include/openssl/crypto.h.in @@ -86,6 +86,9 @@ 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_or(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock); +int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock); /* No longer needed, so this is a no-op */ #define OPENSSL_malloc_init() while(0) continue diff --git a/util/libcrypto.num b/util/libcrypto.num index 93ca779831b..289a6672f93 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5284,3 +5284,5 @@ PEM_write_bio_PrivateKey_ex ? 3_0_0 EXIST::FUNCTION: PEM_write_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION:STDIO PEM_write_bio_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_get_group_name ? 3_0_0 EXIST::FUNCTION: +CRYPTO_atomic_or ? 3_0_0 EXIST::FUNCTION: +CRYPTO_atomic_load ? 3_0_0 EXIST::FUNCTION: