1 /* 2 * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #if defined(_WIN32) 11 # include <windows.h> 12 #endif 13 14 #include <openssl/crypto.h> 15 16 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS) 17 18 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) 19 { 20 CRYPTO_RWLOCK *lock; 21 22 if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) { 23 /* Don't set error, to avoid recursion blowup. */ 24 return NULL; 25 } 26 27 # if !defined(_WIN32_WCE) 28 /* 0x400 is the spin count value suggested in the documentation */ 29 if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) { 30 OPENSSL_free(lock); 31 return NULL; 32 } 33 # else 34 InitializeCriticalSection(lock); 35 # endif 36 37 return lock; 38 } 39 40 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) 41 { 42 EnterCriticalSection(lock); 43 return 1; 44 } 45 46 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) 47 { 48 EnterCriticalSection(lock); 49 return 1; 50 } 51 52 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) 53 { 54 LeaveCriticalSection(lock); 55 return 1; 56 } 57 58 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) 59 { 60 if (lock == NULL) 61 return; 62 63 DeleteCriticalSection(lock); 64 OPENSSL_free(lock); 65 66 return; 67 } 68 69 # define ONCE_UNINITED 0 70 # define ONCE_ININIT 1 71 # define ONCE_DONE 2 72 73 /* 74 * We don't use InitOnceExecuteOnce because that isn't available in WinXP which 75 * we still have to support. 76 */ 77 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) 78 { 79 LONG volatile *lock = (LONG *)once; 80 LONG result; 81 82 if (*lock == ONCE_DONE) 83 return 1; 84 85 do { 86 result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); 87 if (result == ONCE_UNINITED) { 88 init(); 89 *lock = ONCE_DONE; 90 return 1; 91 } 92 } while (result == ONCE_ININIT); 93 94 return (*lock == ONCE_DONE); 95 } 96 97 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) 98 { 99 *key = TlsAlloc(); 100 if (*key == TLS_OUT_OF_INDEXES) 101 return 0; 102 103 return 1; 104 } 105 106 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) 107 { 108 DWORD last_error; 109 void *ret; 110 111 /* 112 * TlsGetValue clears the last error even on success, so that callers may 113 * distinguish it successfully returning NULL or failing. It is documented 114 * to never fail if the argument is a valid index from TlsAlloc, so we do 115 * not need to handle this. 116 * 117 * However, this error-mangling behavior interferes with the caller's use of 118 * GetLastError. In particular SSL_get_error queries the error queue to 119 * determine whether the caller should look at the OS's errors. To avoid 120 * destroying state, save and restore the Windows error. 121 * 122 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686812(v=vs.85).aspx 123 */ 124 last_error = GetLastError(); 125 ret = TlsGetValue(*key); 126 SetLastError(last_error); 127 return ret; 128 } 129 130 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) 131 { 132 if (TlsSetValue(*key, val) == 0) 133 return 0; 134 135 return 1; 136 } 137 138 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) 139 { 140 if (TlsFree(*key) == 0) 141 return 0; 142 143 return 1; 144 } 145 146 CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) 147 { 148 return GetCurrentThreadId(); 149 } 150 151 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) 152 { 153 return (a == b); 154 } 155 156 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) 157 { 158 *ret = (int)InterlockedExchangeAdd((long volatile *)val, (long)amount) + amount; 159 return 1; 160 } 161 162 int openssl_init_fork_handlers(void) 163 { 164 return 0; 165 } 166 167 int openssl_get_fork_id(void) 168 { 169 return 0; 170 } 171 #endif 172