Optimize openssl initialization 16/36116/2
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 17 Feb 2015 13:42:34 +0000 (14:42 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 4 Mar 2015 08:32:07 +0000 (09:32 +0100)
[Issue#] N/A
[Feature/Bug] N/A
[Problem] Each time Manager or PKCS12 object is created initCryptoLib is called
and mutex is locked inside it.
[Cause] N/A
[Solution] Once openssl is initialized the initalization function pointer is
switched to empty one, thus mutex is not used any more.

[Verification] Run tests. Alternatively check in gdb that client calls
initOpenSSL() only once

Change-Id: I733e4ca6c88a6a51d69ebb0606f560a9b4828e4c

src/manager/common/crypto-init.cpp

index 5ae1849..47f99b7 100644 (file)
 #include "crypto-init.h"
 #include <mutex>
 #include <openssl/evp.h>
+#include <atomic>
 
 namespace CKM {
 
 namespace {
-bool isCryptoInitialized = false;
 std::mutex cryptoInitMutex;
-}
 
-void initCryptoLib() {
+void initOpenSSL();
+
+typedef void(*initFnPtr)();
+
+// has to be atomic as storing function pointer is not an atomic operation on armv7l
+std::atomic<initFnPtr> initFn (&initOpenSSL);
+
+void initEmpty() {}
+
+void initOpenSSL() {
+    // DCLP
     std::lock_guard<std::mutex> lock(cryptoInitMutex);
-    if(!isCryptoInitialized)
+    /*
+     * We don't care about memory ordering here. Current thread will order it correctly and for
+     * other threads only store matters. Also only one thread can be here at once because of lock.
+     */
+    if(initFn.load(std::memory_order_relaxed) != &initEmpty)
     {
-        isCryptoInitialized = true;
         OpenSSL_add_all_ciphers();
         OpenSSL_add_all_algorithms();
         OpenSSL_add_all_digests();
+
+        /*
+         * Synchronizes with load. Everything that happened before this store in this thread is
+         * visible to everything that happens after load in another thread. We switch to an empty
+         * function here.
+         */
+        initFn.store(&initEmpty, std::memory_order_release);
     }
 }
 
+} // namespace anonymous
+
+void initCryptoLib() {
+    /*
+     * Synchronizes with store. Everything that happened before store in another thread will be
+     * visible in this thread after load.
+     */
+    initFn.load(std::memory_order_acquire)();
+}
+
 } /* namespace CKM */