1=pod
2
3=head1 NAME
4
5CRYPTO_THREAD_run_once,
6CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock,
7CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free,
8CRYPTO_atomic_add, CRYPTO_atomic_add64, CRYPTO_atomic_and, CRYPTO_atomic_or,
9CRYPTO_atomic_load, CRYPTO_atomic_store, CRYPTO_atomic_load_int,
10OSSL_set_max_threads, OSSL_get_max_threads,
11OSSL_get_thread_support_flags, OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL,
12OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN - OpenSSL thread support
13
14=head1 SYNOPSIS
15
16 #include <openssl/crypto.h>
17
18 CRYPTO_ONCE CRYPTO_ONCE_STATIC_INIT;
19 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void));
20
21 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
22 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
23 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
24 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
25 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
26
27 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
28 int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret,
29                         CRYPTO_RWLOCK *lock);
30 int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret,
31                       CRYPTO_RWLOCK *lock);
32 int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
33                      CRYPTO_RWLOCK *lock);
34 int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
35 int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock);
36 int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock);
37
38 int OSSL_set_max_threads(OSSL_LIB_CTX *ctx, uint64_t max_threads);
39 uint64_t OSSL_get_max_threads(OSSL_LIB_CTX *ctx);
40 uint32_t OSSL_get_thread_support_flags(void);
41
42 #define OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL
43 #define OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN
44
45=head1 DESCRIPTION
46
47OpenSSL can be safely used in multi-threaded applications provided that
48support for the underlying OS threading API is built-in. Currently, OpenSSL
49supports the pthread and Windows APIs. OpenSSL can also be built without
50any multi-threading support, for example on platforms that don't provide
51any threading support or that provide a threading API that is not yet
52supported by OpenSSL.
53
54The following multi-threading function are provided:
55
56=over 2
57
58=item *
59
60CRYPTO_THREAD_run_once() can be used to perform one-time initialization.
61The I<once> argument must be a pointer to a static object of type
62B<CRYPTO_ONCE> that was statically initialized to the value
63B<CRYPTO_ONCE_STATIC_INIT>.
64The I<init> argument is a pointer to a function that performs the desired
65exactly once initialization.
66In particular, this can be used to allocate locks in a thread-safe manner,
67which can then be used with the locking functions below.
68
69=item *
70
71CRYPTO_THREAD_lock_new() allocates, initializes and returns a new read/write
72lock.
73
74=item *
75
76CRYPTO_THREAD_read_lock() locks the provided I<lock> for reading.
77
78=item *
79
80CRYPTO_THREAD_write_lock() locks the provided I<lock> for writing.
81
82=item *
83
84CRYPTO_THREAD_unlock() unlocks the previously locked I<lock>.
85
86=item *
87
88CRYPTO_THREAD_lock_free() frees the provided I<lock>.
89If the argument is NULL, nothing is done.
90
91=item *
92
93CRYPTO_atomic_add() atomically adds I<amount> to I<*val> and returns the
94result of the operation in I<*ret>. I<lock> will be locked, unless atomic
95operations are supported on the specific platform. Because of this, if a
96variable is modified by CRYPTO_atomic_add() then CRYPTO_atomic_add() must
97be the only way that the variable is modified. If atomic operations are not
98supported and I<lock> is NULL, then the function will fail.
99
100=item *
101
102CRYPTO_atomic_add64() atomically adds I<op> to I<*val> and returns the
103result of the operation in I<*ret>. I<lock> will be locked, unless atomic
104operations are supported on the specific platform. Because of this, if a
105variable is modified by CRYPTO_atomic_add64() then CRYPTO_atomic_add64() must
106be the only way that the variable is modified. If atomic operations are not
107supported and I<lock> is NULL, then the function will fail.
108
109=item *
110
111CRYPTO_atomic_and() performs an atomic bitwise and of I<op> and I<*val> and stores
112the result back in I<*val>. It also returns the result of the operation in
113I<*ret>. I<lock> will be locked, unless atomic operations are supported on the
114specific platform. Because of this, if a variable is modified by
115CRYPTO_atomic_and() or read by CRYPTO_atomic_load() then CRYPTO_atomic_and() must
116be the only way that the variable is modified. If atomic operations are not
117supported and I<lock> is NULL, then the function will fail.
118
119=item *
120
121CRYPTO_atomic_or() performs an atomic bitwise or of I<op> and I<*val> and stores
122the result back in I<*val>. It also returns the result of the operation in
123I<*ret>. I<lock> will be locked, unless atomic operations are supported on the
124specific platform. Because of this, if a variable is modified by
125CRYPTO_atomic_or() or read by CRYPTO_atomic_load() then CRYPTO_atomic_or() must
126be the only way that the variable is modified. If atomic operations are not
127supported and I<lock> is NULL, then the function will fail.
128
129=item *
130
131CRYPTO_atomic_load() atomically loads the contents of I<*val> into I<*ret>.
132I<lock> will be locked, unless atomic operations are supported on the specific
133platform. Because of this, if a variable is modified by CRYPTO_atomic_or() or
134read by CRYPTO_atomic_load() then CRYPTO_atomic_load() must be the only way that
135the variable is read. If atomic operations are not supported and I<lock> is
136NULL, then the function will fail.
137
138=item *
139
140CRYPTO_atomic_store() atomically stores the contents of I<val> into I<*dst>.
141I<lock> will be locked, unless atomic operations are supported on the specific
142platform.
143
144=item *
145
146CRYPTO_atomic_load_int() works identically to CRYPTO_atomic_load() but operates
147on an I<int> value instead of a I<uint64_t> value.
148
149=item *
150
151OSSL_set_max_threads() sets the maximum number of threads to be used by the
152thread pool. If the argument is 0, thread pooling is disabled. OpenSSL will
153not create any threads and existing threads in the thread pool will be torn
154down. The maximum thread count is a limit, not a target. Threads will not be
155spawned unless (and until) there is demand. Thread polling is disabled by
156default. To enable threading you must call OSSL_set_max_threads() explicitly.
157Under no circumstances is this done for you.
158
159=item *
160
161OSSL_get_thread_support_flags() determines what thread pool functionality
162OpenSSL is compiled with and is able to support in the current run time
163environment. B<OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL> indicates that the base
164thread pool functionality is available, and
165B<OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN> indicates that the default thread pool
166model is available. The default thread pool model is currently the only model
167available, therefore both of these flags must be set for thread pool
168functionality to be used.
169
170=back
171
172=head1 RETURN VALUES
173
174CRYPTO_THREAD_run_once() returns 1 on success, or 0 on error.
175
176CRYPTO_THREAD_lock_new() returns the allocated lock, or NULL on error.
177
178CRYPTO_THREAD_lock_free() returns no value.
179
180OSSL_set_max_threads() returns 1 on success and 0 on failure. Returns failure
181if OpenSSL-managed thread pooling is not supported (for example, if it is not
182supported on the current platform, or because OpenSSL is not built with the
183necessary support).
184
185OSSL_get_max_threads() returns the maximum number of threads currently allowed
186to be used by the thread pool. If thread pooling is disabled or not available,
187returns 0.
188
189OSSL_get_thread_support_flags() returns zero or more B<OSSL_THREAD_SUPPORT_FLAG>
190values.
191
192The other functions return 1 on success, or 0 on error.
193
194=head1 NOTES
195
196On Windows platforms the CRYPTO_THREAD_* types and functions in the
197F<< <openssl/crypto.h> >> header are dependent on some of the types
198customarily made available by including F<< <windows.h> >>. The application
199developer is likely to require control over when the latter is included,
200commonly as one of the first included headers. Therefore, it is defined as an
201application developer's responsibility to include F<< <windows.h> >> prior to
202F<< <openssl/crypto.h> >> where use of CRYPTO_THREAD_* types and functions is
203required.
204
205=head1 EXAMPLES
206
207You can find out if OpenSSL was configured with thread support:
208
209 #include <openssl/opensslconf.h>
210 #if defined(OPENSSL_THREADS)
211     /* thread support enabled */
212 #else
213     /* no thread support */
214 #endif
215
216This example safely initializes and uses a lock.
217
218 #ifdef _WIN32
219 # include <windows.h>
220 #endif
221 #include <openssl/crypto.h>
222
223 static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT;
224 static CRYPTO_RWLOCK *lock;
225
226 static void myinit(void)
227 {
228     lock = CRYPTO_THREAD_lock_new();
229 }
230
231 static int mylock(void)
232 {
233     if (!CRYPTO_THREAD_run_once(&once, void init) || lock == NULL)
234         return 0;
235     return CRYPTO_THREAD_write_lock(lock);
236 }
237
238 static int myunlock(void)
239 {
240     return CRYPTO_THREAD_unlock(lock);
241 }
242
243 int serialized(void)
244 {
245     int ret = 0;
246
247     if (!mylock()) {
248        /* Do not unlock unless the lock was successfully acquired. */
249        return 0;
250     }
251
252     /* Your code here, do not return without releasing the lock! */
253     ret = ... ;
254     myunlock();
255     return ret;
256 }
257
258Finalization of locks is an advanced topic, not covered in this example.
259This can only be done at process exit or when a dynamically loaded library is
260no longer in use and is unloaded.
261The simplest solution is to just "leak" the lock in applications and not
262repeatedly load/unload shared libraries that allocate locks.
263
264=head1 SEE ALSO
265
266L<crypto(7)>, L<openssl-threads(7)>.
267
268=head1 HISTORY
269
270CRYPTO_atomic_store() was added in OpenSSL 3.4.0
271
272=head1 COPYRIGHT
273
274Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
275
276Licensed under the Apache License 2.0 (the "License").  You may not use
277this file except in compliance with the License.  You can obtain a copy
278in the file LICENSE in the source distribution or at
279L<https://www.openssl.org/source/license.html>.
280
281=cut
282