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

openSUSE Build Service is sponsored by