brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 153bbf8 Raw
87 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef _LINUX_ONCE_H3#define _LINUX_ONCE_H4 5#include <linux/types.h>6#include <linux/jump_label.h>7 8/* Helpers used from arbitrary contexts.9 * Hard irqs are blocked, be cautious.10 */11bool __do_once_start(bool *done, unsigned long *flags);12void __do_once_done(bool *done, struct static_key_true *once_key,13		    unsigned long *flags, struct module *mod) HWJS_SUSPENDS;14 15/* Variant for process contexts only. */16bool __do_once_sleepable_start(bool *done) HWJS_SUSPENDS;17void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,18			      struct module *mod) HWJS_SUSPENDS;19 20/* Call a function exactly once. The idea of DO_ONCE() is to perform21 * a function call such as initialization of random seeds, etc, only22 * once, where DO_ONCE() can live in the fast-path. After @func has23 * been called with the passed arguments, the static key will patch24 * out the condition into a nop. DO_ONCE() guarantees type safety of25 * arguments!26 *27 * Note that the following is not equivalent ...28 *29 *   DO_ONCE(func, arg);30 *   DO_ONCE(func, arg);31 *32 * ... to this version:33 *34 *   void foo(void)35 *   {36 *     DO_ONCE(func, arg);37 *   }38 *39 *   foo();40 *   foo();41 *42 * In case the one-time invocation could be triggered from multiple43 * places, then a common helper function must be defined, so that only44 * a single static key will be placed there!45 */46#define DO_ONCE(func, ...)						     \47	({								     \48		bool ___ret = false;					     \49		static bool __section(".data.once") ___done = false;	     \50		static DEFINE_STATIC_KEY_TRUE(___once_key);		     \51		if (static_branch_unlikely(&___once_key)) {		     \52			unsigned long ___flags;				     \53			___ret = __do_once_start(&___done, &___flags);	     \54			if (unlikely(___ret)) {				     \55				func(__VA_ARGS__);			     \56				__do_once_done(&___done, &___once_key,	     \57					       &___flags, THIS_MODULE);	     \58			}						     \59		}							     \60		___ret;							     \61	})62 63/* Variant of DO_ONCE() for process/sleepable contexts. */64#define DO_ONCE_SLEEPABLE(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_sleepable_start(&___done);		\71			if (unlikely(___ret)) {					\72				func(__VA_ARGS__);				\73				__do_once_sleepable_done(&___done, &___once_key,\74						    THIS_MODULE);		\75			}							\76		}								\77		___ret;								\78	})79 80#define get_random_once(buf, nbytes)					     \81	DO_ONCE(get_random_bytes, (buf), (nbytes))82 83#define get_random_sleepable_once(buf, nbytes)				     \84	DO_ONCE_SLEEPABLE(get_random_bytes, (buf), (nbytes))85 86#endif /* _LINUX_ONCE_H */87