| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org> |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 25 | * SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #ifndef _SYS_SLEEPQUEUE_H_ |
| 29 | #define _SYS_SLEEPQUEUE_H_ |
| 30 | |
| 31 | /* |
| 32 | * Sleep queue interface. Sleep/wakeup, condition variables, and sx |
| 33 | * locks use a sleep queue for the queue of threads blocked on a sleep |
| 34 | * channel. |
| 35 | * |
| 36 | * A thread calls sleepq_lock() to lock the sleep queue chain associated |
| 37 | * with a given wait channel. A thread can then call call sleepq_add() to |
| 38 | * add themself onto a sleep queue and call one of the sleepq_wait() |
| 39 | * functions to actually go to sleep. If a thread needs to abort a sleep |
| 40 | * operation it should call sleepq_release() to unlock the associated sleep |
| 41 | * queue chain lock. If the thread also needs to remove itself from a queue |
| 42 | * it just enqueued itself on, it can use sleepq_remove() instead. |
| 43 | * |
| 44 | * If the thread only wishes to sleep for a limited amount of time, it can |
| 45 | * call sleepq_set_timeout() after sleepq_add() to setup a timeout. It |
| 46 | * should then use one of the sleepq_timedwait() functions to block. |
| 47 | * |
| 48 | * A thread is normally resumed from a sleep queue by either the |
| 49 | * sleepq_signal() or sleepq_broadcast() functions. Sleepq_signal() wakes |
| 50 | * the thread with the highest priority that is sleeping on the specified |
| 51 | * wait channel. Sleepq_broadcast() wakes all threads that are sleeping |
| 52 | * on the specified wait channel. A thread sleeping in an interruptible |
| 53 | * sleep can be interrupted by calling sleepq_abort(). A thread can also |
| 54 | * be removed from a specified sleep queue using the sleepq_remove() |
| 55 | * function. Note that the sleep queue chain must first be locked via |
| 56 | * sleepq_lock() before calling sleepq_abort(), sleepq_broadcast(), or |
| 57 | * sleepq_signal(). These routines each return a boolean that will be true |
| 58 | * if at least one swapped-out thread was resumed. In that case, the caller |
| 59 | * is responsible for waking up the swapper by calling kick_proc0() after |
| 60 | * releasing the sleep queue chain lock. |
| 61 | * |
| 62 | * Each thread allocates a sleep queue at thread creation via sleepq_alloc() |
| 63 | * and releases it at thread destruction via sleepq_free(). Note that |
| 64 | * a sleep queue is not tied to a specific thread and that the sleep queue |
| 65 | * released at thread destruction may not be the same sleep queue that the |
| 66 | * thread allocated when it was created. |
| 67 | * |
| 68 | * XXX: Some other parts of the kernel such as ithread sleeping may end up |
| 69 | * using this interface as well (death to TDI_IWAIT!) |
| 70 | */ |
| 71 | |
| 72 | struct lock_object; |
| 73 | struct sleepqueue; |
| 74 | struct thread; |
| 75 | |
| 76 | #ifdef _KERNEL |
| 77 | |
| 78 | #define	SLEEPQ_TYPE		0x0ff		/* Mask of sleep queue types. */ |
| 79 | #define	SLEEPQ_SLEEP		0x00		/* Used by sleep/wakeup. */ |
| 80 | #define	SLEEPQ_CONDVAR		0x01		/* Used for a cv. */ |
| 81 | #define	SLEEPQ_PAUSE		0x02		/* Used by pause. */ |
| 82 | #define	SLEEPQ_SX		0x03		/* Used by an sx lock. */ |
| 83 | #define	SLEEPQ_LK		0x04		/* Used by a lockmgr. */ |
| 84 | #define	SLEEPQ_INTERRUPTIBLE	0x100		/* Sleep is interruptible. */ |
| 85 | #define	SLEEPQ_UNFAIR		0x200		/* Unfair wakeup order. */ |
| 86 | #define	SLEEPQ_DROP		0x400		/* Return without lock held. */ |
| 87 | |
| 88 | void	init_sleepqueues(void); |
| 89 | void	sleepq_abort(struct thread *td, int intrval); |
| 90 | void	sleepq_add(const void *wchan, struct lock_object *lock, |
| 91 | 	 const char *wmesg, int flags, int queue); |
| 92 | struct sleepqueue *sleepq_alloc(void); |
| 93 | void	sleepq_broadcast(const void *wchan, int flags, int pri, int queue); |
| 94 | void	sleepq_chains_remove_matching(bool (*matches)(struct thread *)); |
| 95 | void	sleepq_free(struct sleepqueue *sq); |
| 96 | void	sleepq_lock(const void *wchan); |
| 97 | struct sleepqueue *sleepq_lookup(const void *wchan); |
| 98 | void	sleepq_release(const void *wchan); |
| 99 | void	sleepq_remove(struct thread *td, const void *wchan); |
| 100 | void	sleepq_remove_matching(struct sleepqueue *sq, int queue, |
| 101 | 	 bool (*matches)(struct thread *), int pri); |
| 102 | void	sleepq_remove_nested(struct thread *td); |
| 103 | void	sleepq_signal(const void *wchan, int flags, int pri, int queue); |
| 104 | void	sleepq_set_timeout_sbt(const void *wchan, sbintime_t sbt, |
| 105 | 	 sbintime_t pr, int flags); |
| 106 | #define	sleepq_set_timeout(wchan, timo)					\ |
| 107 | sleepq_set_timeout_sbt((wchan), tick_sbt * (timo), 0, C_HARDCLOCK) |
| 108 | u_int	sleepq_sleepcnt(const void *wchan, int queue); |
| 109 | int	sleepq_timedwait(const void *wchan, int pri); |
| 110 | int	sleepq_timedwait_sig(const void *wchan, int pri); |
| 111 | int	sleepq_type(const void *wchan); |
| 112 | void	sleepq_wait(const void *wchan, int pri); |
| 113 | int	sleepq_wait_sig(const void *wchan, int pri); |
| 114 | |
| 115 | #ifdef STACK |
| 116 | struct sbuf; |
| 117 | int sleepq_sbuf_print_stacks(struct sbuf *sb, const void *wchan, int queue, |
| 118 | int *count_stacks_printed); |
| 119 | #endif |
| 120 | |
| 121 | #endif	/* _KERNEL */ |
| 122 | #endif	/* !_SYS_SLEEPQUEUE_H_ */ |