cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

once.h (1934B)


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