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