.. | .. |
---|
5 | 5 | #include <linux/types.h> |
---|
6 | 6 | #include <linux/jump_label.h> |
---|
7 | 7 | |
---|
| 8 | +/* Helpers used from arbitrary contexts. |
---|
| 9 | + * Hard irqs are blocked, be cautious. |
---|
| 10 | + */ |
---|
8 | 11 | bool __do_once_start(bool *done, unsigned long *flags); |
---|
9 | 12 | void __do_once_done(bool *done, struct static_key_true *once_key, |
---|
10 | | - unsigned long *flags, struct module *mod); |
---|
| 13 | + unsigned long *flags); |
---|
| 14 | + |
---|
| 15 | +/* Variant for process contexts only. */ |
---|
| 16 | +bool __do_once_slow_start(bool *done); |
---|
| 17 | +void __do_once_slow_done(bool *done, struct static_key_true *once_key, |
---|
| 18 | + struct module *mod); |
---|
11 | 19 | |
---|
12 | 20 | /* Call a function exactly once. The idea of DO_ONCE() is to perform |
---|
13 | 21 | * a function call such as initialization of random seeds, etc, only |
---|
.. | .. |
---|
46 | 54 | if (unlikely(___ret)) { \ |
---|
47 | 55 | func(__VA_ARGS__); \ |
---|
48 | 56 | __do_once_done(&___done, &___once_key, \ |
---|
49 | | - &___flags, THIS_MODULE); \ |
---|
| 57 | + &___flags); \ |
---|
| 58 | + } \ |
---|
| 59 | + } \ |
---|
| 60 | + ___ret; \ |
---|
| 61 | + }) |
---|
| 62 | + |
---|
| 63 | +/* Variant of DO_ONCE() for process/sleepable contexts. */ |
---|
| 64 | +#define DO_ONCE_SLOW(func, ...) \ |
---|
| 65 | + ({ \ |
---|
| 66 | + bool ___ret = false; \ |
---|
| 67 | + static bool __section(".data.once") ___done = false; \ |
---|
| 68 | + static DEFINE_STATIC_KEY_TRUE(___once_key); \ |
---|
| 69 | + if (static_branch_unlikely(&___once_key)) { \ |
---|
| 70 | + ___ret = __do_once_slow_start(&___done); \ |
---|
| 71 | + if (unlikely(___ret)) { \ |
---|
| 72 | + func(__VA_ARGS__); \ |
---|
| 73 | + __do_once_slow_done(&___done, &___once_key, \ |
---|
| 74 | + THIS_MODULE); \ |
---|
50 | 75 | } \ |
---|
51 | 76 | } \ |
---|
52 | 77 | ___ret; \ |
---|
.. | .. |
---|
57 | 82 | #define get_random_once_wait(buf, nbytes) \ |
---|
58 | 83 | DO_ONCE(get_random_bytes_wait, (buf), (nbytes)) \ |
---|
59 | 84 | |
---|
| 85 | +#define get_random_slow_once(buf, nbytes) \ |
---|
| 86 | + DO_ONCE_SLOW(get_random_bytes, (buf), (nbytes)) |
---|
| 87 | + |
---|
60 | 88 | #endif /* _LINUX_ONCE_H */ |
---|