Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _LINUX_ONCE_H
0003 #define _LINUX_ONCE_H
0004 
0005 #include <linux/types.h>
0006 #include <linux/jump_label.h>
0007 
0008 bool __do_once_start(bool *done, unsigned long *flags);
0009 void __do_once_done(bool *done, struct static_key_true *once_key,
0010             unsigned long *flags, struct module *mod);
0011 
0012 /* Call a function exactly once. The idea of DO_ONCE() is to perform
0013  * a function call such as initialization of random seeds, etc, only
0014  * once, where DO_ONCE() can live in the fast-path. After @func has
0015  * been called with the passed arguments, the static key will patch
0016  * out the condition into a nop. DO_ONCE() guarantees type safety of
0017  * arguments!
0018  *
0019  * Note that the following is not equivalent ...
0020  *
0021  *   DO_ONCE(func, arg);
0022  *   DO_ONCE(func, arg);
0023  *
0024  * ... to this version:
0025  *
0026  *   void foo(void)
0027  *   {
0028  *     DO_ONCE(func, arg);
0029  *   }
0030  *
0031  *   foo();
0032  *   foo();
0033  *
0034  * In case the one-time invocation could be triggered from multiple
0035  * places, then a common helper function must be defined, so that only
0036  * a single static key will be placed there!
0037  */
0038 #define DO_ONCE(func, ...)                           \
0039     ({                                   \
0040         bool ___ret = false;                         \
0041         static bool __section(".data.once") ___done = false;         \
0042         static DEFINE_STATIC_KEY_TRUE(___once_key);          \
0043         if (static_branch_unlikely(&___once_key)) {          \
0044             unsigned long ___flags;                  \
0045             ___ret = __do_once_start(&___done, &___flags);       \
0046             if (unlikely(___ret)) {                  \
0047                 func(__VA_ARGS__);               \
0048                 __do_once_done(&___done, &___once_key,       \
0049                            &___flags, THIS_MODULE);      \
0050             }                            \
0051         }                                \
0052         ___ret;                              \
0053     })
0054 
0055 #define get_random_once(buf, nbytes)                         \
0056     DO_ONCE(get_random_bytes, (buf), (nbytes))
0057 
0058 #endif /* _LINUX_ONCE_H */