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