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