wait.h revision 334760
11592Srgrimes/*- 21592Srgrimes * Copyright (c) 2010 Isilon Systems, Inc. 31592Srgrimes * Copyright (c) 2010 iX Systems, Inc. 41592Srgrimes * Copyright (c) 2010 Panasas, Inc. 51592Srgrimes * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd. 61592Srgrimes * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org> 71592Srgrimes * All rights reserved. 81592Srgrimes * 91592Srgrimes * Redistribution and use in source and binary forms, with or without 101592Srgrimes * modification, are permitted provided that the following conditions 111592Srgrimes * are met: 121592Srgrimes * 1. Redistributions of source code must retain the above copyright 131592Srgrimes * notice unmodified, this list of conditions, and the following 141592Srgrimes * disclaimer. 151592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161592Srgrimes * notice, this list of conditions and the following disclaimer in the 171592Srgrimes * documentation and/or other materials provided with the distribution. 181592Srgrimes * 191592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 201592Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 211592Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 221592Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 231592Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 241592Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 251592Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 261592Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 271592Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 281592Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 291592Srgrimes * 301592Srgrimes * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/wait.h 334760 2018-06-07 07:37:38Z hselasky $ 311592Srgrimes */ 321592Srgrimes 331592Srgrimes#ifndef _LINUX_WAIT_H_ 341592Srgrimes#define _LINUX_WAIT_H_ 3529916Smarkm 361592Srgrimes#include <linux/compiler.h> 371592Srgrimes#include <linux/list.h> 381592Srgrimes#include <linux/spinlock.h> 391592Srgrimes 401592Srgrimes#include <asm/atomic.h> 4131405Scharnier 4229916Smarkm#include <sys/param.h> 4331405Scharnier#include <sys/systm.h> 4431405Scharnier 4550476Speter#define SKIP_SLEEP() (SCHEDULER_STOPPED() || kdb_active) 461592Srgrimes 471592Srgrimes#define might_sleep() \ 481592Srgrimes WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "might_sleep()") 491592Srgrimes 501592Srgrimesstruct wait_queue; 511592Srgrimesstruct wait_queue_head; 521592Srgrimes 531592Srgrimestypedef struct wait_queue wait_queue_t; 541592Srgrimestypedef struct wait_queue_head wait_queue_head_t; 551592Srgrimes 561592Srgrimestypedef int wait_queue_func_t(wait_queue_t *, unsigned int, int, void *); 571592Srgrimes 5829916Smarkm/* 591592Srgrimes * Many API consumers directly reference these fields and those of 601592Srgrimes * wait_queue_head. 611592Srgrimes */ 621592Srgrimesstruct wait_queue { 631592Srgrimes unsigned int flags; /* always 0 */ 641592Srgrimes void *private; 651592Srgrimes wait_queue_func_t *func; 661592Srgrimes struct list_head task_list; 671592Srgrimes}; 681592Srgrimes 6911486Sdgstruct wait_queue_head { 701592Srgrimes spinlock_t lock; 711592Srgrimes struct list_head task_list; 721592Srgrimes}; 7331405Scharnier 7431405Scharnier/* 751592Srgrimes * This function is referenced by at least one DRM driver, so it may not be 761592Srgrimes * renamed and furthermore must be the default wait queue callback. 771592Srgrimes */ 781592Srgrimesextern wait_queue_func_t autoremove_wake_function; 791592Srgrimesextern wait_queue_func_t default_wake_function; 8031405Scharnier 811592Srgrimes#define DEFINE_WAIT_FUNC(name, function) \ 821592Srgrimes wait_queue_t name = { \ 8351433Smarkm .private = current, \ 8451433Smarkm .func = function, \ 8551433Smarkm .task_list = LINUX_LIST_HEAD_INIT(name.task_list) \ 8651433Smarkm } 8751433Smarkm 881592Srgrimes#define DEFINE_WAIT(name) \ 891592Srgrimes DEFINE_WAIT_FUNC(name, autoremove_wake_function) 901592Srgrimes 911592Srgrimes#define DECLARE_WAITQUEUE(name, task) \ 9251433Smarkm wait_queue_t name = { \ 931592Srgrimes .private = task, \ 9456590Sshin .task_list = LINUX_LIST_HEAD_INIT(name.task_list) \ 9556590Sshin } 9656590Sshin 9756590Sshin#define DECLARE_WAIT_QUEUE_HEAD(name) \ 9856590Sshin wait_queue_head_t name = { \ 991592Srgrimes .task_list = LINUX_LIST_HEAD_INIT(name.task_list), \ 1001592Srgrimes }; \ 1011592Srgrimes MTX_SYSINIT(name, &(name).lock.m, spin_lock_name("wqhead"), MTX_DEF) 1021592Srgrimes 1031592Srgrimes#define init_waitqueue_head(wqh) do { \ 1041592Srgrimes mtx_init(&(wqh)->lock.m, spin_lock_name("wqhead"), \ 1051592Srgrimes NULL, MTX_DEF | MTX_NEW | MTX_NOWITNESS); \ 10611486Sdg INIT_LIST_HEAD(&(wqh)->task_list); \ 1071592Srgrimes} while (0) 1081592Srgrimes 1091592Srgrimesvoid linux_wake_up(wait_queue_head_t *, unsigned int, int, bool); 11056590Sshin 11156590Sshin#define wake_up(wqh) \ 11256590Sshin linux_wake_up(wqh, TASK_NORMAL, 1, false) 11356590Sshin#define wake_up_all(wqh) \ 11456590Sshin linux_wake_up(wqh, TASK_NORMAL, 0, false) 11556590Sshin#define wake_up_locked(wqh) \ 11656590Sshin linux_wake_up(wqh, TASK_NORMAL, 1, true) 11756590Sshin#define wake_up_all_locked(wqh) \ 11856590Sshin linux_wake_up(wqh, TASK_NORMAL, 0, true) 11956590Sshin#define wake_up_interruptible(wqh) \ 12056590Sshin linux_wake_up(wqh, TASK_INTERRUPTIBLE, 1, false) 12156590Sshin#define wake_up_interruptible_all(wqh) \ 12256590Sshin linux_wake_up(wqh, TASK_INTERRUPTIBLE, 0, false) 12356590Sshin 1241592Srgrimesint linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, 1251592Srgrimes unsigned int, spinlock_t *); 1261592Srgrimes 1271592Srgrimes/* 12856590Sshin * Returns -ERESTARTSYS for a signal, 0 if cond is false after timeout, 1 if 1291592Srgrimes * cond is true after timeout, remaining jiffies (> 0) if cond is true before 1301592Srgrimes * timeout. 1311592Srgrimes */ 1321592Srgrimes#define __wait_event_common(wqh, cond, timeout, state, lock) ({ \ 1331592Srgrimes DEFINE_WAIT(__wq); \ 13451433Smarkm const int __timeout = ((int)(timeout)) < 1 ? 1 : (timeout); \ 13551433Smarkm int __start = ticks; \ 13651433Smarkm int __ret = 0; \ 13751433Smarkm \ 1381592Srgrimes for (;;) { \ 1391592Srgrimes linux_prepare_to_wait(&(wqh), &__wq, state); \ 1401592Srgrimes if (cond) \ 1411592Srgrimes break; \ 1421592Srgrimes __ret = linux_wait_event_common(&(wqh), &__wq, \ 1431592Srgrimes __timeout, state, lock); \ 14456590Sshin if (__ret != 0) \ 1451592Srgrimes break; \ 1461592Srgrimes } \ 1471592Srgrimes linux_finish_wait(&(wqh), &__wq); \ 1481592Srgrimes if (__timeout != MAX_SCHEDULE_TIMEOUT) { \ 1491592Srgrimes if (__ret == -EWOULDBLOCK) \ 15024349Simp __ret = !!(cond); \ 1511592Srgrimes else if (__ret != -ERESTARTSYS) { \ 15211486Sdg __ret = __timeout + __start - ticks; \ 15311486Sdg /* range check return value */ \ 15411486Sdg if (__ret < 1) \ 1551592Srgrimes __ret = 1; \ 1561592Srgrimes else if (__ret > __timeout) \ 1571592Srgrimes __ret = __timeout; \ 1581592Srgrimes } \ 1591592Srgrimes } \ 1601592Srgrimes __ret; \ 1611592Srgrimes}) 1621592Srgrimes 1631592Srgrimes#define wait_event(wqh, cond) do { \ 1641592Srgrimes (void) __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 1651592Srgrimes TASK_UNINTERRUPTIBLE, NULL); \ 1661592Srgrimes} while (0) 1671592Srgrimes 1681592Srgrimes#define wait_event_timeout(wqh, cond, timeout) ({ \ 1691592Srgrimes __wait_event_common(wqh, cond, timeout, TASK_UNINTERRUPTIBLE, \ 1701592Srgrimes NULL); \ 1711592Srgrimes}) 1721592Srgrimes 1731592Srgrimes#define wait_event_killable(wqh, cond) ({ \ 1741592Srgrimes __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 1751592Srgrimes TASK_INTERRUPTIBLE, NULL); \ 1761592Srgrimes}) 1771592Srgrimes 1781592Srgrimes#define wait_event_interruptible(wqh, cond) ({ \ 1791592Srgrimes __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 1801592Srgrimes TASK_INTERRUPTIBLE, NULL); \ 1811592Srgrimes}) 1821592Srgrimes 1831592Srgrimes#define wait_event_interruptible_timeout(wqh, cond, timeout) ({ \ 1841592Srgrimes __wait_event_common(wqh, cond, timeout, TASK_INTERRUPTIBLE, \ 1851592Srgrimes NULL); \ 18611486Sdg}) 18711486Sdg 18811486Sdg/* 18956590Sshin * Wait queue is already locked. 19056590Sshin */ 1911592Srgrimes#define wait_event_interruptible_locked(wqh, cond) ({ \ 1921592Srgrimes int __ret; \ 1931592Srgrimes \ 19456590Sshin spin_unlock(&(wqh).lock); \ 19511486Sdg __ret = __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 1961592Srgrimes TASK_INTERRUPTIBLE, NULL); \ 19729916Smarkm spin_lock(&(wqh).lock); \ 1981592Srgrimes __ret; \ 1991592Srgrimes}) 2001592Srgrimes 2011592Srgrimes/* 2021592Srgrimes * The passed spinlock is held when testing the condition. 2031592Srgrimes */ 2041592Srgrimes#define wait_event_interruptible_lock_irq(wqh, cond, lock) ({ \ 2051592Srgrimes __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 2061592Srgrimes TASK_INTERRUPTIBLE, &(lock)); \ 2071592Srgrimes}) 2081592Srgrimes 2091592Srgrimes/* 2101592Srgrimes * The passed spinlock is held when testing the condition. 21156590Sshin */ 2121592Srgrimes#define wait_event_lock_irq(wqh, cond, lock) ({ \ 2131592Srgrimes __wait_event_common(wqh, cond, MAX_SCHEDULE_TIMEOUT, \ 2141592Srgrimes TASK_UNINTERRUPTIBLE, &(lock)); \ 21556590Sshin}) 21656590Sshin 2171592Srgrimesstatic inline void 2181592Srgrimes__add_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq) 2191592Srgrimes{ 2201592Srgrimes list_add(&wq->task_list, &wqh->task_list); 2211592Srgrimes} 2221592Srgrimes 2231592Srgrimesstatic inline void 2241592Srgrimesadd_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq) 2251592Srgrimes{ 22656590Sshin 22756590Sshin spin_lock(&wqh->lock); 22856590Sshin __add_wait_queue(wqh, wq); 22956590Sshin spin_unlock(&wqh->lock); 23056590Sshin} 23124191Simp 2321592Srgrimesstatic inline void 2331592Srgrimes__add_wait_queue_tail(wait_queue_head_t *wqh, wait_queue_t *wq) 23463959Sume{ 23556590Sshin list_add_tail(&wq->task_list, &wqh->task_list); 23663959Sume} 23756590Sshin 23856590Sshinstatic inline void 23956590Sshin__remove_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq) 24056590Sshin{ 24156590Sshin list_del(&wq->task_list); 24256590Sshin} 24356590Sshin 24456590Sshinstatic inline void 24556590Sshinremove_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq) 2461592Srgrimes{ 24756590Sshin 2481592Srgrimes spin_lock(&wqh->lock); 2491592Srgrimes __remove_wait_queue(wqh, wq); 2501592Srgrimes spin_unlock(&wqh->lock); 25156590Sshin} 25256590Sshin 25322455Simpbool linux_waitqueue_active(wait_queue_head_t *); 25422455Simp 2551592Srgrimes#define waitqueue_active(wqh) linux_waitqueue_active(wqh) 2561592Srgrimes 2571592Srgrimesvoid linux_prepare_to_wait(wait_queue_head_t *, wait_queue_t *, int); 2581592Srgrimesvoid linux_finish_wait(wait_queue_head_t *, wait_queue_t *); 2591592Srgrimes 2601592Srgrimes#define prepare_to_wait(wqh, wq, state) linux_prepare_to_wait(wqh, wq, state) 2611592Srgrimes#define finish_wait(wqh, wq) linux_finish_wait(wqh, wq) 2621592Srgrimes 26322455Simpvoid linux_wake_up_bit(void *, int); 26422455Simpint linux_wait_on_bit_timeout(unsigned long *, int, unsigned int, int); 26522455Simpvoid linux_wake_up_atomic_t(atomic_t *); 26622455Simpint linux_wait_on_atomic_t(atomic_t *, unsigned int); 26722455Simp 26856590Sshin#define wake_up_bit(word, bit) linux_wake_up_bit(word, bit) 26922455Simp#define wait_on_bit(word, bit, state) \ 27022455Simp linux_wait_on_bit_timeout(word, bit, state, MAX_SCHEDULE_TIMEOUT) 27122455Simp#define wait_on_bit_timeout(word, bit, state, timeout) \ 27222455Simp linux_wait_on_bit_timeout(word, bit, state, timeout) 27322455Simp#define wake_up_atomic_t(a) linux_wake_up_atomic_t(a) 27422455Simp/* 2751592Srgrimes * All existing callers have a cb that just schedule()s. To avoid adding 2761592Srgrimes * complexity, just emulate that internally. The prototype is different so that 27756590Sshin * callers must be manually modified; a cb that does something other than call 2781592Srgrimes * schedule() will require special treatment. 2791592Srgrimes */ 2801592Srgrimes#define wait_on_atomic_t(a, state) linux_wait_on_atomic_t(a, state) 2811592Srgrimes 2821592Srgrimesstruct task_struct; 2831592Srgrimesbool linux_wake_up_state(struct task_struct *, unsigned int); 2841592Srgrimes 2851592Srgrimes#define wake_up_process(task) linux_wake_up_state(task, TASK_NORMAL) 2861592Srgrimes#define wake_up_state(task, state) linux_wake_up_state(task, state) 2871592Srgrimes 28829916Smarkm#endif /* _LINUX_WAIT_H_ */ 28929916Smarkm