File 0666-crypto-register-optimized-add_lock_callback-function.patch of Package erlang
From 1714d614d87194ae2608e1b892b3566f175e2a00 Mon Sep 17 00:00:00 2001
From: Mikael Pettersson <mikael.pettersson@klarna.com>
Date: Wed, 11 Nov 2020 15:43:34 +0100
Subject: [PATCH 2/4] crypto: register optimized add_lock_callback function
when possible
Otherwise all PKEY reference count changes in openssl older than 1.1.0 will compete for a single global mutex.
---
lib/crypto/c_src/crypto.c | 1 +
lib/crypto/c_src/crypto_callback.c | 24 ++++++++++++++++++++++++
lib/crypto/c_src/crypto_callback.h | 2 ++
3 files changed, 27 insertions(+)
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index f740b19a94..b88413d873 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -250,6 +250,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
#ifdef OPENSSL_THREADS
if (nlocks > 0) {
+ CRYPTO_set_add_lock_callback(ccb->add_lock_function);
CRYPTO_set_locking_callback(ccb->locking_function);
CRYPTO_set_id_callback(ccb->id_function);
CRYPTO_set_dynlock_create_callback(ccb->dyn_create_function);
diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
index f9cbd525d0..0244952a65 100644
--- a/lib/crypto/c_src/crypto_callback.c
+++ b/lib/crypto/c_src/crypto_callback.c
@@ -133,6 +133,28 @@ static INLINE void locking(int mode, ErlNifRWLock* lock)
}
#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
+
+/* TODO: there should be an enif_atomic32_add_return() */
+
+typedef int (*add_lock_function_t)(int *var, int incr, int type, const char *file, int line);
+
+#if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
+static int add_lock_function(int *var, int incr, int type, const char *file, int line)
+{
+ return __atomic_add_fetch(var, incr, __ATOMIC_ACQ_REL);
+}
+
+static add_lock_function_t get_add_lock_function(void)
+{
+ return __atomic_always_lock_free(sizeof(int), NULL) ? add_lock_function : NULL;
+}
+#else
+static add_lock_function_t get_add_lock_function(void)
+{
+ return NULL;
+}
+#endif
+
static void locking_function(int mode, int n, const char *file, int line)
{
locking(mode, lock_vec[n]);
@@ -172,6 +194,7 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks)
#if OPENSSL_VERSION_NUMBER < 0x10100000
#ifdef OPENSSL_THREADS
+ NULL, /* add_lock_function, filled in below */
&locking_function,
&id_function,
&dyn_create_function,
@@ -184,6 +207,7 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks)
if (!is_initialized) {
#if OPENSSL_VERSION_NUMBER < 0x10100000
#ifdef OPENSSL_THREADS
+ the_struct.add_lock_function = get_add_lock_function();
if (nlocks > 0) {
int i;
diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h
index f59165886b..d7f14ac1cd 100644
--- a/lib/crypto/c_src/crypto_callback.h
+++ b/lib/crypto/c_src/crypto_callback.h
@@ -36,6 +36,8 @@ struct crypto_callbacks
/* openssl callbacks */
#if OPENSSL_VERSION_NUMBER < 0x10100000
#ifdef OPENSSL_THREADS
+ int (*add_lock_function)(int *num, int amount, int type,
+ const char *file, int line);
void (*locking_function)(int mode, int n, const char *file, int line);
unsigned long (*id_function)(void);
struct CRYPTO_dynlock_value* (*dyn_create_function)(const char *file,
--
2.26.2