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

wait_bit.h (11468B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _LINUX_WAIT_BIT_H
      3#define _LINUX_WAIT_BIT_H
      4
      5/*
      6 * Linux wait-bit related types and methods:
      7 */
      8#include <linux/wait.h>
      9
     10struct wait_bit_key {
     11	void			*flags;
     12	int			bit_nr;
     13	unsigned long		timeout;
     14};
     15
     16struct wait_bit_queue_entry {
     17	struct wait_bit_key	key;
     18	struct wait_queue_entry	wq_entry;
     19};
     20
     21#define __WAIT_BIT_KEY_INITIALIZER(word, bit)					\
     22	{ .flags = word, .bit_nr = bit, }
     23
     24typedef int wait_bit_action_f(struct wait_bit_key *key, int mode);
     25
     26void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit);
     27int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode);
     28int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode);
     29void wake_up_bit(void *word, int bit);
     30int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode);
     31int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout);
     32int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode);
     33struct wait_queue_head *bit_waitqueue(void *word, int bit);
     34extern void __init wait_bit_init(void);
     35
     36int wake_bit_function(struct wait_queue_entry *wq_entry, unsigned mode, int sync, void *key);
     37
     38#define DEFINE_WAIT_BIT(name, word, bit)					\
     39	struct wait_bit_queue_entry name = {					\
     40		.key = __WAIT_BIT_KEY_INITIALIZER(word, bit),			\
     41		.wq_entry = {							\
     42			.private	= current,				\
     43			.func		= wake_bit_function,			\
     44			.entry		=					\
     45				LIST_HEAD_INIT((name).wq_entry.entry),		\
     46		},								\
     47	}
     48
     49extern int bit_wait(struct wait_bit_key *key, int mode);
     50extern int bit_wait_io(struct wait_bit_key *key, int mode);
     51extern int bit_wait_timeout(struct wait_bit_key *key, int mode);
     52extern int bit_wait_io_timeout(struct wait_bit_key *key, int mode);
     53
     54/**
     55 * wait_on_bit - wait for a bit to be cleared
     56 * @word: the word being waited on, a kernel virtual address
     57 * @bit: the bit of the word being waited on
     58 * @mode: the task state to sleep in
     59 *
     60 * There is a standard hashed waitqueue table for generic use. This
     61 * is the part of the hashtable's accessor API that waits on a bit.
     62 * For instance, if one were to have waiters on a bitflag, one would
     63 * call wait_on_bit() in threads waiting for the bit to clear.
     64 * One uses wait_on_bit() where one is waiting for the bit to clear,
     65 * but has no intention of setting it.
     66 * Returned value will be zero if the bit was cleared, or non-zero
     67 * if the process received a signal and the mode permitted wakeup
     68 * on that signal.
     69 */
     70static inline int
     71wait_on_bit(unsigned long *word, int bit, unsigned mode)
     72{
     73	might_sleep();
     74	if (!test_bit(bit, word))
     75		return 0;
     76	return out_of_line_wait_on_bit(word, bit,
     77				       bit_wait,
     78				       mode);
     79}
     80
     81/**
     82 * wait_on_bit_io - wait for a bit to be cleared
     83 * @word: the word being waited on, a kernel virtual address
     84 * @bit: the bit of the word being waited on
     85 * @mode: the task state to sleep in
     86 *
     87 * Use the standard hashed waitqueue table to wait for a bit
     88 * to be cleared.  This is similar to wait_on_bit(), but calls
     89 * io_schedule() instead of schedule() for the actual waiting.
     90 *
     91 * Returned value will be zero if the bit was cleared, or non-zero
     92 * if the process received a signal and the mode permitted wakeup
     93 * on that signal.
     94 */
     95static inline int
     96wait_on_bit_io(unsigned long *word, int bit, unsigned mode)
     97{
     98	might_sleep();
     99	if (!test_bit(bit, word))
    100		return 0;
    101	return out_of_line_wait_on_bit(word, bit,
    102				       bit_wait_io,
    103				       mode);
    104}
    105
    106/**
    107 * wait_on_bit_timeout - wait for a bit to be cleared or a timeout elapses
    108 * @word: the word being waited on, a kernel virtual address
    109 * @bit: the bit of the word being waited on
    110 * @mode: the task state to sleep in
    111 * @timeout: timeout, in jiffies
    112 *
    113 * Use the standard hashed waitqueue table to wait for a bit
    114 * to be cleared. This is similar to wait_on_bit(), except also takes a
    115 * timeout parameter.
    116 *
    117 * Returned value will be zero if the bit was cleared before the
    118 * @timeout elapsed, or non-zero if the @timeout elapsed or process
    119 * received a signal and the mode permitted wakeup on that signal.
    120 */
    121static inline int
    122wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
    123		    unsigned long timeout)
    124{
    125	might_sleep();
    126	if (!test_bit(bit, word))
    127		return 0;
    128	return out_of_line_wait_on_bit_timeout(word, bit,
    129					       bit_wait_timeout,
    130					       mode, timeout);
    131}
    132
    133/**
    134 * wait_on_bit_action - wait for a bit to be cleared
    135 * @word: the word being waited on, a kernel virtual address
    136 * @bit: the bit of the word being waited on
    137 * @action: the function used to sleep, which may take special actions
    138 * @mode: the task state to sleep in
    139 *
    140 * Use the standard hashed waitqueue table to wait for a bit
    141 * to be cleared, and allow the waiting action to be specified.
    142 * This is like wait_on_bit() but allows fine control of how the waiting
    143 * is done.
    144 *
    145 * Returned value will be zero if the bit was cleared, or non-zero
    146 * if the process received a signal and the mode permitted wakeup
    147 * on that signal.
    148 */
    149static inline int
    150wait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action,
    151		   unsigned mode)
    152{
    153	might_sleep();
    154	if (!test_bit(bit, word))
    155		return 0;
    156	return out_of_line_wait_on_bit(word, bit, action, mode);
    157}
    158
    159/**
    160 * wait_on_bit_lock - wait for a bit to be cleared, when wanting to set it
    161 * @word: the word being waited on, a kernel virtual address
    162 * @bit: the bit of the word being waited on
    163 * @mode: the task state to sleep in
    164 *
    165 * There is a standard hashed waitqueue table for generic use. This
    166 * is the part of the hashtable's accessor API that waits on a bit
    167 * when one intends to set it, for instance, trying to lock bitflags.
    168 * For instance, if one were to have waiters trying to set bitflag
    169 * and waiting for it to clear before setting it, one would call
    170 * wait_on_bit() in threads waiting to be able to set the bit.
    171 * One uses wait_on_bit_lock() where one is waiting for the bit to
    172 * clear with the intention of setting it, and when done, clearing it.
    173 *
    174 * Returns zero if the bit was (eventually) found to be clear and was
    175 * set.  Returns non-zero if a signal was delivered to the process and
    176 * the @mode allows that signal to wake the process.
    177 */
    178static inline int
    179wait_on_bit_lock(unsigned long *word, int bit, unsigned mode)
    180{
    181	might_sleep();
    182	if (!test_and_set_bit(bit, word))
    183		return 0;
    184	return out_of_line_wait_on_bit_lock(word, bit, bit_wait, mode);
    185}
    186
    187/**
    188 * wait_on_bit_lock_io - wait for a bit to be cleared, when wanting to set it
    189 * @word: the word being waited on, a kernel virtual address
    190 * @bit: the bit of the word being waited on
    191 * @mode: the task state to sleep in
    192 *
    193 * Use the standard hashed waitqueue table to wait for a bit
    194 * to be cleared and then to atomically set it.  This is similar
    195 * to wait_on_bit(), but calls io_schedule() instead of schedule()
    196 * for the actual waiting.
    197 *
    198 * Returns zero if the bit was (eventually) found to be clear and was
    199 * set.  Returns non-zero if a signal was delivered to the process and
    200 * the @mode allows that signal to wake the process.
    201 */
    202static inline int
    203wait_on_bit_lock_io(unsigned long *word, int bit, unsigned mode)
    204{
    205	might_sleep();
    206	if (!test_and_set_bit(bit, word))
    207		return 0;
    208	return out_of_line_wait_on_bit_lock(word, bit, bit_wait_io, mode);
    209}
    210
    211/**
    212 * wait_on_bit_lock_action - wait for a bit to be cleared, when wanting to set it
    213 * @word: the word being waited on, a kernel virtual address
    214 * @bit: the bit of the word being waited on
    215 * @action: the function used to sleep, which may take special actions
    216 * @mode: the task state to sleep in
    217 *
    218 * Use the standard hashed waitqueue table to wait for a bit
    219 * to be cleared and then to set it, and allow the waiting action
    220 * to be specified.
    221 * This is like wait_on_bit() but allows fine control of how the waiting
    222 * is done.
    223 *
    224 * Returns zero if the bit was (eventually) found to be clear and was
    225 * set.  Returns non-zero if a signal was delivered to the process and
    226 * the @mode allows that signal to wake the process.
    227 */
    228static inline int
    229wait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action,
    230			unsigned mode)
    231{
    232	might_sleep();
    233	if (!test_and_set_bit(bit, word))
    234		return 0;
    235	return out_of_line_wait_on_bit_lock(word, bit, action, mode);
    236}
    237
    238extern void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int flags);
    239extern void wake_up_var(void *var);
    240extern wait_queue_head_t *__var_waitqueue(void *p);
    241
    242#define ___wait_var_event(var, condition, state, exclusive, ret, cmd)	\
    243({									\
    244	__label__ __out;						\
    245	struct wait_queue_head *__wq_head = __var_waitqueue(var);	\
    246	struct wait_bit_queue_entry __wbq_entry;			\
    247	long __ret = ret; /* explicit shadow */				\
    248									\
    249	init_wait_var_entry(&__wbq_entry, var,				\
    250			    exclusive ? WQ_FLAG_EXCLUSIVE : 0);		\
    251	for (;;) {							\
    252		long __int = prepare_to_wait_event(__wq_head,		\
    253						   &__wbq_entry.wq_entry, \
    254						   state);		\
    255		if (condition)						\
    256			break;						\
    257									\
    258		if (___wait_is_interruptible(state) && __int) {		\
    259			__ret = __int;					\
    260			goto __out;					\
    261		}							\
    262									\
    263		cmd;							\
    264	}								\
    265	finish_wait(__wq_head, &__wbq_entry.wq_entry);			\
    266__out:	__ret;								\
    267})
    268
    269#define __wait_var_event(var, condition)				\
    270	___wait_var_event(var, condition, TASK_UNINTERRUPTIBLE, 0, 0,	\
    271			  schedule())
    272
    273#define wait_var_event(var, condition)					\
    274do {									\
    275	might_sleep();							\
    276	if (condition)							\
    277		break;							\
    278	__wait_var_event(var, condition);				\
    279} while (0)
    280
    281#define __wait_var_event_killable(var, condition)			\
    282	___wait_var_event(var, condition, TASK_KILLABLE, 0, 0,		\
    283			  schedule())
    284
    285#define wait_var_event_killable(var, condition)				\
    286({									\
    287	int __ret = 0;							\
    288	might_sleep();							\
    289	if (!(condition))						\
    290		__ret = __wait_var_event_killable(var, condition);	\
    291	__ret;								\
    292})
    293
    294#define __wait_var_event_timeout(var, condition, timeout)		\
    295	___wait_var_event(var, ___wait_cond_timeout(condition),		\
    296			  TASK_UNINTERRUPTIBLE, 0, timeout,		\
    297			  __ret = schedule_timeout(__ret))
    298
    299#define wait_var_event_timeout(var, condition, timeout)			\
    300({									\
    301	long __ret = timeout;						\
    302	might_sleep();							\
    303	if (!___wait_cond_timeout(condition))				\
    304		__ret = __wait_var_event_timeout(var, condition, timeout); \
    305	__ret;								\
    306})
    307
    308#define __wait_var_event_interruptible(var, condition)			\
    309	___wait_var_event(var, condition, TASK_INTERRUPTIBLE, 0, 0,	\
    310			  schedule())
    311
    312#define wait_var_event_interruptible(var, condition)			\
    313({									\
    314	int __ret = 0;							\
    315	might_sleep();							\
    316	if (!(condition))						\
    317		__ret = __wait_var_event_interruptible(var, condition);	\
    318	__ret;								\
    319})
    320
    321/**
    322 * clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit
    323 *
    324 * @bit: the bit of the word being waited on
    325 * @word: the word being waited on, a kernel virtual address
    326 *
    327 * You can use this helper if bitflags are manipulated atomically rather than
    328 * non-atomically under a lock.
    329 */
    330static inline void clear_and_wake_up_bit(int bit, void *word)
    331{
    332	clear_bit_unlock(bit, word);
    333	/* See wake_up_bit() for which memory barrier you need to use. */
    334	smp_mb__after_atomic();
    335	wake_up_bit(word, bit);
    336}
    337
    338#endif /* _LINUX_WAIT_BIT_H */