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