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 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)
41 handle = OPENSSL_zalloc(sizeof(*handle));
45 pthread_attr_init(&attr);
46 if (!thread->joinable)
47 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
48 ret = pthread_create(handle, &attr, thread_start_thunk, thread);
49 pthread_attr_destroy(&attr);
54 thread->handle = handle;
58 thread->handle = NULL;
63 int ossl_crypto_thread_native_perform_join(CRYPTO_THREAD *thread, CRYPTO_THREAD_RETVAL *retval)
68 if (thread == NULL || thread->handle == NULL)
71 handle = (pthread_t *) thread->handle;
72 if (pthread_join(*handle, &thread_retval) != 0)
76 * Join return value may be non-NULL when the thread has been cancelled,
77 * as indicated by thread_retval set to PTHREAD_CANCELLED.
79 if (thread_retval != NULL)
85 int ossl_crypto_thread_native_exit(void)
91 int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread)
93 return pthread_equal(*(pthread_t *)thread->handle, pthread_self());
96 CRYPTO_MUTEX *ossl_crypto_mutex_new(void)
98 pthread_mutex_t *mutex;
100 if ((mutex = OPENSSL_zalloc(sizeof(*mutex))) == NULL)
102 if (pthread_mutex_init(mutex, NULL) != 0) {
106 return (CRYPTO_MUTEX *)mutex;
109 int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex)
111 pthread_mutex_t *mutex_p;
113 mutex_p = (pthread_mutex_t *)mutex;
115 if (pthread_mutex_trylock(mutex_p) == EBUSY)
121 void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex)
123 pthread_mutex_t *mutex_p;
125 mutex_p = (pthread_mutex_t *)mutex;
126 pthread_mutex_lock(mutex_p);
129 void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex)
131 pthread_mutex_t *mutex_p;
133 mutex_p = (pthread_mutex_t *)mutex;
134 pthread_mutex_unlock(mutex_p);
137 void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex)
139 pthread_mutex_t **mutex_p;
144 mutex_p = (pthread_mutex_t **)mutex;
145 if (*mutex_p != NULL)
146 pthread_mutex_destroy(*mutex_p);
147 OPENSSL_free(*mutex_p);
151 CRYPTO_CONDVAR *ossl_crypto_condvar_new(void)
153 pthread_cond_t *cv_p;
155 if ((cv_p = OPENSSL_zalloc(sizeof(*cv_p))) == NULL)
157 if (pthread_cond_init(cv_p, NULL) != 0) {
161 return (CRYPTO_CONDVAR *) cv_p;
164 void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex)
166 pthread_cond_t *cv_p;
167 pthread_mutex_t *mutex_p;
169 cv_p = (pthread_cond_t *)cv;
170 mutex_p = (pthread_mutex_t *)mutex;
171 pthread_cond_wait(cv_p, mutex_p);
174 void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex,
177 pthread_cond_t *cv_p = (pthread_cond_t *)cv;
178 pthread_mutex_t *mutex_p = (pthread_mutex_t *)mutex;
180 if (ossl_time_is_infinite(deadline)) {
182 * No deadline. Some pthread implementations allow
183 * pthread_cond_timedwait to work the same as pthread_cond_wait when
184 * abstime is NULL, but it is unclear whether this is POSIXly correct.
186 pthread_cond_wait(cv_p, mutex_p);
188 struct timespec deadline_ts;
191 = ossl_time2seconds(deadline);
193 = (ossl_time2ticks(deadline) % OSSL_TIME_SECOND) / OSSL_TIME_NS;
195 pthread_cond_timedwait(cv_p, mutex_p, &deadline_ts);
199 void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv)
201 pthread_cond_t *cv_p;
203 cv_p = (pthread_cond_t *)cv;
204 pthread_cond_broadcast(cv_p);
207 void ossl_crypto_condvar_signal(CRYPTO_CONDVAR *cv)
209 pthread_cond_t *cv_p;
211 cv_p = (pthread_cond_t *)cv;
212 pthread_cond_signal(cv_p);
215 void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv)
217 pthread_cond_t **cv_p;
222 cv_p = (pthread_cond_t **)cv;
224 pthread_cond_destroy(*cv_p);