]> git.ipfire.org Git - thirdparty/openssl.git/blob - doc/internal/man3/ossl_rcu_lock_new.pod
Copyright year updates
[thirdparty/openssl.git] / doc / internal / man3 / ossl_rcu_lock_new.pod
1 =pod
2
3 =head1 NAME
4
5 ossl_rcu_lock_new,
6 ossl_rcu_lock_free, ossl_rcu_read_lock,
7 ossl_rcu_read_unlock, ossl_rcu_write_lock,
8 ossl_rcu_write_unlock, ossl_synchronize_rcu,
9 ossl_rcu_call, ossl_rcu_deref,
10 ossl_rcu_assign_ptr, ossl_rcu_uptr_deref,
11 ossl_rcu_assign_uptr
12 - perform read-copy-update locking
13
14 =head1 SYNOPSIS
15
16 CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers);
17 void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock);
18 void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock);
19 void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock);
20 void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock);
21 void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock);
22 void ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data);
23 void *ossl_rcu_deref(void **p);
24 void ossl_rcu_uptr_deref(void **p);
25 void ossl_rcu_assign_ptr(void **p, void **v);
26 void ossl_rcu_assign_uptr(void **p, void **v);
27 void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock);
28
29 =head1 DESCRIPTION
30
31 OpenSSL can be safely used in multi-threaded applications provided that
32 support for the underlying OS threading API is built-in. Currently, OpenSSL
33 supports the pthread and Windows APIs. OpenSSL can also be built without
34 any multi-threading support, for example on platforms that don't provide
35 any threading support or that provide a threading API that is not yet
36 supported by OpenSSL.
37
38 In addition to more traditional Read/Write locks, OpenSSL provides
39 Read-Copy-Update (RCU) locks, which allow for always nonblocking read paths.
40
41 The following multi-threading functions are provided:
42
43 =over 2
44
45 =item *
46
47 ossl_rcu_assign_uptr() assigns the value pointed to by v to the
48 location pointed to by p. This function should typically not be used, rely
49 instead on the ossl_rcu_assign_ptr() macro.
50
51 =item *
52
53 ossl_rcu_uptr_deref() returns the value stored at the
54 location pointed to by p. This function should typically not be used, rely
55 instead on the ossl_rcu_deref() macro.
56
57 =item *
58
59 ossl_rcu_assign_ptr() assigns the value pointed to by v to
60 location pointed to by p.
61
62 =item *
63
64 ossl_rcu_lock_new() allocates a new RCU lock. The I<num_writers> param
65 indicates the number of write side threads which may execute
66 ossl_synchronize_rcu() in parallel. The value must be at least 1, but may be
67 larger to obtain increased write side throughput at the cost of additional
68 internal memory usage. A value of 1 is generally recommended.
69
70 =item *
71
72 ossl_rcu_read_lock() acquires a read side hold on data protected by
73 the lock.
74
75 =item *
76
77 ossl_rcu_read_unlock() releases a read side hold on data protected by
78 the lock.
79
80 =item *
81
82 ossl_rcu_write_lock() acquires a write side hold on data protected by
83 the lock. Note only one writer per lock is permitted, as with read/write locks.
84
85 =item *
86
87 ossl_rcu_write_unlock() releases a write side hold on data protected
88 by the lock.
89
90 =item *
91
92 ossl_synchronize_rcu() blocks the calling thread until all read side
93 holds on the lock have been released, guaranteeing that any old data updated by
94 the write side thread is safe to free.
95
96 =item *
97
98 ossl_rcu_call() enqueues a callback function to the lock, to be called
99 when the next synchronization completes. Note: It is not guaranteed that the
100 thread which enqueued the callback will be the thread which executes the
101 callback
102
103 =item *
104
105 ossl_rcu_deref(p) atomically reads a pointer under an RCU locks
106 protection
107
108 =item *
109
110 ossl_rcu_assign_ptr(p,v) atomically writes to a pointer under an
111 RCU locks protection
112
113 =item *
114
115 ossl_rcu_lock_free() frees an allocated RCU lock
116
117 =back
118
119 =head1 RETURN VALUES
120
121 ossl_rcu_lock_new() returns a pointer to a newly created RCU lock structure.
122
123 ossl_rcu_deref() and ossl_rcu_uptr_deref() return the value pointed
124 to by the passed in value v.
125
126 All other functions return no value.
127
128 =head1 EXAMPLES
129
130 You can find out if OpenSSL was configured with thread support:
131
132 #include <openssl/opensslconf.h>
133 #if defined(OPENSSL_THREADS)
134 /* thread support enabled */
135 #else
136 /* no thread support */
137 #endif
138
139 This example safely initializes and uses a lock.
140
141 #include "internal/rcu.h"
142
143 struct foo {
144 int aval;
145 char *name;
146 };
147
148 static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT;
149 static CRYPTO_RCU_LOCK *lock;
150 static struct foo *fooptr = NULL;
151
152 static void myinit(void)
153 {
154 lock = ossl_rcu_lock_new(1);
155 }
156
157 static int initlock(void)
158 {
159 if (!RUN_ONCE(&once, myinit) || lock == NULL)
160 return 0;
161 return 1;
162 }
163
164 static void writer_thread()
165 {
166 struct foo *newfoo;
167 struct foo *oldfoo;
168
169 initlock();
170
171 /*
172 * update steps in an rcu model
173 */
174
175 /*
176 * 1) create a new shared object
177 */
178 newfoo = OPENSSL_zalloc(sizeof(struct foo));
179
180 /*
181 * acquire the write side lock
182 */
183 ossl_rcu_write_lock(lock);
184
185 /*
186 * 2) read the old pointer
187 */
188 oldfoo = ossl_rcu_deref(&fooptr);
189
190 /*
191 * 3) Copy the old pointer to the new object, and
192 * make any needed adjustments
193 */
194 memcpy(newfoo, oldfoo, sizeof(struct foo));
195 newfoo->aval++;
196
197 /*
198 * 4) Update the shared pointer to the new value
199 */
200 ossl_rcu_assign_ptr(&fooptr, &newfoo);
201
202 /*
203 * 5) Release the write side lock
204 */
205 ossl_rcu_write_unlock(lock);
206
207 /*
208 * 6) wait for any read side holds on the old data
209 * to be released
210 */
211 ossl_synchronize_rcu(lock);
212
213 /*
214 * 7) free the old pointer, now that there are no
215 * further readers
216 */
217 OPENSSL_free(oldfoo);
218 }
219
220 static void reader_thread()
221 {
222 struct foo *myfoo = NULL;
223 int a;
224 /*
225 * 1) Acquire a read side hold on the shared data
226 */
227 ossl_rcu_read_lock(lock);
228
229 /*
230 * 2) Access the shared data pointer
231 */
232 myfoo = ossl_rcu_deref(&fooptr);
233
234 /*
235 * 3) Read the data from the pointer
236 */
237 a = myfoo->aval;
238
239 /*
240 * 4) Indicate our hold on the shared data is complete
241 */
242 ossl_rcu_read_unlock(lock);
243 }
244
245 =head1 SEE ALSO
246
247 L<crypto(7)>, L<openssl-threads(7)>.
248
249 =head1 COPYRIGHT
250
251 Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
252
253 Licensed under the Apache License 2.0 (the "License"). You may not use
254 this file except in compliance with the License. You can obtain a copy
255 in the file LICENSE in the source distribution or at
256 L<https://www.openssl.org/source/license.html>.
257
258 =cut