]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/threads_pthread.c
2 * Copyright 2016-2023 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 /* We need to use the OPENSSL_fork_*() deprecated APIs */
11 #define OPENSSL_SUPPRESS_DEPRECATED
13 #include <openssl/crypto.h>
14 #include "internal/cryptlib.h"
20 #if defined(__apple_build_version__) && __apple_build_version__ < 6000000
22 * OS/X 10.7 and 10.8 had a weird version of clang which has __ATOMIC_ACQUIRE and
23 * __ATOMIC_ACQ_REL but which expects only one parameter for __atomic_is_lock_free()
24 * rather than two which has signature __atomic_is_lock_free(sizeof(_Atomic(T))).
25 * All of this makes impossible to use __atomic_is_lock_free here.
27 * See: https://github.com/llvm/llvm-project/commit/a4c2602b714e6c6edb98164550a5ae829b2de760
29 #define BROKEN_CLANG_ATOMICS
32 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
34 # if defined(OPENSSL_SYS_UNIX)
35 # include <sys/types.h>
41 # ifdef PTHREAD_RWLOCK_INITIALIZER
45 CRYPTO_RWLOCK
*CRYPTO_THREAD_lock_new(void)
50 if ((lock
= CRYPTO_zalloc(sizeof(pthread_rwlock_t
), NULL
, 0)) == NULL
)
51 /* Don't set error, to avoid recursion blowup. */
54 if (pthread_rwlock_init(lock
, NULL
) != 0) {
59 pthread_mutexattr_t attr
;
62 if ((lock
= CRYPTO_zalloc(sizeof(pthread_mutex_t
), NULL
, 0)) == NULL
)
63 /* Don't set error, to avoid recursion blowup. */
67 * We don't use recursive mutexes, but try to catch errors if we do.
69 pthread_mutexattr_init(&attr
);
70 # if !defined (__TANDEM) && !defined (_SPT_MODEL_)
71 # if !defined(NDEBUG) && !defined(OPENSSL_NO_MUTEX_ERRORCHECK)
72 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_ERRORCHECK
);
75 /* The SPT Thread Library does not define MUTEX attributes. */
78 if (pthread_mutex_init(lock
, &attr
) != 0) {
79 pthread_mutexattr_destroy(&attr
);
84 pthread_mutexattr_destroy(&attr
);
90 __owur
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK
*lock
)
93 if (pthread_rwlock_rdlock(lock
) != 0)
96 if (pthread_mutex_lock(lock
) != 0) {
97 assert(errno
!= EDEADLK
&& errno
!= EBUSY
);
105 __owur
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK
*lock
)
108 if (pthread_rwlock_wrlock(lock
) != 0)
111 if (pthread_mutex_lock(lock
) != 0) {
112 assert(errno
!= EDEADLK
&& errno
!= EBUSY
);
120 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK
*lock
)
123 if (pthread_rwlock_unlock(lock
) != 0)
126 if (pthread_mutex_unlock(lock
) != 0) {
127 assert(errno
!= EPERM
);
135 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK
*lock
)
141 pthread_rwlock_destroy(lock
);
143 pthread_mutex_destroy(lock
);
150 int CRYPTO_THREAD_run_once(CRYPTO_ONCE
*once
, void (*init
)(void))
152 if (pthread_once(once
, init
) != 0)
158 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL
*key
, void (*cleanup
)(void *))
160 if (pthread_key_create(key
, cleanup
) != 0)
166 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL
*key
)
168 return pthread_getspecific(*key
);
171 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL
*key
, void *val
)
173 if (pthread_setspecific(*key
, val
) != 0)
179 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL
*key
)
181 if (pthread_key_delete(*key
) != 0)
187 CRYPTO_THREAD_ID
CRYPTO_THREAD_get_current_id(void)
189 return pthread_self();
192 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a
, CRYPTO_THREAD_ID b
)
194 return pthread_equal(a
, b
);
197 int CRYPTO_atomic_add(int *val
, int amount
, int *ret
, CRYPTO_RWLOCK
*lock
)
199 # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
200 if (__atomic_is_lock_free(sizeof(*val
), val
)) {
201 *ret
= __atomic_add_fetch(val
, amount
, __ATOMIC_ACQ_REL
);
204 # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
205 /* This will work for all future Solaris versions. */
207 *ret
= atomic_add_int_nv((volatile unsigned int *)val
, amount
);
211 if (lock
== NULL
|| !CRYPTO_THREAD_write_lock(lock
))
217 if (!CRYPTO_THREAD_unlock(lock
))
223 int CRYPTO_atomic_or(uint64_t *val
, uint64_t op
, uint64_t *ret
,
226 # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
227 if (__atomic_is_lock_free(sizeof(*val
), val
)) {
228 *ret
= __atomic_or_fetch(val
, op
, __ATOMIC_ACQ_REL
);
231 # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
232 /* This will work for all future Solaris versions. */
234 *ret
= atomic_or_64_nv(val
, op
);
238 if (lock
== NULL
|| !CRYPTO_THREAD_write_lock(lock
))
243 if (!CRYPTO_THREAD_unlock(lock
))
249 int CRYPTO_atomic_load(uint64_t *val
, uint64_t *ret
, CRYPTO_RWLOCK
*lock
)
251 # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
252 if (__atomic_is_lock_free(sizeof(*val
), val
)) {
253 __atomic_load(val
, ret
, __ATOMIC_ACQUIRE
);
256 # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
257 /* This will work for all future Solaris versions. */
259 *ret
= atomic_or_64_nv(val
, 0);
263 if (lock
== NULL
|| !CRYPTO_THREAD_read_lock(lock
))
266 if (!CRYPTO_THREAD_unlock(lock
))
272 int CRYPTO_atomic_load_int(int *val
, int *ret
, CRYPTO_RWLOCK
*lock
)
274 # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
275 if (__atomic_is_lock_free(sizeof(*val
), val
)) {
276 __atomic_load(val
, ret
, __ATOMIC_ACQUIRE
);
279 # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
280 /* This will work for all future Solaris versions. */
282 *ret
= (int *)atomic_or_uint_nv((unsigned int *)val
, 0);
286 if (lock
== NULL
|| !CRYPTO_THREAD_read_lock(lock
))
289 if (!CRYPTO_THREAD_unlock(lock
))
296 int openssl_init_fork_handlers(void)
300 # endif /* FIPS_MODULE */
302 int openssl_get_fork_id(void)