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