1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_ONCE_H 2 #ifndef _LINUX_ONCE_H 3 #define _LINUX_ONCE_H 3 #define _LINUX_ONCE_H 4 4 5 #include <linux/types.h> 5 #include <linux/types.h> 6 #include <linux/jump_label.h> 6 #include <linux/jump_label.h> 7 7 8 /* Helpers used from arbitrary contexts. << 9 * Hard irqs are blocked, be cautious. << 10 */ << 11 bool __do_once_start(bool *done, unsigned long 8 bool __do_once_start(bool *done, unsigned long *flags); 12 void __do_once_done(bool *done, struct static_ 9 void __do_once_done(bool *done, struct static_key_true *once_key, 13 unsigned long *flags, stru !! 10 unsigned long *flags); 14 << 15 /* Variant for process contexts only. */ << 16 bool __do_once_sleepable_start(bool *done); << 17 void __do_once_sleepable_done(bool *done, stru << 18 struct module *m << 19 11 20 /* Call a function exactly once. The idea of D 12 /* Call a function exactly once. The idea of DO_ONCE() is to perform 21 * a function call such as initialization of r 13 * a function call such as initialization of random seeds, etc, only 22 * once, where DO_ONCE() can live in the fast- 14 * once, where DO_ONCE() can live in the fast-path. After @func has 23 * been called with the passed arguments, the 15 * been called with the passed arguments, the static key will patch 24 * out the condition into a nop. DO_ONCE() gua 16 * out the condition into a nop. DO_ONCE() guarantees type safety of 25 * arguments! 17 * arguments! 26 * 18 * 27 * Note that the following is not equivalent . !! 19 * Not that the following is not equivalent ... 28 * 20 * 29 * DO_ONCE(func, arg); 21 * DO_ONCE(func, arg); 30 * DO_ONCE(func, arg); 22 * DO_ONCE(func, arg); 31 * 23 * 32 * ... to this version: 24 * ... to this version: 33 * 25 * 34 * void foo(void) 26 * void foo(void) 35 * { 27 * { 36 * DO_ONCE(func, arg); 28 * DO_ONCE(func, arg); 37 * } 29 * } 38 * 30 * 39 * foo(); 31 * foo(); 40 * foo(); 32 * foo(); 41 * 33 * 42 * In case the one-time invocation could be tr 34 * In case the one-time invocation could be triggered from multiple 43 * places, then a common helper function must 35 * places, then a common helper function must be defined, so that only 44 * a single static key will be placed there! 36 * a single static key will be placed there! 45 */ 37 */ 46 #define DO_ONCE(func, ...) 38 #define DO_ONCE(func, ...) \ 47 ({ 39 ({ \ 48 bool ___ret = false; 40 bool ___ret = false; \ 49 static bool __section(".data.o !! 41 static bool ___done = false; \ 50 static DEFINE_STATIC_KEY_TRUE( 42 static DEFINE_STATIC_KEY_TRUE(___once_key); \ 51 if (static_branch_unlikely(&__ 43 if (static_branch_unlikely(&___once_key)) { \ 52 unsigned long ___flags 44 unsigned long ___flags; \ 53 ___ret = __do_once_sta 45 ___ret = __do_once_start(&___done, &___flags); \ 54 if (unlikely(___ret)) 46 if (unlikely(___ret)) { \ 55 func(__VA_ARGS 47 func(__VA_ARGS__); \ 56 __do_once_done 48 __do_once_done(&___done, &___once_key, \ 57 !! 49 &___flags); \ 58 } 50 } \ 59 } 51 } \ 60 ___ret; 52 ___ret; \ 61 }) 53 }) 62 54 63 /* Variant of DO_ONCE() for process/sleepable << 64 #define DO_ONCE_SLEEPABLE(func, ...) << 65 ({ << 66 bool ___ret = false; << 67 static bool __section(".data.o << 68 static DEFINE_STATIC_KEY_TRUE( << 69 if (static_branch_unlikely(&__ << 70 ___ret = __do_once_sle << 71 if (unlikely(___ret)) << 72 func(__VA_ARGS << 73 __do_once_slee << 74 << 75 } << 76 } << 77 ___ret; << 78 }) << 79 << 80 #define get_random_once(buf, nbytes) 55 #define get_random_once(buf, nbytes) \ 81 DO_ONCE(get_random_bytes, (buf), (nbyt 56 DO_ONCE(get_random_bytes, (buf), (nbytes)) 82 !! 57 #define get_random_once_wait(buf, nbytes) \ 83 #define get_random_sleepable_once(buf, nbytes) !! 58 DO_ONCE(get_random_bytes_wait, (buf), (nbytes)) \ 84 DO_ONCE_SLEEPABLE(get_random_bytes, (b << 85 59 86 #endif /* _LINUX_ONCE_H */ 60 #endif /* _LINUX_ONCE_H */ 87 61
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.