Make CRYPTO_library_init use a CRYPTO_once_t.

Initialization by multiple consumers on ARM is still problematic due to
CRYPTO_set_NEON_{capable,functional}, until we reimplement that in-library, but
if that is called before the first CRYPTO_library_init, this change makes it
safe.

BUG=556462

Change-Id: I5845d09cca909bace8293ba7adf09a3bd0d4f943
Reviewed-on: https://boringssl-review.googlesource.com/6519
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/crypto.c b/crypto/crypto.c
index 9d2e616..ace1c82 100644
--- a/crypto/crypto.c
+++ b/crypto/crypto.c
@@ -88,22 +88,22 @@
 #endif
 
 
-#if defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER)
 #define OPENSSL_CDECL __cdecl
 #else
 #define OPENSSL_CDECL
 #endif
 
-#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
-#if !defined(OPENSSL_WINDOWS)
-static void do_library_init(void) __attribute__ ((constructor));
-#else
+#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
+static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
+#elif defined(OPENSSL_WINDOWS)
 #pragma section(".CRT$XCU", read)
 static void __cdecl do_library_init(void);
 __declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
     do_library_init;
+#else
+static void do_library_init(void) __attribute__ ((constructor));
 #endif
-#endif  /* !BORINGSSL_NO_STATIC_INITIALIZER */
 
 /* do_library_init is the actual initialization function. If
  * BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
@@ -119,9 +119,9 @@
 void CRYPTO_library_init(void) {
   /* TODO(davidben): It would be tidier if this build knob could be replaced
    * with an internal lazy-init mechanism that would handle things correctly
-   * in-library. */
+   * in-library. https://crbug.com/542879 */
 #if defined(BORINGSSL_NO_STATIC_INITIALIZER)
-  do_library_init();
+  CRYPTO_once(&once, do_library_init);
 #endif
 }