Home | History | Annotate | Line # | Download | only in internal
      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