mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-05-19 12:59:40 +00:00
The function InitOnceExceuteOnce is the best way to support the implementation of CRYPTO_THREAD_run_once() on Windows. Unfortunately WinXP doesn't have it. To get around that we had two different implementations: one for WinXP and one for later versions. Which one was used was based on the value of _WIN32_WINNT. This approach was starting to cause problems though because other parts of OpenSSL assume _WIN32_WINNT is going to be 0x0501 and crashes were occurring dependant on include file ordering. In addition a conditional based on _WIN32_WINNT had made its way into a public header file through commit 5c4328f. This is problematic because the value of this macro can vary between OpenSSL build time and application build time. The simplest solution to this mess is just to always use the WinXP version of CRYPTO_THREAD_run_once(). Its perhaps slightly sub-optimal but probably not noticably. GitHub Issue #1086 Reviewed-by: Richard Levitte <levitte@openssl.org>
133 lines
2.8 KiB
C
133 lines
2.8 KiB
C
/*
|
|
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#include <openssl/crypto.h>
|
|
|
|
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS)
|
|
|
|
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
|
|
{
|
|
CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION));
|
|
if (lock == NULL)
|
|
return NULL;
|
|
|
|
/* 0x400 is the spin count value suggested in the documentation */
|
|
if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) {
|
|
OPENSSL_free(lock);
|
|
return NULL;
|
|
}
|
|
|
|
return lock;
|
|
}
|
|
|
|
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
|
|
{
|
|
EnterCriticalSection(lock);
|
|
return 1;
|
|
}
|
|
|
|
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
|
|
{
|
|
EnterCriticalSection(lock);
|
|
return 1;
|
|
}
|
|
|
|
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
|
|
{
|
|
LeaveCriticalSection(lock);
|
|
return 1;
|
|
}
|
|
|
|
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
|
|
{
|
|
if (lock == NULL)
|
|
return;
|
|
|
|
DeleteCriticalSection(lock);
|
|
OPENSSL_free(lock);
|
|
|
|
return;
|
|
}
|
|
|
|
# define ONCE_UNINITED 0
|
|
# define ONCE_ININIT 1
|
|
# define ONCE_DONE 2
|
|
|
|
/*
|
|
* We don't use InitOnceExecuteOnce because that isn't available in WinXP which
|
|
* we still have to support.
|
|
*/
|
|
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
|
|
{
|
|
LONG volatile *lock = (LONG *)once;
|
|
LONG result;
|
|
|
|
if (*lock == ONCE_DONE)
|
|
return 1;
|
|
|
|
do {
|
|
result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
|
|
if (result == ONCE_UNINITED) {
|
|
init();
|
|
*lock = ONCE_DONE;
|
|
return 1;
|
|
}
|
|
} while (result == ONCE_ININIT);
|
|
|
|
return (*lock == ONCE_DONE);
|
|
}
|
|
|
|
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
|
|
{
|
|
*key = TlsAlloc();
|
|
if (*key == TLS_OUT_OF_INDEXES)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
|
|
{
|
|
return TlsGetValue(*key);
|
|
}
|
|
|
|
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
|
|
{
|
|
if (TlsSetValue(*key, val) == 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
|
|
{
|
|
if (TlsFree(*key) == 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
|
|
{
|
|
return GetCurrentThreadId();
|
|
}
|
|
|
|
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
|
|
{
|
|
return (a == b);
|
|
}
|
|
|
|
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
|
|
{
|
|
*ret = InterlockedExchangeAdd(val, amount) + amount;
|
|
return 1;
|
|
}
|
|
|
|
#endif
|