1 /* 2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 #ifndef OSSL_INTERNAL_THREAD_ONCE_H 11 # define OSSL_INTERNAL_THREAD_ONCE_H 12 # pragma once 13 14 # include <openssl/crypto.h> 15 16 /* 17 * Initialisation of global data should never happen via "RUN_ONCE" inside the 18 * FIPS module. Global data should instead always be associated with a specific 19 * OSSL_LIB_CTX object. In this way data will get cleaned up correctly when the 20 * module gets unloaded. 21 */ 22 # if !defined(FIPS_MODULE) || defined(ALLOW_RUN_ONCE_IN_FIPS) 23 /* 24 * DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly 25 * once. It takes no arguments and returns an int result (1 for success or 26 * 0 for failure). Typical usage might be: 27 * 28 * DEFINE_RUN_ONCE(myinitfunc) 29 * { 30 * do_some_initialisation(); 31 * if (init_is_successful()) 32 * return 1; 33 * 34 * return 0; 35 * } 36 */ 37 # define DEFINE_RUN_ONCE(init) \ 38 static int init(void); \ 39 int init##_ossl_ret_ = 0; \ 40 void init##_ossl_(void) \ 41 { \ 42 init##_ossl_ret_ = init(); \ 43 } \ 44 static int init(void) 45 46 /* 47 * DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly 48 * once that has been defined in another file via DEFINE_RUN_ONCE(). 49 */ 50 # define DECLARE_RUN_ONCE(init) \ 51 extern int init##_ossl_ret_; \ 52 void init##_ossl_(void); 53 54 /* 55 * DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run 56 * exactly once. This function will be declared as static within the file. It 57 * takes no arguments and returns an int result (1 for success or 0 for 58 * failure). Typical usage might be: 59 * 60 * DEFINE_RUN_ONCE_STATIC(myinitfunc) 61 * { 62 * do_some_initialisation(); 63 * if (init_is_successful()) 64 * return 1; 65 * 66 * return 0; 67 * } 68 */ 69 # define DEFINE_RUN_ONCE_STATIC(init) \ 70 static int init(void); \ 71 static int init##_ossl_ret_ = 0; \ 72 static void init##_ossl_(void) \ 73 { \ 74 init##_ossl_ret_ = init(); \ 75 } \ 76 static int init(void) 77 78 /* 79 * DEFINE_RUN_ONCE_STATIC_ALT: Define an alternative initialiser function. This 80 * function will be declared as static within the file. It takes no arguments 81 * and returns an int result (1 for success or 0 for failure). An alternative 82 * initialiser function is expected to be associated with a primary initialiser 83 * function defined via DEFINE_ONCE_STATIC where both functions use the same 84 * CRYPTO_ONCE object to synchronise. Where an alternative initialiser function 85 * is used only one of the primary or the alternative initialiser function will 86 * ever be called - and that function will be called exactly once. Definition 87 * of an alternative initialiser function MUST occur AFTER the definition of the 88 * primary initialiser function. 89 * 90 * Typical usage might be: 91 * 92 * DEFINE_RUN_ONCE_STATIC(myinitfunc) 93 * { 94 * do_some_initialisation(); 95 * if (init_is_successful()) 96 * return 1; 97 * 98 * return 0; 99 * } 100 * 101 * DEFINE_RUN_ONCE_STATIC_ALT(myaltinitfunc, myinitfunc) 102 * { 103 * do_some_alternative_initialisation(); 104 * if (init_is_successful()) 105 * return 1; 106 * 107 * return 0; 108 * } 109 */ 110 # define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \ 111 static int initalt(void); \ 112 static void initalt##_ossl_(void) \ 113 { \ 114 init##_ossl_ret_ = initalt(); \ 115 } \ 116 static int initalt(void) 117 118 /* 119 * RUN_ONCE - use CRYPTO_THREAD_run_once, and check if the init succeeded 120 * @once: pointer to static object of type CRYPTO_ONCE 121 * @init: function name that was previously given to DEFINE_RUN_ONCE, 122 * DEFINE_RUN_ONCE_STATIC or DECLARE_RUN_ONCE. This function 123 * must return 1 for success or 0 for failure. 124 * 125 * The return value is 1 on success (*) or 0 in case of error. 126 * 127 * (*) by convention, since the init function must return 1 on success. 128 */ 129 # define RUN_ONCE(once, init) \ 130 (CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0) 131 132 /* 133 * RUN_ONCE_ALT - use CRYPTO_THREAD_run_once, to run an alternative initialiser 134 * function and check if that initialisation succeeded 135 * @once: pointer to static object of type CRYPTO_ONCE 136 * @initalt: alternative initialiser function name that was previously given to 137 * DEFINE_RUN_ONCE_STATIC_ALT. This function must return 1 for 138 * success or 0 for failure. 139 * @init: primary initialiser function name that was previously given to 140 * DEFINE_RUN_ONCE_STATIC. This function must return 1 for success or 141 * 0 for failure. 142 * 143 * The return value is 1 on success (*) or 0 in case of error. 144 * 145 * (*) by convention, since the init function must return 1 on success. 146 */ 147 # define RUN_ONCE_ALT(once, initalt, init) \ 148 (CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0) 149 150 # endif /* FIPS_MODULE */ 151 #endif /* OSSL_INTERNAL_THREAD_ONCE_H */ 152