Home | History | Annotate | Line # | Download | only in rumpkern
sleepq.c revision 1.26
      1  1.26        ad /*	$NetBSD: sleepq.c,v 1.26 2023/10/05 19:28:30 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.26        ad __KERNEL_RCSID(0, "$NetBSD: sleepq.c,v 1.26 2023/10/05 19:28:30 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.1     pooka /*
    150   1.3     pooka  * Thread scheduler handles priorities.  Therefore no action here.
    151   1.3     pooka  * (maybe do something if we're deperate?)
    152   1.3     pooka  */
    153   1.3     pooka void
    154   1.3     pooka sleepq_changepri(struct lwp *l, pri_t pri)
    155   1.3     pooka {
    156   1.3     pooka 
    157   1.3     pooka }
    158   1.3     pooka 
    159   1.3     pooka void
    160   1.3     pooka sleepq_lendpri(struct lwp *l, pri_t pri)
    161   1.3     pooka {
    162   1.3     pooka 
    163   1.3     pooka }
    164   1.3     pooka 
    165   1.3     pooka struct lwp *
    166   1.3     pooka syncobj_noowner(wchan_t wc)
    167   1.3     pooka {
    168   1.3     pooka 
    169   1.3     pooka 	return NULL;
    170   1.3     pooka }
    171   1.3     pooka 
    172   1.9     rmind void
    173   1.9     rmind lwp_unlock_to(struct lwp *l, kmutex_t *new)
    174   1.1     pooka {
    175   1.9     rmind 	kmutex_t *old;
    176   1.1     pooka 
    177   1.9     rmind 	KASSERT(mutex_owned(l->l_mutex));
    178   1.9     rmind 
    179   1.9     rmind 	old = l->l_mutex;
    180  1.22  riastrad 	atomic_store_release(&l->l_mutex, new);
    181   1.9     rmind 	mutex_spin_exit(old);
    182   1.1     pooka }
    183  1.24        ad 
    184  1.24        ad void
    185  1.24        ad lwp_lock(lwp_t *l)
    186  1.24        ad {
    187  1.24        ad 	kmutex_t *old = atomic_load_consume(&l->l_mutex);
    188  1.24        ad 
    189  1.24        ad 	mutex_spin_enter(old);
    190  1.24        ad 	while (__predict_false(atomic_load_relaxed(&l->l_mutex) != old)) {
    191  1.24        ad 		mutex_spin_exit(old);
    192  1.24        ad 		old = atomic_load_consume(&l->l_mutex);
    193  1.24        ad 		mutex_spin_enter(old);
    194  1.24        ad 	}
    195  1.24        ad }
    196  1.24        ad 
    197  1.24        ad void
    198  1.24        ad lwp_unlock(lwp_t *l)
    199  1.24        ad {
    200  1.24        ad 
    201  1.24        ad 	mutex_spin_exit(l->l_mutex);
    202  1.24        ad }
    203  1.24        ad 
    204  1.24        ad void
    205  1.24        ad lwp_changepri(lwp_t *l, pri_t pri)
    206  1.24        ad {
    207  1.24        ad 
    208  1.24        ad 	/* fuck */
    209  1.24        ad }
    210  1.24        ad 
    211  1.24        ad void
    212  1.24        ad lwp_lendpri(lwp_t *l, pri_t pri)
    213  1.24        ad {
    214  1.24        ad 
    215  1.24        ad 	/* you */
    216  1.24        ad }
    217  1.24        ad 
    218  1.24        ad pri_t
    219  1.24        ad lwp_eprio(lwp_t *l)
    220  1.24        ad {
    221  1.24        ad 
    222  1.24        ad 	/* Antti */
    223  1.24        ad 	return l->l_priority;
    224  1.24        ad }
    225