diff options
Diffstat (limited to 'crypto/init.c')
-rw-r--r-- | crypto/init.c | 119 |
1 files changed, 6 insertions, 113 deletions
diff --git a/crypto/init.c b/crypto/init.c index 7512a1e9d6..fd24e4f50b 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -31,58 +31,6 @@ static int stopped = 0; -typedef struct thread_event_handler_st THREAD_EVENT_HANDLER; -struct thread_event_handler_st { - OPENSSL_CTX *ctx; - ossl_thread_stop_handler_fn handfn; - THREAD_EVENT_HANDLER *next; -}; - -/* - * Since per-thread-specific-data destructors are not universally - * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key - * is assumed to have destructor associated. And then an effort is made - * to call this single destructor on non-pthread platform[s]. - * - * Initial value is "impossible". It is used as guard value to shortcut - * destructor for threads terminating before libcrypto is initialized or - * after it's de-initialized. Access to the key doesn't have to be - * serialized for the said threads, because they didn't use libcrypto - * and it doesn't matter if they pick "impossible" or derefernce real - * key value and pull NULL past initialization in the first thread that - * intends to use libcrypto. - */ -static union { - long sane; - CRYPTO_THREAD_LOCAL value; -} destructor_key = { -1 }; - -static void ossl_init_thread_stop(THREAD_EVENT_HANDLER **hands); - -static void ossl_init_thread_destructor(void *hands) -{ - ossl_init_thread_stop((THREAD_EVENT_HANDLER **)hands); -} - -static THREAD_EVENT_HANDLER **ossl_init_get_thread_local(int alloc) -{ - THREAD_EVENT_HANDLER **hands = - CRYPTO_THREAD_get_local(&destructor_key.value); - - if (alloc) { - if (hands == NULL - && (hands = OPENSSL_zalloc(sizeof(*hands))) != NULL - && !CRYPTO_THREAD_set_local(&destructor_key.value, hands)) { - OPENSSL_free(hands); - return NULL; - } - } else { - CRYPTO_THREAD_set_local(&destructor_key.value, NULL); - } - - return hands; -} - typedef struct ossl_init_stop_st OPENSSL_INIT_STOP; struct ossl_init_stop_st { void (*handler)(void); @@ -96,8 +44,6 @@ static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; static int base_inited = 0; DEFINE_RUN_ONCE_STATIC(ossl_init_base) { - CRYPTO_THREAD_LOCAL key; - if (ossl_trace_init() == 0) return 0; @@ -105,13 +51,14 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) #ifndef OPENSSL_NO_CRYPTO_MDEBUG ossl_malloc_setup_failures(); #endif - if (!CRYPTO_THREAD_init_local(&key, ossl_init_thread_destructor)) - return 0; + if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) goto err; OPENSSL_cpuid_setup(); - destructor_key.value = key; + if (!init_thread()) + return 0; + base_inited = 1; return 1; @@ -120,7 +67,6 @@ err: CRYPTO_THREAD_lock_free(init_lock); init_lock = NULL; - CRYPTO_THREAD_cleanup_local(&key); return 0; } @@ -424,60 +370,9 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_zlib) } #endif -static void ossl_init_thread_stop(THREAD_EVENT_HANDLER **hands) -{ - THREAD_EVENT_HANDLER *curr, *prev = NULL; - - /* Can't do much about this */ - if (hands == NULL) - return; - - curr = *hands; - while (curr != NULL) { - curr->handfn(curr->ctx); - prev = curr; - curr = curr->next; - OPENSSL_free(prev); - } - - OPENSSL_free(hands); -} - -void OPENSSL_thread_stop(void) -{ - if (destructor_key.sane != -1) - ossl_init_thread_stop(ossl_init_get_thread_local(0)); -} - -int ossl_init_thread_start(OPENSSL_CTX *ctx, ossl_thread_stop_handler_fn handfn) -{ - THREAD_EVENT_HANDLER **hands; - THREAD_EVENT_HANDLER *hand; - - if (!OPENSSL_init_crypto(0, NULL)) - return 0; - - hands = ossl_init_get_thread_local(1); - - if (hands == NULL) - return 0; - - hand = OPENSSL_malloc(sizeof(*hand)); - if (hand == NULL) - return 0; - - hand->handfn = handfn; - hand->ctx = ctx; - hand->next = *hands; - *hands = hand; - - return 1; -} - void OPENSSL_cleanup(void) { OPENSSL_INIT_STOP *currhandler, *lasthandler; - CRYPTO_THREAD_LOCAL key; /* * TODO(3.0): This function needs looking at with a view to moving most/all @@ -497,7 +392,7 @@ void OPENSSL_cleanup(void) * Thread stop may not get automatically called by the thread library for * the very last thread in some situations, so call it directly. */ - ossl_init_thread_stop(ossl_init_get_thread_local(0)); + OPENSSL_thread_stop(); currhandler = stop_handlers; while (currhandler != NULL) { @@ -533,9 +428,7 @@ void OPENSSL_cleanup(void) err_free_strings_int(); } - key = destructor_key.value; - destructor_key.sane = -1; - CRYPTO_THREAD_cleanup_local(&key); + cleanup_thread(); /* * Note that cleanup order is important: |