int ossl_init_thread_start(const void *index, void *arg,
                           OSSL_thread_stop_handler_fn handfn)
{
    THREAD_EVENT_HANDLER **hands;
    THREAD_EVENT_HANDLER *hand;
#ifdef FIPS_MODE
    OPENSSL_CTX *ctx = arg;
    CRYPTO_THREAD_LOCAL *local
        = openssl_ctx_get_data(ctx, OPENSSL_CTX_THREAD_EVENT_HANDLER_INDEX,
                               &thread_event_ossl_ctx_method);
#else
    CRYPTO_THREAD_LOCAL *local = &destructor_key.value;
#endif
    hands = init_get_thread_local(local, 1, 0);
    if (hands == NULL)
        return 0;
#ifdef FIPS_MODE
    if (*hands == NULL) {
        if (!c_thread_start(FIPS_get_provider(ctx), ossl_ctx_thread_stop))
            return 0;
    }
#endif
    hand = OPENSSL_malloc(sizeof(*hand));
    if (hand == NULL)
        return 0;
    hand->handfn = handfn;
    hand->arg = arg;
    hand->index = index;
    hand->next = *hands;
    *hands = hand;
    return 1;
}
['int ossl_init_thread_start(const void *index, void *arg,\n                           OSSL_thread_stop_handler_fn handfn)\n{\n    THREAD_EVENT_HANDLER **hands;\n    THREAD_EVENT_HANDLER *hand;\n#ifdef FIPS_MODE\n    OPENSSL_CTX *ctx = arg;\n    CRYPTO_THREAD_LOCAL *local\n        = openssl_ctx_get_data(ctx, OPENSSL_CTX_THREAD_EVENT_HANDLER_INDEX,\n                               &thread_event_ossl_ctx_method);\n#else\n    CRYPTO_THREAD_LOCAL *local = &destructor_key.value;\n#endif\n    hands = init_get_thread_local(local, 1, 0);\n    if (hands == NULL)\n        return 0;\n#ifdef FIPS_MODE\n    if (*hands == NULL) {\n        if (!c_thread_start(FIPS_get_provider(ctx), ossl_ctx_thread_stop))\n            return 0;\n    }\n#endif\n    hand = OPENSSL_malloc(sizeof(*hand));\n    if (hand == NULL)\n        return 0;\n    hand->handfn = handfn;\n    hand->arg = arg;\n    hand->index = index;\n    hand->next = *hands;\n    *hands = hand;\n    return 1;\n}', 'void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,\n                           const OPENSSL_CTX_METHOD *meth)\n{\n    void *data = NULL;\n    ctx = openssl_ctx_get_concrete(ctx);\n    if (ctx == NULL)\n        return NULL;\n    CRYPTO_THREAD_read_lock(ctx->lock);\n    if (ctx->dyn_indexes[index] == -1\n            && !openssl_ctx_init_index(ctx, index, meth)) {\n        CRYPTO_THREAD_unlock(ctx->lock);\n        return NULL;\n    }\n    if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,\n                             &ctx->data, ctx->dyn_indexes[index]))\n        data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);\n    CRYPTO_THREAD_unlock(ctx->lock);\n    return data;\n}', 'OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)\n{\n#ifndef FIPS_MODE\n    if (ctx == NULL) {\n        if (!RUN_ONCE(&default_context_init, do_default_context_init))\n            return 0;\n        return default_context;\n    }\n#endif\n    return ctx;\n}', 'static THREAD_EVENT_HANDLER **\ninit_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep)\n{\n    THREAD_EVENT_HANDLER **hands = CRYPTO_THREAD_get_local(local);\n    if (alloc) {\n        if (hands == NULL) {\n            if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL)\n                return NULL;\n            if (!CRYPTO_THREAD_set_local(local, hands)) {\n                OPENSSL_free(hands);\n                return NULL;\n            }\n#ifndef FIPS_MODE\n            if (!init_thread_push_handlers(hands)) {\n                CRYPTO_THREAD_set_local(local, NULL);\n                OPENSSL_free(hands);\n                return NULL;\n            }\n#endif\n        }\n    } else if (!keep) {\n        CRYPTO_THREAD_set_local(local, NULL);\n    }\n    return hands;\n}', 'void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)\n{\n    return pthread_getspecific(*key);\n}']