once.h 1.8 KB

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