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_POSIX)
15 # include <sys/types.h>
18 static void *thread_start_thunk(void *vthread)
20 CRYPTO_THREAD *thread;
21 CRYPTO_THREAD_RETVAL ret;
23 thread = (CRYPTO_THREAD *)vthread;
25 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
26 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
28 ret = thread->routine(thread->data);
29 ossl_crypto_mutex_lock(thread->statelock);
30 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_FINISHED);
32 ossl_crypto_condvar_broadcast(thread->condvar);
33 ossl_crypto_mutex_unlock(thread->statelock);
38 int ossl_crypto_thread_native_spawn(CRYPTO_THREAD *thread)
44 handle = OPENSSL_zalloc(sizeof(*handle));
48 pthread_attr_init(&attr);
49 if (!thread->joinable)
50 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
51 ret = pthread_create(handle, &attr, thread_start_thunk, thread);
52 pthread_attr_destroy(&attr);
57 thread->handle = handle;
61 thread->handle = NULL;
66 int ossl_crypto_thread_native_join(CRYPTO_THREAD *thread, CRYPTO_THREAD_RETVAL *retval)
70 uint64_t req_state_mask;
75 req_state_mask = CRYPTO_THREAD_TERMINATED | CRYPTO_THREAD_JOINED;
77 ossl_crypto_mutex_lock(thread->statelock);
78 if (CRYPTO_THREAD_GET_STATE(thread, req_state_mask)) {
79 ossl_crypto_mutex_unlock(thread->statelock);
82 while (!CRYPTO_THREAD_GET_STATE(thread, CRYPTO_THREAD_FINISHED))
83 ossl_crypto_condvar_wait(thread->condvar, thread->statelock);
84 ossl_crypto_mutex_unlock(thread->statelock);
86 handle = (pthread_t *) thread->handle;
90 if (pthread_join(*handle, &thread_retval) != 0)
94 * Join return value may be non-NULL when the thread has been cancelled,
95 * as indicated by thread_retval set to PTHREAD_CANCELLED.
97 if (thread_retval != NULL)
102 *retval = thread->retval;
104 ossl_crypto_mutex_lock(thread->statelock);
105 CRYPTO_THREAD_UNSET_ERROR(thread, CRYPTO_THREAD_JOINED);
106 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_JOINED);
107 ossl_crypto_mutex_unlock(thread->statelock);
111 ossl_crypto_mutex_lock(thread->statelock);
112 CRYPTO_THREAD_SET_ERROR(thread, CRYPTO_THREAD_JOINED);
113 ossl_crypto_mutex_unlock(thread->statelock);
117 int ossl_crypto_thread_native_terminate(CRYPTO_THREAD *thread)
123 mask = CRYPTO_THREAD_FINISHED;
124 mask |= CRYPTO_THREAD_TERMINATED;
125 mask |= CRYPTO_THREAD_JOINED;
130 ossl_crypto_mutex_lock(thread->statelock);
131 if (thread->handle == NULL || CRYPTO_THREAD_GET_STATE(thread, mask))
133 ossl_crypto_mutex_unlock(thread->statelock);
135 handle = thread->handle;
136 if (pthread_cancel(*handle) != 0) {
137 ossl_crypto_mutex_lock(thread->statelock);
138 CRYPTO_THREAD_SET_ERROR(thread, CRYPTO_THREAD_TERMINATED);
139 ossl_crypto_mutex_unlock(thread->statelock);
142 if (pthread_join(*handle, &res) != 0)
144 if (res != PTHREAD_CANCELED)
147 thread->handle = NULL;
148 OPENSSL_free(handle);
150 ossl_crypto_mutex_lock(thread->statelock);
152 CRYPTO_THREAD_UNSET_ERROR(thread, CRYPTO_THREAD_TERMINATED);
153 CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_TERMINATED);
154 ossl_crypto_mutex_unlock(thread->statelock);
158 int ossl_crypto_thread_native_exit(void)
164 int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread)
166 return pthread_equal(*(pthread_t *)thread->handle, pthread_self());
169 CRYPTO_MUTEX *ossl_crypto_mutex_new(void)
171 pthread_mutex_t *mutex;
173 if ((mutex = OPENSSL_zalloc(sizeof(*mutex))) == NULL)
175 if (pthread_mutex_init(mutex, NULL) != 0) {
179 return (CRYPTO_MUTEX *)mutex;
182 int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex)
184 pthread_mutex_t *mutex_p;
186 mutex_p = (pthread_mutex_t *)mutex;
188 if (pthread_mutex_trylock(mutex_p) == EBUSY)
194 void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex)
196 pthread_mutex_t *mutex_p;
198 mutex_p = (pthread_mutex_t *)mutex;
199 pthread_mutex_lock(mutex_p);
202 void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex)
204 pthread_mutex_t *mutex_p;
206 mutex_p = (pthread_mutex_t *)mutex;
207 pthread_mutex_unlock(mutex_p);
210 void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex)
212 pthread_mutex_t **mutex_p;
217 mutex_p = (pthread_mutex_t **)mutex;
218 if (*mutex_p != NULL)
219 pthread_mutex_destroy(*mutex_p);
220 OPENSSL_free(*mutex_p);
224 CRYPTO_CONDVAR *ossl_crypto_condvar_new(void)
226 pthread_cond_t *cv_p;
228 if ((cv_p = OPENSSL_zalloc(sizeof(*cv_p))) == NULL)
230 if (pthread_cond_init(cv_p, NULL) != 0) {
234 return (CRYPTO_CONDVAR *) cv_p;
237 void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex)
239 pthread_cond_t *cv_p;
240 pthread_mutex_t *mutex_p;
242 cv_p = (pthread_cond_t *)cv;
243 mutex_p = (pthread_mutex_t *)mutex;
244 pthread_cond_wait(cv_p, mutex_p);
247 void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv)
249 pthread_cond_t *cv_p;
251 cv_p = (pthread_cond_t *)cv;
252 pthread_cond_broadcast(cv_p);
255 void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv)
257 pthread_cond_t **cv_p;
262 cv_p = (pthread_cond_t **)cv;
264 pthread_cond_destroy(*cv_p);
269 void ossl_crypto_mem_barrier(void)
271 # if defined(__clang__) || defined(__GNUC__)
272 __sync_synchronize();
273 # elif !defined(OPENSSL_NO_ASM)
274 # if defined(__alpha__) /* Alpha */
275 __asm__ volatile("mb" : : : "memory");
276 # elif defined(__amd64__) || defined(__i386__) || defined(__i486__) \
277 || defined(__i586__) || defined(__i686__) || defined(__i386) /* x86 */
278 __asm__ volatile("mfence" : : : "memory");
279 # elif defined(__arm__) || defined(__aarch64__) /* ARMv7, ARMv8 */
280 __asm__ volatile("dmb ish" : : : "memory");
281 # elif defined(__hppa__) /* PARISC */
282 __asm__ volatile("" : : : "memory");
283 # elif defined(__mips__) /* MIPS */
284 __asm__ volatile("sync" : : : "memory");
285 # elif defined(__powerpc__) || defined(__powerpc64__) /* power, ppc64, ppc64le */
286 __asm__ volatile("sync" : : : "memory");
287 # elif defined(__sparc__)
288 __asm__ volatile("ba,pt %%xcc, 1f\n\t" \
292 # elif defined(__s390__) || defined(__s390x__) /* z */
293 __asm__ volatile("bcr 15,0" : : : "memory");
294 # elif defined(__riscv) || defined(__riscv__) /* riscv */
295 __asm__ volatile("fence iorw,iorw" : : : "memory");
296 # else /* others, compiler only */
297 __asm__ volatile("" : : : "memory");
300 /* compiler only barrier */
301 __asm__ volatile("" : : : "memory");