]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/threads_pthread.c
Coverity: hkdf ENV_MD_size() is an int that can be negative
[thirdparty/openssl.git] / crypto / threads_pthread.c
1 /*
2 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10 #include <openssl/crypto.h>
11 #include "internal/cryptlib.h"
12
13 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
14
15 # ifdef PTHREAD_RWLOCK_INITIALIZER
16 # define USE_RWLOCK
17 # endif
18
19 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
20 {
21 # ifdef USE_RWLOCK
22 CRYPTO_RWLOCK *lock;
23
24 if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) {
25 /* Don't set error, to avoid recursion blowup. */
26 return NULL;
27 }
28
29 if (pthread_rwlock_init(lock, NULL) != 0) {
30 OPENSSL_free(lock);
31 return NULL;
32 }
33 # else
34 pthread_mutexattr_t attr;
35 CRYPTO_RWLOCK *lock;
36
37 if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) {
38 /* Don't set error, to avoid recursion blowup. */
39 return NULL;
40 }
41
42 pthread_mutexattr_init(&attr);
43 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
44
45 if (pthread_mutex_init(lock, &attr) != 0) {
46 pthread_mutexattr_destroy(&attr);
47 OPENSSL_free(lock);
48 return NULL;
49 }
50
51 pthread_mutexattr_destroy(&attr);
52 # endif
53
54 return lock;
55 }
56
57 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
58 {
59 # ifdef USE_RWLOCK
60 if (pthread_rwlock_rdlock(lock) != 0)
61 return 0;
62 # else
63 if (pthread_mutex_lock(lock) != 0)
64 return 0;
65 # endif
66
67 return 1;
68 }
69
70 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
71 {
72 # ifdef USE_RWLOCK
73 if (pthread_rwlock_wrlock(lock) != 0)
74 return 0;
75 # else
76 if (pthread_mutex_lock(lock) != 0)
77 return 0;
78 # endif
79
80 return 1;
81 }
82
83 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
84 {
85 # ifdef USE_RWLOCK
86 if (pthread_rwlock_unlock(lock) != 0)
87 return 0;
88 # else
89 if (pthread_mutex_unlock(lock) != 0)
90 return 0;
91 # endif
92
93 return 1;
94 }
95
96 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
97 {
98 if (lock == NULL)
99 return;
100
101 # ifdef USE_RWLOCK
102 pthread_rwlock_destroy(lock);
103 # else
104 pthread_mutex_destroy(lock);
105 # endif
106 OPENSSL_free(lock);
107
108 return;
109 }
110
111 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
112 {
113 if (pthread_once(once, init) != 0)
114 return 0;
115
116 return 1;
117 }
118
119 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
120 {
121 if (pthread_key_create(key, cleanup) != 0)
122 return 0;
123
124 return 1;
125 }
126
127 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
128 {
129 return pthread_getspecific(*key);
130 }
131
132 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
133 {
134 if (pthread_setspecific(*key, val) != 0)
135 return 0;
136
137 return 1;
138 }
139
140 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
141 {
142 if (pthread_key_delete(*key) != 0)
143 return 0;
144
145 return 1;
146 }
147
148 CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
149 {
150 return pthread_self();
151 }
152
153 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
154 {
155 return pthread_equal(a, b);
156 }
157
158 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
159 {
160 # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
161 if (__atomic_is_lock_free(sizeof(*val), val)) {
162 *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
163 return 1;
164 }
165 # endif
166 if (!CRYPTO_THREAD_write_lock(lock))
167 return 0;
168
169 *val += amount;
170 *ret = *val;
171
172 if (!CRYPTO_THREAD_unlock(lock))
173 return 0;
174
175 return 1;
176 }
177
178 # ifdef OPENSSL_SYS_UNIX
179 static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
180
181 static void fork_once_func(void)
182 {
183 pthread_atfork(OPENSSL_fork_prepare,
184 OPENSSL_fork_parent, OPENSSL_fork_child);
185 }
186 # endif
187
188 int openssl_init_fork_handlers(void)
189 {
190 # ifdef OPENSSL_SYS_UNIX
191 if (pthread_once(&fork_once_control, fork_once_func) == 0)
192 return 1;
193 # endif
194 return 0;
195 }
196 #endif