]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - include/linux/once.h
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[karo-tx-linux.git] / include / linux / once.h
1 #ifndef _LINUX_ONCE_H
2 #define _LINUX_ONCE_H
3
4 #include <linux/types.h>
5 #include <linux/jump_label.h>
6
7 bool __do_once_start(bool *done, unsigned long *flags);
8 void __do_once_done(bool *done, struct static_key *once_key,
9                     unsigned long *flags);
10
11 /* Call a function exactly once. The idea of DO_ONCE() is to perform
12  * a function call such as initialization of random seeds, etc, only
13  * once, where DO_ONCE() can live in the fast-path. After @func has
14  * been called with the passed arguments, the static key will patch
15  * out the condition into a nop. DO_ONCE() guarantees type safety of
16  * arguments!
17  *
18  * Not that the following is not equivalent ...
19  *
20  *   DO_ONCE(func, arg);
21  *   DO_ONCE(func, arg);
22  *
23  * ... to this version:
24  *
25  *   void foo(void)
26  *   {
27  *     DO_ONCE(func, arg);
28  *   }
29  *
30  *   foo();
31  *   foo();
32  *
33  * In case the one-time invocation could be triggered from multiple
34  * places, then a common helper function must be defined, so that only
35  * a single static key will be placed there!
36  */
37 #define DO_ONCE(func, ...)                                                   \
38         ({                                                                   \
39                 bool ___ret = false;                                         \
40                 static bool ___done = false;                                 \
41                 static struct static_key ___once_key = STATIC_KEY_INIT_TRUE; \
42                 if (static_key_true(&___once_key)) {                         \
43                         unsigned long ___flags;                              \
44                         ___ret = __do_once_start(&___done, &___flags);       \
45                         if (unlikely(___ret)) {                              \
46                                 func(__VA_ARGS__);                           \
47                                 __do_once_done(&___done, &___once_key,       \
48                                                &___flags);                   \
49                         }                                                    \
50                 }                                                            \
51                 ___ret;                                                      \
52         })
53
54 #define get_random_once(buf, nbytes)                                         \
55         DO_ONCE(get_random_bytes, (buf), (nbytes))
56
57 #endif /* _LINUX_ONCE_H */