xref: /netbsd-src/sys/rump/librump/rumpkern/sleepq.c (revision dfdc9d45b31fafe6326077ebf2ad5b26a65d13cc)
1*dfdc9d45Sad /*	$NetBSD: sleepq.c,v 1.28 2023/10/13 18:23:54 ad Exp $	*/
2b33ee0fbSpooka 
3b33ee0fbSpooka /*
4b33ee0fbSpooka  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
5b33ee0fbSpooka  *
6b33ee0fbSpooka  * Redistribution and use in source and binary forms, with or without
7b33ee0fbSpooka  * modification, are permitted provided that the following conditions
8b33ee0fbSpooka  * are met:
9b33ee0fbSpooka  * 1. Redistributions of source code must retain the above copyright
10b33ee0fbSpooka  *    notice, this list of conditions and the following disclaimer.
11b33ee0fbSpooka  * 2. Redistributions in binary form must reproduce the above copyright
12b33ee0fbSpooka  *    notice, this list of conditions and the following disclaimer in the
13b33ee0fbSpooka  *    documentation and/or other materials provided with the distribution.
14b33ee0fbSpooka  *
15b33ee0fbSpooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16b33ee0fbSpooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17b33ee0fbSpooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18b33ee0fbSpooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19b33ee0fbSpooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20b33ee0fbSpooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21b33ee0fbSpooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22b33ee0fbSpooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23b33ee0fbSpooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24b33ee0fbSpooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25b33ee0fbSpooka  * SUCH DAMAGE.
26b33ee0fbSpooka  */
27b33ee0fbSpooka 
28a768afd6Spooka #include <sys/cdefs.h>
29*dfdc9d45Sad __KERNEL_RCSID(0, "$NetBSD: sleepq.c,v 1.28 2023/10/13 18:23:54 ad Exp $");
30a768afd6Spooka 
31b33ee0fbSpooka #include <sys/param.h>
32b33ee0fbSpooka #include <sys/condvar.h>
33b33ee0fbSpooka #include <sys/mutex.h>
348ef9411fSpooka #include <sys/once.h>
35b33ee0fbSpooka #include <sys/queue.h>
36b33ee0fbSpooka #include <sys/sleepq.h>
37b33ee0fbSpooka #include <sys/syncobj.h>
3818922633Sskrll #include <sys/atomic.h>
39b33ee0fbSpooka 
406bb51422Spooka #include <rump-sys/kern.h>
41254ffabcSpooka 
42b33ee0fbSpooka syncobj_t sleep_syncobj;
438ef9411fSpooka 
44b33ee0fbSpooka void
sleepq_init(sleepq_t * sq)45b33ee0fbSpooka sleepq_init(sleepq_t *sq)
46b33ee0fbSpooka {
47b33ee0fbSpooka 
4871d4f850Sad 	LIST_INIT(sq);
49e71b1b1eSchristos 	cv_init(&sq->sq_cv, "sleepq");
50e71b1b1eSchristos }
51e71b1b1eSchristos 
52e71b1b1eSchristos void
sleepq_destroy(sleepq_t * sq)53e71b1b1eSchristos sleepq_destroy(sleepq_t *sq)
54e71b1b1eSchristos {
55e71b1b1eSchristos 
56e71b1b1eSchristos 	cv_destroy(&sq->sq_cv);
57b33ee0fbSpooka }
58b33ee0fbSpooka 
590a6ca13bSad int
sleepq_enter(sleepq_t * sq,lwp_t * l,kmutex_t * mp)606ed72b5fSad sleepq_enter(sleepq_t *sq, lwp_t *l, kmutex_t *mp)
616ed72b5fSad {
620a6ca13bSad 	int nlocks;
636ed72b5fSad 
646ed72b5fSad 	lwp_lock(l);
655e6f75a1Sad 	if (mp != NULL) {
666ed72b5fSad 		lwp_unlock_to(l, mp);
675e6f75a1Sad 	}
685e6f75a1Sad 	if ((nlocks = l->l_blcnt) != 0) {
695e6f75a1Sad 		KERNEL_UNLOCK_ALL(NULL, NULL);
705e6f75a1Sad 	}
710a6ca13bSad 	return nlocks;
726ed72b5fSad }
736ed72b5fSad 
746ed72b5fSad void
sleepq_enqueue(sleepq_t * sq,wchan_t wc,const char * wmsg,syncobj_t * sob,bool catch_p)75caccdff7Sad sleepq_enqueue(sleepq_t *sq, wchan_t wc, const char *wmsg, syncobj_t *sob,
76caccdff7Sad     bool catch_p)
77b33ee0fbSpooka {
78b33ee0fbSpooka 	struct lwp *l = curlwp;
79b33ee0fbSpooka 
80b33ee0fbSpooka 	l->l_wchan = wc;
81e5a2e2b2Spooka 	l->l_wmesg = wmsg;
82254ffabcSpooka 	l->l_sleepq = sq;
8371d4f850Sad 	LIST_INSERT_HEAD(sq, l, l_sleepchain);
84b33ee0fbSpooka }
85b33ee0fbSpooka 
86b33ee0fbSpooka int
sleepq_block(int timo,bool catch,syncobj_t * syncobj __unused,int nlocks)870a6ca13bSad sleepq_block(int timo, bool catch, syncobj_t *syncobj __unused, int nlocks)
88b33ee0fbSpooka {
89b33ee0fbSpooka 	struct lwp *l = curlwp;
90254ffabcSpooka 	int error = 0;
91254ffabcSpooka 	kmutex_t *mp = l->l_mutex;
92b33ee0fbSpooka 
93254ffabcSpooka 	while (l->l_wchan) {
940199e732Spooka 		l->l_mutex = mp; /* keep sleepq lock until woken up */
95e71b1b1eSchristos 		error = cv_timedwait(&l->l_sleepq->sq_cv, mp, timo);
96b0bfbf33Spooka 		if (error == EWOULDBLOCK || error == EINTR) {
970199e732Spooka 			if (l->l_wchan) {
9871d4f850Sad 				LIST_REMOVE(l, l_sleepchain);
99254ffabcSpooka 				l->l_wchan = NULL;
100e5a2e2b2Spooka 				l->l_wmesg = NULL;
101254ffabcSpooka 			}
102afa1f603Spooka 		}
1030199e732Spooka 	}
104254ffabcSpooka 	mutex_spin_exit(mp);
105b33ee0fbSpooka 
1060a6ca13bSad 	if (nlocks)
1070a6ca13bSad 		KERNEL_LOCK(nlocks, curlwp);
108b33ee0fbSpooka 
109254ffabcSpooka 	return error;
110b33ee0fbSpooka }
111b33ee0fbSpooka 
112e1b9adccSpooka void
sleepq_wake(sleepq_t * sq,wchan_t wchan,u_int expected,kmutex_t * mp)113b33ee0fbSpooka sleepq_wake(sleepq_t *sq, wchan_t wchan, u_int expected, kmutex_t *mp)
114b33ee0fbSpooka {
115254ffabcSpooka 	struct lwp *l, *l_next;
116b33ee0fbSpooka 	bool found = false;
117b33ee0fbSpooka 
11871d4f850Sad 	for (l = LIST_FIRST(sq); l; l = l_next) {
11971d4f850Sad 		l_next = LIST_NEXT(l, l_sleepchain);
120b33ee0fbSpooka 		if (l->l_wchan == wchan) {
121b33ee0fbSpooka 			found = true;
122b33ee0fbSpooka 			l->l_wchan = NULL;
123e5a2e2b2Spooka 			l->l_wmesg = NULL;
12471d4f850Sad 			LIST_REMOVE(l, l_sleepchain);
12580733d75Spooka 			if (--expected == 0)
12680733d75Spooka 				break;
127b33ee0fbSpooka 		}
128b33ee0fbSpooka 	}
129b33ee0fbSpooka 	if (found)
130e71b1b1eSchristos 		cv_broadcast(&sq->sq_cv);
131b33ee0fbSpooka 
132b33ee0fbSpooka 	mutex_spin_exit(mp);
133b33ee0fbSpooka }
134b33ee0fbSpooka 
1353e88e8e7Srmind void
sleepq_unsleep(struct lwp * l,bool cleanup)136254ffabcSpooka sleepq_unsleep(struct lwp *l, bool cleanup)
137254ffabcSpooka {
138254ffabcSpooka 
139254ffabcSpooka 	l->l_wchan = NULL;
140e5a2e2b2Spooka 	l->l_wmesg = NULL;
14171d4f850Sad 	LIST_REMOVE(l, l_sleepchain);
142e71b1b1eSchristos 	cv_broadcast(&l->l_sleepq->sq_cv);
143254ffabcSpooka 
144254ffabcSpooka 	if (cleanup) {
145254ffabcSpooka 		mutex_spin_exit(l->l_mutex);
146254ffabcSpooka 	}
147254ffabcSpooka }
148254ffabcSpooka 
14932a89764Sad void
sleepq_remove(sleepq_t * sq,struct lwp * l,bool wakeup)15032a89764Sad sleepq_remove(sleepq_t *sq, struct lwp *l, bool wakeup)
15132a89764Sad {
15232a89764Sad 
153*dfdc9d45Sad 	sleepq_unsleep(l, false);
15432a89764Sad }
15532a89764Sad 
156b33ee0fbSpooka /*
157254ffabcSpooka  * Thread scheduler handles priorities.  Therefore no action here.
158254ffabcSpooka  * (maybe do something if we're deperate?)
159254ffabcSpooka  */
160254ffabcSpooka void
sleepq_changepri(struct lwp * l,pri_t pri)161254ffabcSpooka sleepq_changepri(struct lwp *l, pri_t pri)
162254ffabcSpooka {
163254ffabcSpooka 
164254ffabcSpooka }
165254ffabcSpooka 
166254ffabcSpooka void
sleepq_lendpri(struct lwp * l,pri_t pri)167254ffabcSpooka sleepq_lendpri(struct lwp *l, pri_t pri)
168254ffabcSpooka {
169254ffabcSpooka 
170254ffabcSpooka }
171254ffabcSpooka 
172254ffabcSpooka struct lwp *
syncobj_noowner(wchan_t wc)173254ffabcSpooka syncobj_noowner(wchan_t wc)
174254ffabcSpooka {
175254ffabcSpooka 
176254ffabcSpooka 	return NULL;
177254ffabcSpooka }
178254ffabcSpooka 
17911a35aedSrmind void
lwp_unlock_to(struct lwp * l,kmutex_t * new)18011a35aedSrmind lwp_unlock_to(struct lwp *l, kmutex_t *new)
181b33ee0fbSpooka {
18211a35aedSrmind 	kmutex_t *old;
183b33ee0fbSpooka 
18411a35aedSrmind 	KASSERT(mutex_owned(l->l_mutex));
18511a35aedSrmind 
186254ffabcSpooka 	old = l->l_mutex;
1872d859edaSriastradh 	atomic_store_release(&l->l_mutex, new);
18811a35aedSrmind 	mutex_spin_exit(old);
189b33ee0fbSpooka }
1906ed72b5fSad 
1916ed72b5fSad void
lwp_lock(lwp_t * l)1926ed72b5fSad lwp_lock(lwp_t *l)
1936ed72b5fSad {
1946ed72b5fSad 	kmutex_t *old = atomic_load_consume(&l->l_mutex);
1956ed72b5fSad 
1966ed72b5fSad 	mutex_spin_enter(old);
1976ed72b5fSad 	while (__predict_false(atomic_load_relaxed(&l->l_mutex) != old)) {
1986ed72b5fSad 		mutex_spin_exit(old);
1996ed72b5fSad 		old = atomic_load_consume(&l->l_mutex);
2006ed72b5fSad 		mutex_spin_enter(old);
2016ed72b5fSad 	}
2026ed72b5fSad }
2036ed72b5fSad 
2046ed72b5fSad void
lwp_unlock(lwp_t * l)2056ed72b5fSad lwp_unlock(lwp_t *l)
2066ed72b5fSad {
2076ed72b5fSad 
2086ed72b5fSad 	mutex_spin_exit(l->l_mutex);
2096ed72b5fSad }
2106ed72b5fSad 
2116ed72b5fSad void
lwp_changepri(lwp_t * l,pri_t pri)2126ed72b5fSad lwp_changepri(lwp_t *l, pri_t pri)
2136ed72b5fSad {
2146ed72b5fSad 
2156ed72b5fSad 	/* fuck */
2166ed72b5fSad }
2176ed72b5fSad 
2186ed72b5fSad void
lwp_lendpri(lwp_t * l,pri_t pri)2196ed72b5fSad lwp_lendpri(lwp_t *l, pri_t pri)
2206ed72b5fSad {
2216ed72b5fSad 
2226ed72b5fSad 	/* you */
2236ed72b5fSad }
2246ed72b5fSad 
2256ed72b5fSad pri_t
lwp_eprio(lwp_t * l)2266ed72b5fSad lwp_eprio(lwp_t *l)
2276ed72b5fSad {
2286ed72b5fSad 
2296ed72b5fSad 	/* Antti */
2306ed72b5fSad 	return l->l_priority;
2316ed72b5fSad }
232