]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/threads_pthread.c
Corrections according the review comments.
[thirdparty/openssl.git] / crypto / threads_pthread.c
1 /*
2 * Copyright 2016 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
12 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
13
14 # ifdef PTHREAD_RWLOCK_INITIALIZER
15 # define USE_RWLOCK
16 # endif
17
18 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
19 {
20 # ifdef USE_RWLOCK
21 CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t));
22 if (lock == NULL)
23 return NULL;
24
25 if (pthread_rwlock_init(lock, NULL) != 0) {
26 OPENSSL_free(lock);
27 return NULL;
28 }
29 # else
30 pthread_mutexattr_t attr;
31
32 CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_mutex_t));
33 if (lock == NULL)
34 return NULL;
35
36 pthread_mutexattr_init(&attr);
37 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
38
39 if (pthread_mutex_init(lock, &attr) != 0) {
40 pthread_mutexattr_destroy(&attr);
41 OPENSSL_free(lock);
42 return NULL;
43 }
44
45 pthread_mutexattr_destroy(&attr);
46 # endif
47
48 return lock;
49 }
50
51 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
52 {
53 # ifdef USE_RWLOCK
54 if (pthread_rwlock_rdlock(lock) != 0)
55 return 0;
56 # else
57 if (pthread_mutex_lock(lock) != 0)
58 return 0;
59 # endif
60
61 return 1;
62 }
63
64 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
65 {
66 # ifdef USE_RWLOCK
67 if (pthread_rwlock_wrlock(lock) != 0)
68 return 0;
69 # else
70 if (pthread_mutex_lock(lock) != 0)
71 return 0;
72 # endif
73
74 return 1;
75 }
76
77 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
78 {
79 # ifdef USE_RWLOCK
80 if (pthread_rwlock_unlock(lock) != 0)
81 return 0;
82 # else
83 if (pthread_mutex_unlock(lock) != 0)
84 return 0;
85 # endif
86
87 return 1;
88 }
89
90 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
91 {
92 if (lock == NULL)
93 return;
94
95 # ifdef USE_RWLOCK
96 pthread_rwlock_destroy(lock);
97 # else
98 pthread_mutex_destroy(lock);
99 # endif
100 OPENSSL_free(lock);
101
102 return;
103 }
104
105 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
106 {
107 if (pthread_once(once, init) != 0)
108 return 0;
109
110 return 1;
111 }
112
113 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
114 {
115 if (pthread_key_create(key, cleanup) != 0)
116 return 0;
117
118 return 1;
119 }
120
121 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
122 {
123 return pthread_getspecific(*key);
124 }
125
126 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
127 {
128 if (pthread_setspecific(*key, val) != 0)
129 return 0;
130
131 return 1;
132 }
133
134 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
135 {
136 if (pthread_key_delete(*key) != 0)
137 return 0;
138
139 return 1;
140 }
141
142 CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
143 {
144 return pthread_self();
145 }
146
147 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
148 {
149 return pthread_equal(a, b);
150 }
151
152 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
153 {
154 # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
155 if (__atomic_is_lock_free(sizeof(*val), val)) {
156 *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
157 return 1;
158 }
159 # endif
160 if (!CRYPTO_THREAD_write_lock(lock))
161 return 0;
162
163 *val += amount;
164 *ret = *val;
165
166 if (!CRYPTO_THREAD_unlock(lock))
167 return 0;
168
169 return 1;
170 }
171
172 #endif