/src/openssl/crypto/threads_pthread.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the OpenSSL license (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 | 1.60M | { |
21 | 1.60M | # ifdef USE_RWLOCK |
22 | 1.60M | CRYPTO_RWLOCK *lock; |
23 | 1.60M | |
24 | 1.60M | if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) { |
25 | 0 | /* Don't set error, to avoid recursion blowup. */ |
26 | 0 | return NULL; |
27 | 0 | } |
28 | 1.60M | |
29 | 1.60M | if (pthread_rwlock_init(lock, NULL) != 0) { |
30 | 0 | OPENSSL_free(lock); |
31 | 0 | return NULL; |
32 | 0 | } |
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 | 1.60M | return lock; |
55 | 1.60M | } |
56 | | |
57 | | int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) |
58 | 1.90M | { |
59 | 1.90M | # ifdef USE_RWLOCK |
60 | 1.90M | if (pthread_rwlock_rdlock(lock) != 0) |
61 | 0 | return 0; |
62 | | # else |
63 | | if (pthread_mutex_lock(lock) != 0) |
64 | | return 0; |
65 | | # endif |
66 | | |
67 | 1.90M | return 1; |
68 | 1.90M | } |
69 | | |
70 | | int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) |
71 | 2.81M | { |
72 | 2.81M | # ifdef USE_RWLOCK |
73 | 2.81M | if (pthread_rwlock_wrlock(lock) != 0) |
74 | 0 | return 0; |
75 | | # else |
76 | | if (pthread_mutex_lock(lock) != 0) |
77 | | return 0; |
78 | | # endif |
79 | | |
80 | 2.81M | return 1; |
81 | 2.81M | } |
82 | | |
83 | | int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) |
84 | 4.71M | { |
85 | 4.71M | # ifdef USE_RWLOCK |
86 | 4.71M | if (pthread_rwlock_unlock(lock) != 0) |
87 | 0 | return 0; |
88 | | # else |
89 | | if (pthread_mutex_unlock(lock) != 0) |
90 | | return 0; |
91 | | # endif |
92 | | |
93 | 4.71M | return 1; |
94 | 4.71M | } |
95 | | |
96 | | void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) |
97 | 1.60M | { |
98 | 1.60M | if (lock == NULL) |
99 | 1.60M | return; |
100 | 1.60M | |
101 | 1.60M | # ifdef USE_RWLOCK |
102 | 1.60M | pthread_rwlock_destroy(lock); |
103 | | # else |
104 | | pthread_mutex_destroy(lock); |
105 | | # endif |
106 | 1.60M | OPENSSL_free(lock); |
107 | 1.60M | |
108 | 1.60M | return; |
109 | 1.60M | } |
110 | | |
111 | | int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) |
112 | 7.06M | { |
113 | 7.06M | if (pthread_once(once, init) != 0) |
114 | 0 | return 0; |
115 | 7.06M | |
116 | 7.06M | return 1; |
117 | 7.06M | } |
118 | | |
119 | | int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) |
120 | 16 | { |
121 | 16 | if (pthread_key_create(key, cleanup) != 0) |
122 | 0 | return 0; |
123 | 16 | |
124 | 16 | return 1; |
125 | 16 | } |
126 | | |
127 | | void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) |
128 | 1.33M | { |
129 | 1.33M | return pthread_getspecific(*key); |
130 | 1.33M | } |
131 | | |
132 | | int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) |
133 | 40 | { |
134 | 40 | if (pthread_setspecific(*key, val) != 0) |
135 | 0 | return 0; |
136 | 40 | |
137 | 40 | return 1; |
138 | 40 | } |
139 | | |
140 | | int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) |
141 | 16 | { |
142 | 16 | if (pthread_key_delete(*key) != 0) |
143 | 0 | return 0; |
144 | 16 | |
145 | 16 | return 1; |
146 | 16 | } |
147 | | |
148 | | CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) |
149 | 0 | { |
150 | 0 | return pthread_self(); |
151 | 0 | } |
152 | | |
153 | | int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) |
154 | 0 | { |
155 | 0 | return pthread_equal(a, b); |
156 | 0 | } |
157 | | |
158 | | int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) |
159 | 0 | { |
160 | 0 | # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) |
161 | 0 | if (__atomic_is_lock_free(sizeof(*val), val)) { |
162 | 0 | *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL); |
163 | 0 | return 1; |
164 | 0 | } |
165 | 0 | # endif |
166 | 0 | if (!CRYPTO_THREAD_write_lock(lock)) |
167 | 0 | return 0; |
168 | 0 | |
169 | 0 | *val += amount; |
170 | 0 | *ret = *val; |
171 | 0 |
|
172 | 0 | if (!CRYPTO_THREAD_unlock(lock)) |
173 | 0 | return 0; |
174 | 0 | |
175 | 0 | return 1; |
176 | 0 | } |
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 | 0 | { |
183 | 0 | pthread_atfork(OPENSSL_fork_prepare, |
184 | 0 | OPENSSL_fork_parent, OPENSSL_fork_child); |
185 | 0 | } |
186 | | # endif |
187 | | |
188 | | int openssl_init_fork_handlers(void) |
189 | 0 | { |
190 | 0 | # ifdef OPENSSL_SYS_UNIX |
191 | 0 | if (pthread_once(&fork_once_control, fork_once_func) == 0) |
192 | 0 | return 1; |
193 | 0 | # endif |
194 | 0 | return 0; |
195 | 0 | } |
196 | | #endif |