1 1.28 ad /* $NetBSD: sleepq.c,v 1.28 2023/10/13 18:23:54 ad Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2008 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.2 pooka #include <sys/cdefs.h> 29 1.28 ad __KERNEL_RCSID(0, "$NetBSD: sleepq.c,v 1.28 2023/10/13 18:23:54 ad Exp $"); 30 1.2 pooka 31 1.1 pooka #include <sys/param.h> 32 1.1 pooka #include <sys/condvar.h> 33 1.1 pooka #include <sys/mutex.h> 34 1.6 pooka #include <sys/once.h> 35 1.1 pooka #include <sys/queue.h> 36 1.1 pooka #include <sys/sleepq.h> 37 1.1 pooka #include <sys/syncobj.h> 38 1.10 skrll #include <sys/atomic.h> 39 1.1 pooka 40 1.17 pooka #include <rump-sys/kern.h> 41 1.3 pooka 42 1.1 pooka syncobj_t sleep_syncobj; 43 1.1 pooka 44 1.21 christos void 45 1.21 christos sleepq_init(sleepq_t *sq) 46 1.6 pooka { 47 1.6 pooka 48 1.21 christos LIST_INIT(sq); 49 1.21 christos cv_init(&sq->sq_cv, "sleepq"); 50 1.6 pooka } 51 1.6 pooka 52 1.1 pooka void 53 1.21 christos sleepq_destroy(sleepq_t *sq) 54 1.1 pooka { 55 1.1 pooka 56 1.21 christos cv_destroy(&sq->sq_cv); 57 1.1 pooka } 58 1.1 pooka 59 1.25 ad int 60 1.24 ad sleepq_enter(sleepq_t *sq, lwp_t *l, kmutex_t *mp) 61 1.24 ad { 62 1.25 ad int nlocks; 63 1.24 ad 64 1.24 ad lwp_lock(l); 65 1.26 ad if (mp != NULL) { 66 1.26 ad lwp_unlock_to(l, mp); 67 1.26 ad } 68 1.26 ad if ((nlocks = l->l_blcnt) != 0) { 69 1.26 ad KERNEL_UNLOCK_ALL(NULL, NULL); 70 1.26 ad } 71 1.25 ad return nlocks; 72 1.24 ad } 73 1.24 ad 74 1.24 ad void 75 1.19 ad sleepq_enqueue(sleepq_t *sq, wchan_t wc, const char *wmsg, syncobj_t *sob, 76 1.19 ad bool catch_p) 77 1.1 pooka { 78 1.1 pooka struct lwp *l = curlwp; 79 1.1 pooka 80 1.1 pooka l->l_wchan = wc; 81 1.12 pooka l->l_wmesg = wmsg; 82 1.3 pooka l->l_sleepq = sq; 83 1.18 ad LIST_INSERT_HEAD(sq, l, l_sleepchain); 84 1.1 pooka } 85 1.1 pooka 86 1.1 pooka int 87 1.25 ad sleepq_block(int timo, bool catch, syncobj_t *syncobj __unused, int nlocks) 88 1.1 pooka { 89 1.1 pooka struct lwp *l = curlwp; 90 1.3 pooka int error = 0; 91 1.3 pooka kmutex_t *mp = l->l_mutex; 92 1.1 pooka 93 1.3 pooka while (l->l_wchan) { 94 1.13 pooka l->l_mutex = mp; /* keep sleepq lock until woken up */ 95 1.21 christos error = cv_timedwait(&l->l_sleepq->sq_cv, mp, timo); 96 1.11 pooka if (error == EWOULDBLOCK || error == EINTR) { 97 1.13 pooka if (l->l_wchan) { 98 1.18 ad LIST_REMOVE(l, l_sleepchain); 99 1.13 pooka l->l_wchan = NULL; 100 1.13 pooka l->l_wmesg = NULL; 101 1.13 pooka } 102 1.4 pooka } 103 1.3 pooka } 104 1.3 pooka mutex_spin_exit(mp); 105 1.1 pooka 106 1.25 ad if (nlocks) 107 1.25 ad KERNEL_LOCK(nlocks, curlwp); 108 1.1 pooka 109 1.3 pooka return error; 110 1.1 pooka } 111 1.1 pooka 112 1.16 pooka void 113 1.1 pooka sleepq_wake(sleepq_t *sq, wchan_t wchan, u_int expected, kmutex_t *mp) 114 1.1 pooka { 115 1.3 pooka struct lwp *l, *l_next; 116 1.1 pooka bool found = false; 117 1.1 pooka 118 1.18 ad for (l = LIST_FIRST(sq); l; l = l_next) { 119 1.18 ad l_next = LIST_NEXT(l, l_sleepchain); 120 1.1 pooka if (l->l_wchan == wchan) { 121 1.1 pooka found = true; 122 1.1 pooka l->l_wchan = NULL; 123 1.12 pooka l->l_wmesg = NULL; 124 1.18 ad LIST_REMOVE(l, l_sleepchain); 125 1.15 pooka if (--expected == 0) 126 1.15 pooka break; 127 1.1 pooka } 128 1.1 pooka } 129 1.1 pooka if (found) 130 1.21 christos cv_broadcast(&sq->sq_cv); 131 1.1 pooka 132 1.1 pooka mutex_spin_exit(mp); 133 1.1 pooka } 134 1.1 pooka 135 1.5 rmind void 136 1.3 pooka sleepq_unsleep(struct lwp *l, bool cleanup) 137 1.3 pooka { 138 1.3 pooka 139 1.3 pooka l->l_wchan = NULL; 140 1.12 pooka l->l_wmesg = NULL; 141 1.18 ad LIST_REMOVE(l, l_sleepchain); 142 1.21 christos cv_broadcast(&l->l_sleepq->sq_cv); 143 1.3 pooka 144 1.3 pooka if (cleanup) { 145 1.3 pooka mutex_spin_exit(l->l_mutex); 146 1.3 pooka } 147 1.3 pooka } 148 1.3 pooka 149 1.27 ad void 150 1.27 ad sleepq_remove(sleepq_t *sq, struct lwp *l, bool wakeup) 151 1.27 ad { 152 1.27 ad 153 1.28 ad sleepq_unsleep(l, false); 154 1.27 ad } 155 1.27 ad 156 1.1 pooka /* 157 1.3 pooka * Thread scheduler handles priorities. Therefore no action here. 158 1.3 pooka * (maybe do something if we're deperate?) 159 1.3 pooka */ 160 1.3 pooka void 161 1.3 pooka sleepq_changepri(struct lwp *l, pri_t pri) 162 1.3 pooka { 163 1.3 pooka 164 1.3 pooka } 165 1.3 pooka 166 1.3 pooka void 167 1.3 pooka sleepq_lendpri(struct lwp *l, pri_t pri) 168 1.3 pooka { 169 1.3 pooka 170 1.3 pooka } 171 1.3 pooka 172 1.3 pooka struct lwp * 173 1.3 pooka syncobj_noowner(wchan_t wc) 174 1.3 pooka { 175 1.3 pooka 176 1.3 pooka return NULL; 177 1.3 pooka } 178 1.3 pooka 179 1.9 rmind void 180 1.9 rmind lwp_unlock_to(struct lwp *l, kmutex_t *new) 181 1.1 pooka { 182 1.9 rmind kmutex_t *old; 183 1.1 pooka 184 1.9 rmind KASSERT(mutex_owned(l->l_mutex)); 185 1.9 rmind 186 1.9 rmind old = l->l_mutex; 187 1.22 riastrad atomic_store_release(&l->l_mutex, new); 188 1.9 rmind mutex_spin_exit(old); 189 1.1 pooka } 190 1.24 ad 191 1.24 ad void 192 1.24 ad lwp_lock(lwp_t *l) 193 1.24 ad { 194 1.24 ad kmutex_t *old = atomic_load_consume(&l->l_mutex); 195 1.24 ad 196 1.24 ad mutex_spin_enter(old); 197 1.24 ad while (__predict_false(atomic_load_relaxed(&l->l_mutex) != old)) { 198 1.24 ad mutex_spin_exit(old); 199 1.24 ad old = atomic_load_consume(&l->l_mutex); 200 1.24 ad mutex_spin_enter(old); 201 1.24 ad } 202 1.24 ad } 203 1.24 ad 204 1.24 ad void 205 1.24 ad lwp_unlock(lwp_t *l) 206 1.24 ad { 207 1.24 ad 208 1.24 ad mutex_spin_exit(l->l_mutex); 209 1.24 ad } 210 1.24 ad 211 1.24 ad void 212 1.24 ad lwp_changepri(lwp_t *l, pri_t pri) 213 1.24 ad { 214 1.24 ad 215 1.24 ad /* fuck */ 216 1.24 ad } 217 1.24 ad 218 1.24 ad void 219 1.24 ad lwp_lendpri(lwp_t *l, pri_t pri) 220 1.24 ad { 221 1.24 ad 222 1.24 ad /* you */ 223 1.24 ad } 224 1.24 ad 225 1.24 ad pri_t 226 1.24 ad lwp_eprio(lwp_t *l) 227 1.24 ad { 228 1.24 ad 229 1.24 ad /* Antti */ 230 1.24 ad return l->l_priority; 231 1.24 ad } 232