-/* Implement "once" functionality */
-#if !defined(OPENSSL_THREADS)
-typedef int OPENSSL_INIT_ONCE;
-# define OPENSSL_INIT_ONCE_STATIC_INIT 0
-
-static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
-{
- if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) {
- *once = 1;
- init();
- }
-}
-
-static int ossl_init_setup_thread_stop(void)
-{
- /*
- * There are no threads to stop. Do nothing.
- */
- return 1;
-}
-
-static void ossl_init_thread_stop_cleanup(void)
-{
-}
-
-static struct thread_local_inits_st *local = NULL;
-static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc)
-{
- struct thread_local_inits_st *tmp;
-
- tmp = local;
-
- if (local == NULL && alloc)
- tmp = local = OPENSSL_zalloc(sizeof(*local));
-
- if (!alloc)
- local = NULL;
-
- return tmp;
-}
-
-#elif defined(OPENSSL_SYS_WINDOWS)
-
-# include <windows.h>
-
-# if _WIN32_WINNT < 0x0600
-
-/*
- * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not
- * have InitOnceExecuteOnce, so we fall back to using a spinlock instead.
- */
-typedef LONG OPENSSL_INIT_ONCE;
-# define OPENSSL_INIT_ONCE_STATIC_INIT 0
-
-# define ONCE_UNINITED 0
-# define ONCE_ININIT 1
-# define ONCE_DONE 2
-
-static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
-{
- LONG volatile *lock = (LONG *)once;
- LONG result;
-
- if (*lock == ONCE_DONE)
- return;
-
- do {
- result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
- if (result == ONCE_UNINITED) {
- init();
- *lock = ONCE_DONE;
- return;
- }
- } while (result == ONCE_ININIT);
-}
-
-# else
-
-typedef INIT_ONCE OPENSSL_INIT_ONCE;
-# define OPENSSL_INIT_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT
-
-static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused)
-{
- void (*init)(void) = initfp;
-
- init();
-
- return TRUE;
-}
-
-static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
-{
- InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL);
-}
-# endif
-
-static DWORD threadstopkey = TLS_OUT_OF_INDEXES;
-
-static int ossl_init_setup_thread_stop(void)
-{
- /*
- * We use a dummy thread local key here. We use the destructor to detect
- * when the thread is going to stop
- */
- threadstopkey = TlsAlloc();
- if (threadstopkey == TLS_OUT_OF_INDEXES)
- return 0;
-
- return 1;
-}
-
-static void ossl_init_thread_stop_cleanup(void)
-{
- if (threadstopkey != TLS_OUT_OF_INDEXES) {
- TlsFree(threadstopkey);
- }
-}
-
-static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc)
-{
- struct thread_local_inits_st *local = TlsGetValue(threadstopkey);
-
- if (local == NULL && alloc) {
- local = OPENSSL_zalloc(sizeof *local);
- TlsSetValue(threadstopkey, local);
- }
- if (!alloc) {
- TlsSetValue(threadstopkey, NULL);
- }
-
- return local;
-}
-
-#else /* pthreads */
-# include <pthread.h>
-
-static pthread_key_t threadstopkey;
-
-typedef pthread_once_t OPENSSL_INIT_ONCE;
-# define OPENSSL_INIT_ONCE_STATIC_INIT PTHREAD_ONCE_INIT
-
-static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
-{
- pthread_once(once, init);
-}