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