162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _LINUX_WAIT_BIT_H 362306a36Sopenharmony_ci#define _LINUX_WAIT_BIT_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * Linux wait-bit related types and methods: 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/wait.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistruct wait_bit_key { 1162306a36Sopenharmony_ci void *flags; 1262306a36Sopenharmony_ci int bit_nr; 1362306a36Sopenharmony_ci unsigned long timeout; 1462306a36Sopenharmony_ci}; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct wait_bit_queue_entry { 1762306a36Sopenharmony_ci struct wait_bit_key key; 1862306a36Sopenharmony_ci struct wait_queue_entry wq_entry; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ 2262306a36Sopenharmony_ci { .flags = word, .bit_nr = bit, } 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_citypedef int wait_bit_action_f(struct wait_bit_key *key, int mode); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_civoid __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit); 2762306a36Sopenharmony_ciint __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); 2862306a36Sopenharmony_ciint __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); 2962306a36Sopenharmony_civoid wake_up_bit(void *word, int bit); 3062306a36Sopenharmony_ciint out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode); 3162306a36Sopenharmony_ciint out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout); 3262306a36Sopenharmony_ciint out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode); 3362306a36Sopenharmony_cistruct wait_queue_head *bit_waitqueue(void *word, int bit); 3462306a36Sopenharmony_ciextern void __init wait_bit_init(void); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciint wake_bit_function(struct wait_queue_entry *wq_entry, unsigned mode, int sync, void *key); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define DEFINE_WAIT_BIT(name, word, bit) \ 3962306a36Sopenharmony_ci struct wait_bit_queue_entry name = { \ 4062306a36Sopenharmony_ci .key = __WAIT_BIT_KEY_INITIALIZER(word, bit), \ 4162306a36Sopenharmony_ci .wq_entry = { \ 4262306a36Sopenharmony_ci .private = current, \ 4362306a36Sopenharmony_ci .func = wake_bit_function, \ 4462306a36Sopenharmony_ci .entry = \ 4562306a36Sopenharmony_ci LIST_HEAD_INIT((name).wq_entry.entry), \ 4662306a36Sopenharmony_ci }, \ 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciextern int bit_wait(struct wait_bit_key *key, int mode); 5062306a36Sopenharmony_ciextern int bit_wait_io(struct wait_bit_key *key, int mode); 5162306a36Sopenharmony_ciextern int bit_wait_timeout(struct wait_bit_key *key, int mode); 5262306a36Sopenharmony_ciextern int bit_wait_io_timeout(struct wait_bit_key *key, int mode); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/** 5562306a36Sopenharmony_ci * wait_on_bit - wait for a bit to be cleared 5662306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 5762306a36Sopenharmony_ci * @bit: the bit of the word being waited on 5862306a36Sopenharmony_ci * @mode: the task state to sleep in 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * There is a standard hashed waitqueue table for generic use. This 6162306a36Sopenharmony_ci * is the part of the hashtable's accessor API that waits on a bit. 6262306a36Sopenharmony_ci * For instance, if one were to have waiters on a bitflag, one would 6362306a36Sopenharmony_ci * call wait_on_bit() in threads waiting for the bit to clear. 6462306a36Sopenharmony_ci * One uses wait_on_bit() where one is waiting for the bit to clear, 6562306a36Sopenharmony_ci * but has no intention of setting it. 6662306a36Sopenharmony_ci * Returned value will be zero if the bit was cleared, or non-zero 6762306a36Sopenharmony_ci * if the process received a signal and the mode permitted wakeup 6862306a36Sopenharmony_ci * on that signal. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistatic inline int 7162306a36Sopenharmony_ciwait_on_bit(unsigned long *word, int bit, unsigned mode) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci might_sleep(); 7462306a36Sopenharmony_ci if (!test_bit_acquire(bit, word)) 7562306a36Sopenharmony_ci return 0; 7662306a36Sopenharmony_ci return out_of_line_wait_on_bit(word, bit, 7762306a36Sopenharmony_ci bit_wait, 7862306a36Sopenharmony_ci mode); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * wait_on_bit_io - wait for a bit to be cleared 8362306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 8462306a36Sopenharmony_ci * @bit: the bit of the word being waited on 8562306a36Sopenharmony_ci * @mode: the task state to sleep in 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * Use the standard hashed waitqueue table to wait for a bit 8862306a36Sopenharmony_ci * to be cleared. This is similar to wait_on_bit(), but calls 8962306a36Sopenharmony_ci * io_schedule() instead of schedule() for the actual waiting. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Returned value will be zero if the bit was cleared, or non-zero 9262306a36Sopenharmony_ci * if the process received a signal and the mode permitted wakeup 9362306a36Sopenharmony_ci * on that signal. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic inline int 9662306a36Sopenharmony_ciwait_on_bit_io(unsigned long *word, int bit, unsigned mode) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci might_sleep(); 9962306a36Sopenharmony_ci if (!test_bit_acquire(bit, word)) 10062306a36Sopenharmony_ci return 0; 10162306a36Sopenharmony_ci return out_of_line_wait_on_bit(word, bit, 10262306a36Sopenharmony_ci bit_wait_io, 10362306a36Sopenharmony_ci mode); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/** 10762306a36Sopenharmony_ci * wait_on_bit_timeout - wait for a bit to be cleared or a timeout elapses 10862306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 10962306a36Sopenharmony_ci * @bit: the bit of the word being waited on 11062306a36Sopenharmony_ci * @mode: the task state to sleep in 11162306a36Sopenharmony_ci * @timeout: timeout, in jiffies 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * Use the standard hashed waitqueue table to wait for a bit 11462306a36Sopenharmony_ci * to be cleared. This is similar to wait_on_bit(), except also takes a 11562306a36Sopenharmony_ci * timeout parameter. 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * Returned value will be zero if the bit was cleared before the 11862306a36Sopenharmony_ci * @timeout elapsed, or non-zero if the @timeout elapsed or process 11962306a36Sopenharmony_ci * received a signal and the mode permitted wakeup on that signal. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_cistatic inline int 12262306a36Sopenharmony_ciwait_on_bit_timeout(unsigned long *word, int bit, unsigned mode, 12362306a36Sopenharmony_ci unsigned long timeout) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci might_sleep(); 12662306a36Sopenharmony_ci if (!test_bit_acquire(bit, word)) 12762306a36Sopenharmony_ci return 0; 12862306a36Sopenharmony_ci return out_of_line_wait_on_bit_timeout(word, bit, 12962306a36Sopenharmony_ci bit_wait_timeout, 13062306a36Sopenharmony_ci mode, timeout); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * wait_on_bit_action - wait for a bit to be cleared 13562306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 13662306a36Sopenharmony_ci * @bit: the bit of the word being waited on 13762306a36Sopenharmony_ci * @action: the function used to sleep, which may take special actions 13862306a36Sopenharmony_ci * @mode: the task state to sleep in 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * Use the standard hashed waitqueue table to wait for a bit 14162306a36Sopenharmony_ci * to be cleared, and allow the waiting action to be specified. 14262306a36Sopenharmony_ci * This is like wait_on_bit() but allows fine control of how the waiting 14362306a36Sopenharmony_ci * is done. 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * Returned value will be zero if the bit was cleared, or non-zero 14662306a36Sopenharmony_ci * if the process received a signal and the mode permitted wakeup 14762306a36Sopenharmony_ci * on that signal. 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic inline int 15062306a36Sopenharmony_ciwait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action, 15162306a36Sopenharmony_ci unsigned mode) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci might_sleep(); 15462306a36Sopenharmony_ci if (!test_bit_acquire(bit, word)) 15562306a36Sopenharmony_ci return 0; 15662306a36Sopenharmony_ci return out_of_line_wait_on_bit(word, bit, action, mode); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * wait_on_bit_lock - wait for a bit to be cleared, when wanting to set it 16162306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 16262306a36Sopenharmony_ci * @bit: the bit of the word being waited on 16362306a36Sopenharmony_ci * @mode: the task state to sleep in 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * There is a standard hashed waitqueue table for generic use. This 16662306a36Sopenharmony_ci * is the part of the hashtable's accessor API that waits on a bit 16762306a36Sopenharmony_ci * when one intends to set it, for instance, trying to lock bitflags. 16862306a36Sopenharmony_ci * For instance, if one were to have waiters trying to set bitflag 16962306a36Sopenharmony_ci * and waiting for it to clear before setting it, one would call 17062306a36Sopenharmony_ci * wait_on_bit() in threads waiting to be able to set the bit. 17162306a36Sopenharmony_ci * One uses wait_on_bit_lock() where one is waiting for the bit to 17262306a36Sopenharmony_ci * clear with the intention of setting it, and when done, clearing it. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * Returns zero if the bit was (eventually) found to be clear and was 17562306a36Sopenharmony_ci * set. Returns non-zero if a signal was delivered to the process and 17662306a36Sopenharmony_ci * the @mode allows that signal to wake the process. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic inline int 17962306a36Sopenharmony_ciwait_on_bit_lock(unsigned long *word, int bit, unsigned mode) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci might_sleep(); 18262306a36Sopenharmony_ci if (!test_and_set_bit(bit, word)) 18362306a36Sopenharmony_ci return 0; 18462306a36Sopenharmony_ci return out_of_line_wait_on_bit_lock(word, bit, bit_wait, mode); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/** 18862306a36Sopenharmony_ci * wait_on_bit_lock_io - wait for a bit to be cleared, when wanting to set it 18962306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 19062306a36Sopenharmony_ci * @bit: the bit of the word being waited on 19162306a36Sopenharmony_ci * @mode: the task state to sleep in 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * Use the standard hashed waitqueue table to wait for a bit 19462306a36Sopenharmony_ci * to be cleared and then to atomically set it. This is similar 19562306a36Sopenharmony_ci * to wait_on_bit(), but calls io_schedule() instead of schedule() 19662306a36Sopenharmony_ci * for the actual waiting. 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * Returns zero if the bit was (eventually) found to be clear and was 19962306a36Sopenharmony_ci * set. Returns non-zero if a signal was delivered to the process and 20062306a36Sopenharmony_ci * the @mode allows that signal to wake the process. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_cistatic inline int 20362306a36Sopenharmony_ciwait_on_bit_lock_io(unsigned long *word, int bit, unsigned mode) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci might_sleep(); 20662306a36Sopenharmony_ci if (!test_and_set_bit(bit, word)) 20762306a36Sopenharmony_ci return 0; 20862306a36Sopenharmony_ci return out_of_line_wait_on_bit_lock(word, bit, bit_wait_io, mode); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/** 21262306a36Sopenharmony_ci * wait_on_bit_lock_action - wait for a bit to be cleared, when wanting to set it 21362306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 21462306a36Sopenharmony_ci * @bit: the bit of the word being waited on 21562306a36Sopenharmony_ci * @action: the function used to sleep, which may take special actions 21662306a36Sopenharmony_ci * @mode: the task state to sleep in 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * Use the standard hashed waitqueue table to wait for a bit 21962306a36Sopenharmony_ci * to be cleared and then to set it, and allow the waiting action 22062306a36Sopenharmony_ci * to be specified. 22162306a36Sopenharmony_ci * This is like wait_on_bit() but allows fine control of how the waiting 22262306a36Sopenharmony_ci * is done. 22362306a36Sopenharmony_ci * 22462306a36Sopenharmony_ci * Returns zero if the bit was (eventually) found to be clear and was 22562306a36Sopenharmony_ci * set. Returns non-zero if a signal was delivered to the process and 22662306a36Sopenharmony_ci * the @mode allows that signal to wake the process. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_cistatic inline int 22962306a36Sopenharmony_ciwait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action, 23062306a36Sopenharmony_ci unsigned mode) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci might_sleep(); 23362306a36Sopenharmony_ci if (!test_and_set_bit(bit, word)) 23462306a36Sopenharmony_ci return 0; 23562306a36Sopenharmony_ci return out_of_line_wait_on_bit_lock(word, bit, action, mode); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ciextern void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int flags); 23962306a36Sopenharmony_ciextern void wake_up_var(void *var); 24062306a36Sopenharmony_ciextern wait_queue_head_t *__var_waitqueue(void *p); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci#define ___wait_var_event(var, condition, state, exclusive, ret, cmd) \ 24362306a36Sopenharmony_ci({ \ 24462306a36Sopenharmony_ci __label__ __out; \ 24562306a36Sopenharmony_ci struct wait_queue_head *__wq_head = __var_waitqueue(var); \ 24662306a36Sopenharmony_ci struct wait_bit_queue_entry __wbq_entry; \ 24762306a36Sopenharmony_ci long __ret = ret; /* explicit shadow */ \ 24862306a36Sopenharmony_ci \ 24962306a36Sopenharmony_ci init_wait_var_entry(&__wbq_entry, var, \ 25062306a36Sopenharmony_ci exclusive ? WQ_FLAG_EXCLUSIVE : 0); \ 25162306a36Sopenharmony_ci for (;;) { \ 25262306a36Sopenharmony_ci long __int = prepare_to_wait_event(__wq_head, \ 25362306a36Sopenharmony_ci &__wbq_entry.wq_entry, \ 25462306a36Sopenharmony_ci state); \ 25562306a36Sopenharmony_ci if (condition) \ 25662306a36Sopenharmony_ci break; \ 25762306a36Sopenharmony_ci \ 25862306a36Sopenharmony_ci if (___wait_is_interruptible(state) && __int) { \ 25962306a36Sopenharmony_ci __ret = __int; \ 26062306a36Sopenharmony_ci goto __out; \ 26162306a36Sopenharmony_ci } \ 26262306a36Sopenharmony_ci \ 26362306a36Sopenharmony_ci cmd; \ 26462306a36Sopenharmony_ci } \ 26562306a36Sopenharmony_ci finish_wait(__wq_head, &__wbq_entry.wq_entry); \ 26662306a36Sopenharmony_ci__out: __ret; \ 26762306a36Sopenharmony_ci}) 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci#define __wait_var_event(var, condition) \ 27062306a36Sopenharmony_ci ___wait_var_event(var, condition, TASK_UNINTERRUPTIBLE, 0, 0, \ 27162306a36Sopenharmony_ci schedule()) 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#define wait_var_event(var, condition) \ 27462306a36Sopenharmony_cido { \ 27562306a36Sopenharmony_ci might_sleep(); \ 27662306a36Sopenharmony_ci if (condition) \ 27762306a36Sopenharmony_ci break; \ 27862306a36Sopenharmony_ci __wait_var_event(var, condition); \ 27962306a36Sopenharmony_ci} while (0) 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#define __wait_var_event_killable(var, condition) \ 28262306a36Sopenharmony_ci ___wait_var_event(var, condition, TASK_KILLABLE, 0, 0, \ 28362306a36Sopenharmony_ci schedule()) 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci#define wait_var_event_killable(var, condition) \ 28662306a36Sopenharmony_ci({ \ 28762306a36Sopenharmony_ci int __ret = 0; \ 28862306a36Sopenharmony_ci might_sleep(); \ 28962306a36Sopenharmony_ci if (!(condition)) \ 29062306a36Sopenharmony_ci __ret = __wait_var_event_killable(var, condition); \ 29162306a36Sopenharmony_ci __ret; \ 29262306a36Sopenharmony_ci}) 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci#define __wait_var_event_timeout(var, condition, timeout) \ 29562306a36Sopenharmony_ci ___wait_var_event(var, ___wait_cond_timeout(condition), \ 29662306a36Sopenharmony_ci TASK_UNINTERRUPTIBLE, 0, timeout, \ 29762306a36Sopenharmony_ci __ret = schedule_timeout(__ret)) 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci#define wait_var_event_timeout(var, condition, timeout) \ 30062306a36Sopenharmony_ci({ \ 30162306a36Sopenharmony_ci long __ret = timeout; \ 30262306a36Sopenharmony_ci might_sleep(); \ 30362306a36Sopenharmony_ci if (!___wait_cond_timeout(condition)) \ 30462306a36Sopenharmony_ci __ret = __wait_var_event_timeout(var, condition, timeout); \ 30562306a36Sopenharmony_ci __ret; \ 30662306a36Sopenharmony_ci}) 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci#define __wait_var_event_interruptible(var, condition) \ 30962306a36Sopenharmony_ci ___wait_var_event(var, condition, TASK_INTERRUPTIBLE, 0, 0, \ 31062306a36Sopenharmony_ci schedule()) 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci#define wait_var_event_interruptible(var, condition) \ 31362306a36Sopenharmony_ci({ \ 31462306a36Sopenharmony_ci int __ret = 0; \ 31562306a36Sopenharmony_ci might_sleep(); \ 31662306a36Sopenharmony_ci if (!(condition)) \ 31762306a36Sopenharmony_ci __ret = __wait_var_event_interruptible(var, condition); \ 31862306a36Sopenharmony_ci __ret; \ 31962306a36Sopenharmony_ci}) 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/** 32262306a36Sopenharmony_ci * clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit 32362306a36Sopenharmony_ci * 32462306a36Sopenharmony_ci * @bit: the bit of the word being waited on 32562306a36Sopenharmony_ci * @word: the word being waited on, a kernel virtual address 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * You can use this helper if bitflags are manipulated atomically rather than 32862306a36Sopenharmony_ci * non-atomically under a lock. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_cistatic inline void clear_and_wake_up_bit(int bit, void *word) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci clear_bit_unlock(bit, word); 33362306a36Sopenharmony_ci /* See wake_up_bit() for which memory barrier you need to use. */ 33462306a36Sopenharmony_ci smp_mb__after_atomic(); 33562306a36Sopenharmony_ci wake_up_bit(word, bit); 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci#endif /* _LINUX_WAIT_BIT_H */ 339