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