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 - OpenSSL thread support 9 10=head1 SYNOPSIS 11 12 #include <openssl/crypto.h> 13 14 CRYPTO_ONCE CRYPTO_ONCE_STATIC_INIT; 15 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)); 16 17 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void); 18 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock); 19 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock); 20 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock); 21 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); 22 23 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); 24 25=head1 DESCRIPTION 26 27OpenSSL can be safely used in multi-threaded applications provided that 28support for the underlying OS threading API is built-in. Currently, OpenSSL 29supports the pthread and Windows APIs. OpenSSL can also be built without 30any multi-threading support, for example on platforms that don't provide 31any threading support or that provide a threading API that is not yet 32supported by OpenSSL. 33 34The following multi-threading function are provided: 35 36=over 2 37 38=item * 39 40CRYPTO_THREAD_run_once() can be used to perform one-time initialization. 41The B<once> argument must be a pointer to a static object of type 42B<CRYPTO_ONCE> that was statically initialized to the value 43B<CRYPTO_ONCE_STATIC_INIT>. 44The B<init> argument is a pointer to a function that performs the desired 45exactly once initialization. 46In particular, this can be used to allocate locks in a thread-safe manner, 47which can then be used with the locking functions below. 48 49=item * 50 51CRYPTO_THREAD_lock_new() allocates, initializes and returns a new read/write 52lock. 53 54=item * 55 56CRYPTO_THREAD_read_lock() locks the provided B<lock> for reading. 57 58=item * 59 60CRYPTO_THREAD_write_lock() locks the provided B<lock> for writing. 61 62=item * 63 64CRYPTO_THREAD_unlock() unlocks the previously locked B<lock>. 65 66=item * 67 68CRYPTO_THREAD_lock_free() frees the provided B<lock>. 69 70=item * 71 72CRYPTO_atomic_add() atomically adds B<amount> to B<val> and returns the 73result of the operation in B<ret>. B<lock> will be locked, unless atomic 74operations are supported on the specific platform. Because of this, if a 75variable is modified by CRYPTO_atomic_add() then CRYPTO_atomic_add() must 76be the only way that the variable is modified. 77 78=back 79 80=head1 RETURN VALUES 81 82CRYPTO_THREAD_run_once() returns 1 on success, or 0 on error. 83 84CRYPTO_THREAD_lock_new() returns the allocated lock, or NULL on error. 85 86CRYPTO_THREAD_lock_free() returns no value. 87 88The other functions return 1 on success, or 0 on error. 89 90=head1 NOTES 91 92On Windows platforms the CRYPTO_THREAD_* types and functions in the 93openssl/crypto.h header are dependent on some of the types customarily 94made available by including windows.h. The application developer is 95likely to require control over when the latter is included, commonly as 96one of the first included headers. Therefore, it is defined as an 97application developer's responsibility to include windows.h prior to 98crypto.h where use of CRYPTO_THREAD_* types and functions is required. 99 100=head1 EXAMPLES 101 102This example safely initializes and uses a lock. 103 104 #ifdef _WIN32 105 # include <windows.h> 106 #endif 107 #include <openssl/crypto.h> 108 109 static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT; 110 static CRYPTO_RWLOCK *lock; 111 112 static void myinit(void) 113 { 114 lock = CRYPTO_THREAD_lock_new(); 115 } 116 117 static int mylock(void) 118 { 119 if (!CRYPTO_THREAD_run_once(&once, void init) || lock == NULL) 120 return 0; 121 return CRYPTO_THREAD_write_lock(lock); 122 } 123 124 static int myunlock(void) 125 { 126 return CRYPTO_THREAD_unlock(lock); 127 } 128 129 int serialized(void) 130 { 131 int ret = 0; 132 133 if (mylock()) { 134 /* Your code here, do not return without releasing the lock! */ 135 ret = ... ; 136 } 137 myunlock(); 138 return ret; 139 } 140 141Finalization of locks is an advanced topic, not covered in this example. 142This can only be done at process exit or when a dynamically loaded library is 143no longer in use and is unloaded. 144The simplest solution is to just "leak" the lock in applications and not 145repeatedly load/unload shared libraries that allocate locks. 146 147=head1 NOTES 148 149You can find out if OpenSSL was configured with thread support: 150 151 #include <openssl/opensslconf.h> 152 #if defined(OPENSSL_THREADS) 153 /* thread support enabled */ 154 #else 155 /* no thread support */ 156 #endif 157 158=head1 SEE ALSO 159 160L<crypto(7)> 161 162=head1 COPYRIGHT 163 164Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. 165 166Licensed under the OpenSSL license (the "License"). You may not use 167this file except in compliance with the License. You can obtain a copy 168in the file LICENSE in the source distribution or at 169L<https://www.openssl.org/source/license.html>. 170 171=cut 172