2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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
10 #include <internal/thread_arch.h>
12 #if defined(OPENSSL_THREADS_WINNT)
16 static DWORD __stdcall thread_start_thunk(LPVOID vthread)
18 CRYPTO_THREAD *thread;
19 CRYPTO_THREAD_RETVAL ret;
21 thread = (CRYPTO_THREAD *)vthread;
23 thread->thread_id = GetCurrentThreadId();
25 ret = thread->routine(thread->data);
26 ossl_crypto_mutex_lock(thread->statelock);
27 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_FINISHED);
29 ossl_crypto_condvar_broadcast(thread->condvar);
30 ossl_crypto_mutex_unlock(thread->statelock);
35 int ossl_crypto_thread_native_spawn(CRYPTO_THREAD *thread)
39 handle = OPENSSL_zalloc(sizeof(*handle));
43 *handle = (HANDLE)_beginthreadex(NULL, 0, &thread_start_thunk, thread, 0, NULL);
47 thread->handle = handle;
51 thread->handle = NULL;
56 int ossl_crypto_thread_native_join(CRYPTO_THREAD *thread, CRYPTO_THREAD_RETVAL *retval)
65 req_state_mask = CRYPTO_THREAD_TERMINATED | CRYPTO_THREAD_JOINED;
67 ossl_crypto_mutex_lock(thread->statelock);
68 if (CRYPTO_THREAD_GET_STATE(thread, req_state_mask))
70 while (!CRYPTO_THREAD_GET_STATE(thread, CRYPTO_THREAD_FINISHED))
71 ossl_crypto_condvar_wait(thread->condvar, thread->statelock);
73 handle = (HANDLE *) thread->handle;
77 if (WaitForSingleObject(*handle, INFINITE) != WAIT_OBJECT_0)
80 if (GetExitCodeThread(*handle, &thread_retval) == 0)
84 * GetExitCodeThread call followed by this check is to make sure that
85 * the thread exitted properly. In particular, thread_retval may be
86 * non-zero when exitted via explicit ExitThread/TerminateThread or
87 * if the thread is still active (returns STILL_ACTIVE (259)).
89 if (thread_retval != 0)
92 if (CloseHandle(*handle) == 0)
97 *retval = thread->retval;
99 CRYPTO_THREAD_UNSET_ERROR(thread, CRYPTO_THREAD_JOINED);
100 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_JOINED);
101 ossl_crypto_mutex_unlock(thread->statelock);
105 CRYPTO_THREAD_SET_ERROR(thread, CRYPTO_THREAD_JOINED);
106 ossl_crypto_mutex_unlock(thread->statelock);
110 int ossl_crypto_thread_native_terminate(CRYPTO_THREAD *thread)
115 mask = CRYPTO_THREAD_FINISHED;
116 mask |= CRYPTO_THREAD_TERMINATED;
117 mask |= CRYPTO_THREAD_JOINED;
122 ossl_crypto_mutex_lock(thread->statelock);
123 if (thread->handle == NULL || CRYPTO_THREAD_GET_STATE(thread, mask))
125 ossl_crypto_mutex_unlock(thread->statelock);
127 handle = thread->handle;
128 if (WaitForSingleObject(*handle, 0) != WAIT_OBJECT_0) {
129 if (TerminateThread(*handle, STILL_ACTIVE) == 0) {
130 ossl_crypto_mutex_lock(thread->statelock);
131 CRYPTO_THREAD_SET_ERROR(thread, CRYPTO_THREAD_TERMINATED);
132 ossl_crypto_mutex_unlock(thread->statelock);
137 if (CloseHandle(*handle) == 0) {
138 CRYPTO_THREAD_SET_ERROR(thread, CRYPTO_THREAD_TERMINATED);
142 thread->handle = NULL;
143 OPENSSL_free(handle);
145 ossl_crypto_mutex_lock(thread->statelock);
147 CRYPTO_THREAD_UNSET_ERROR(thread, CRYPTO_THREAD_TERMINATED);
148 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_TERMINATED);
149 ossl_crypto_mutex_unlock(thread->statelock);
153 int ossl_crypto_thread_native_exit(void)
159 int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread)
161 return thread->thread_id == GetCurrentThreadId();
164 CRYPTO_MUTEX *ossl_crypto_mutex_new(void)
166 CRITICAL_SECTION *mutex;
168 if ((mutex = OPENSSL_zalloc(sizeof(*mutex))) == NULL)
170 InitializeCriticalSection(mutex);
171 return (CRYPTO_MUTEX *)mutex;
174 void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex)
176 CRITICAL_SECTION *mutex_p;
178 mutex_p = (CRITICAL_SECTION *)mutex;
179 EnterCriticalSection(mutex_p);
182 int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex)
184 CRITICAL_SECTION *mutex_p;
186 mutex_p = (CRITICAL_SECTION *)mutex;
187 if (TryEnterCriticalSection(mutex_p))
193 void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex)
195 CRITICAL_SECTION *mutex_p;
197 mutex_p = (CRITICAL_SECTION *)mutex;
198 LeaveCriticalSection(mutex_p);
201 void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex)
203 CRITICAL_SECTION **mutex_p;
205 mutex_p = (CRITICAL_SECTION **)mutex;
206 if (*mutex_p != NULL)
207 DeleteCriticalSection(*mutex_p);
208 OPENSSL_free(*mutex_p);
212 CRYPTO_CONDVAR *ossl_crypto_condvar_new(void)
214 CONDITION_VARIABLE *cv_p;
216 if ((cv_p = OPENSSL_zalloc(sizeof(*cv_p))) == NULL)
218 InitializeConditionVariable(cv_p);
219 return (CRYPTO_CONDVAR *)cv_p;
222 void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex)
224 CONDITION_VARIABLE *cv_p;
225 CRITICAL_SECTION *mutex_p;
227 cv_p = (CONDITION_VARIABLE *)cv;
228 mutex_p = (CRITICAL_SECTION *)mutex;
229 SleepConditionVariableCS(cv_p, mutex_p, INFINITE);
232 void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv)
234 CONDITION_VARIABLE *cv_p;
236 cv_p = (CONDITION_VARIABLE *)cv;
237 WakeAllConditionVariable(cv_p);
240 void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv)
242 CONDITION_VARIABLE **cv_p;
244 cv_p = (CONDITION_VARIABLE **)cv;
249 void ossl_crypto_mem_barrier(void)