Skip to content

Commit d5e742d

Browse files
mattcaswellbeldmit
authored andcommitted
Add some more CRYPTO_atomic functions
We add an implementation for CRYPTO_atomic_or() and CRYPTO_atomic_load() Reviewed-by: Dmitry Belyavskiy <[email protected]> (Merged from #13733)
1 parent 30af356 commit d5e742d

File tree

5 files changed

+86
-4
lines changed

5 files changed

+86
-4
lines changed

crypto/threads_none.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
133133
return 1;
134134
}
135135

136+
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
137+
CRYPTO_RWLOCK *lock)
138+
{
139+
*val |= op;
140+
*ret = *val;
141+
142+
return 1;
143+
}
144+
145+
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
146+
{
147+
*ret = *val;
148+
149+
return 1;
150+
}
151+
136152
int openssl_init_fork_handlers(void)
137153
{
138154
return 0;

crypto/threads_pthread.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
185185
return 1;
186186
}
187187
# endif
188-
if (!CRYPTO_THREAD_write_lock(lock))
188+
if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
189189
return 0;
190190

191191
*val += amount;
@@ -197,6 +197,54 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
197197
return 1;
198198
}
199199

200+
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
201+
CRYPTO_RWLOCK *lock)
202+
{
203+
# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
204+
if (__atomic_is_lock_free(sizeof(*val), val)) {
205+
*ret = __atomic_or_fetch(val, op, __ATOMIC_ACQ_REL);
206+
return 1;
207+
}
208+
# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
209+
/* This will work for all future Solaris versions. */
210+
if (ret != NULL) {
211+
*ret = atomic_or_64_nv(val, op);
212+
return 1;
213+
}
214+
# endif
215+
if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
216+
return 0;
217+
*val |= op;
218+
*ret = *val;
219+
220+
if (!CRYPTO_THREAD_unlock(lock))
221+
return 0;
222+
223+
return 1;
224+
}
225+
226+
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
227+
{
228+
# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE)
229+
if (__atomic_is_lock_free(sizeof(*val), val)) {
230+
__atomic_load(val, ret, __ATOMIC_ACQUIRE);
231+
return 1;
232+
}
233+
# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
234+
/* This will work for all future Solaris versions. */
235+
if (ret != NULL) {
236+
*ret = atomic_or_64_nv(val, 0);
237+
return 1;
238+
}
239+
# endif
240+
if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
241+
return 0;
242+
*ret = *val;
243+
if (!CRYPTO_THREAD_unlock(lock))
244+
return 0;
245+
246+
return 1;
247+
}
200248
# ifndef FIPS_MODULE
201249
# ifdef OPENSSL_SYS_UNIX
202250

crypto/threads_win.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
6666
return;
6767
}
6868

69-
# define ONCE_UNINITED 0
70-
# define ONCE_ININIT 1
71-
# define ONCE_DONE 2
69+
# define ONCE_UNINITED 0
70+
# define ONCE_ININIT 1
71+
# define ONCE_DONE 2
7272

7373
/*
7474
* We don't use InitOnceExecuteOnce because that isn't available in WinXP which
@@ -159,6 +159,19 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
159159
return 1;
160160
}
161161

162+
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
163+
CRYPTO_RWLOCK *lock)
164+
{
165+
*ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op;
166+
return 1;
167+
}
168+
169+
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
170+
{
171+
*ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0);
172+
return 1;
173+
}
174+
162175
int openssl_init_fork_handlers(void)
163176
{
164177
return 0;

include/openssl/crypto.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
8686
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
8787

8888
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
89+
int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
90+
CRYPTO_RWLOCK *lock);
91+
int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
8992

9093
/* No longer needed, so this is a no-op */
9194
#define OPENSSL_malloc_init() while(0) continue

util/libcrypto.num

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5284,3 +5284,5 @@ PEM_write_bio_PrivateKey_ex ? 3_0_0 EXIST::FUNCTION:
52845284
PEM_write_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION:STDIO
52855285
PEM_write_bio_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION:
52865286
EVP_PKEY_get_group_name ? 3_0_0 EXIST::FUNCTION:
5287+
CRYPTO_atomic_or ? 3_0_0 EXIST::FUNCTION:
5288+
CRYPTO_atomic_load ? 3_0_0 EXIST::FUNCTION:

0 commit comments

Comments
 (0)