Home | History | Annotate | Line # | Download | only in rumpkern
klock.c revision 1.10
      1  1.10  msaitoh /*	$NetBSD: klock.c,v 1.10 2016/07/07 06:55:44 msaitoh Exp $	*/
      2   1.1    pooka 
      3   1.1    pooka /*
      4   1.1    pooka  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
      5   1.1    pooka  *
      6   1.1    pooka  * Development of this software was supported by the
      7   1.1    pooka  * Finnish Cultural Foundation.
      8   1.1    pooka  *
      9   1.1    pooka  * Redistribution and use in source and binary forms, with or without
     10   1.1    pooka  * modification, are permitted provided that the following conditions
     11   1.1    pooka  * are met:
     12   1.1    pooka  * 1. Redistributions of source code must retain the above copyright
     13   1.1    pooka  *    notice, this list of conditions and the following disclaimer.
     14   1.1    pooka  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1    pooka  *    notice, this list of conditions and the following disclaimer in the
     16   1.1    pooka  *    documentation and/or other materials provided with the distribution.
     17   1.1    pooka  *
     18   1.1    pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     19   1.1    pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20   1.1    pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21   1.1    pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     22   1.1    pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23   1.1    pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24   1.1    pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25   1.1    pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26   1.1    pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27   1.1    pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28   1.1    pooka  * SUCH DAMAGE.
     29   1.1    pooka  */
     30   1.1    pooka 
     31   1.1    pooka #include <sys/cdefs.h>
     32  1.10  msaitoh __KERNEL_RCSID(0, "$NetBSD: klock.c,v 1.10 2016/07/07 06:55:44 msaitoh Exp $");
     33   1.1    pooka 
     34   1.1    pooka #include <sys/param.h>
     35   1.1    pooka #include <sys/systm.h>
     36   1.5    pooka #include <sys/evcnt.h>
     37   1.1    pooka 
     38   1.9    pooka #include <rump-sys/kern.h>
     39   1.9    pooka 
     40   1.1    pooka #include <rump/rumpuser.h>
     41   1.1    pooka 
     42   1.1    pooka /*
     43   1.1    pooka  * giant lock
     44   1.1    pooka  */
     45   1.1    pooka 
     46   1.3    pooka struct rumpuser_mtx *rump_giantlock;
     47   1.3    pooka static int giantcnt;
     48   1.3    pooka static struct lwp *giantowner;
     49   1.1    pooka 
     50   1.5    pooka static struct evcnt ev_biglock_fast;
     51   1.5    pooka static struct evcnt ev_biglock_slow;
     52   1.5    pooka static struct evcnt ev_biglock_recurse;
     53   1.5    pooka 
     54   1.5    pooka void
     55   1.5    pooka rump_biglock_init(void)
     56   1.5    pooka {
     57   1.5    pooka 
     58   1.5    pooka 	evcnt_attach_dynamic(&ev_biglock_fast, EVCNT_TYPE_MISC, NULL,
     59   1.5    pooka 	    "rump biglock", "fast");
     60   1.5    pooka 	evcnt_attach_dynamic(&ev_biglock_slow, EVCNT_TYPE_MISC, NULL,
     61   1.5    pooka 	    "rump biglock", "slow");
     62   1.5    pooka 	evcnt_attach_dynamic(&ev_biglock_recurse, EVCNT_TYPE_MISC, NULL,
     63   1.5    pooka 	    "rump biglock", "recurse");
     64   1.5    pooka }
     65   1.5    pooka 
     66   1.1    pooka void
     67   1.3    pooka rump_kernel_bigwrap(int *nlocks)
     68   1.1    pooka {
     69   1.1    pooka 
     70   1.3    pooka 	KASSERT(giantcnt > 0 && curlwp == giantowner);
     71  1.10  msaitoh 	giantowner = NULL;
     72   1.3    pooka 	*nlocks = giantcnt;
     73   1.3    pooka 	giantcnt = 0;
     74   1.1    pooka }
     75   1.1    pooka 
     76   1.1    pooka void
     77   1.3    pooka rump_kernel_bigunwrap(int nlocks)
     78   1.1    pooka {
     79   1.1    pooka 
     80   1.3    pooka 	KASSERT(giantowner == NULL);
     81   1.3    pooka 	giantowner = curlwp;
     82   1.3    pooka 	giantcnt = nlocks;
     83   1.1    pooka }
     84   1.1    pooka 
     85   1.1    pooka void
     86   1.1    pooka _kernel_lock(int nlocks)
     87   1.1    pooka {
     88   1.3    pooka 	struct lwp *l = curlwp;
     89   1.1    pooka 
     90   1.3    pooka 	while (nlocks) {
     91   1.3    pooka 		if (giantowner == l) {
     92   1.3    pooka 			giantcnt += nlocks;
     93   1.3    pooka 			nlocks = 0;
     94   1.5    pooka 			ev_biglock_recurse.ev_count++;
     95   1.3    pooka 		} else {
     96   1.8    pooka 			if (rumpuser_mutex_tryenter(rump_giantlock) != 0) {
     97   1.3    pooka 				rump_unschedule_cpu1(l, NULL);
     98   1.3    pooka 				rumpuser_mutex_enter_nowrap(rump_giantlock);
     99   1.3    pooka 				rump_schedule_cpu(l);
    100   1.5    pooka 				ev_biglock_slow.ev_count++;
    101   1.5    pooka 			} else {
    102   1.5    pooka 				ev_biglock_fast.ev_count++;
    103   1.3    pooka 			}
    104   1.3    pooka 			giantowner = l;
    105   1.3    pooka 			giantcnt = 1;
    106   1.3    pooka 			nlocks--;
    107   1.1    pooka 		}
    108   1.1    pooka 	}
    109   1.1    pooka }
    110   1.1    pooka 
    111   1.1    pooka void
    112   1.1    pooka _kernel_unlock(int nlocks, int *countp)
    113   1.1    pooka {
    114   1.1    pooka 
    115   1.3    pooka 	if (giantowner != curlwp) {
    116   1.1    pooka 		KASSERT(nlocks == 0);
    117   1.1    pooka 		if (countp)
    118   1.1    pooka 			*countp = 0;
    119   1.1    pooka 		return;
    120   1.1    pooka 	}
    121   1.1    pooka 
    122   1.1    pooka 	if (countp)
    123   1.3    pooka 		*countp = giantcnt;
    124   1.1    pooka 	if (nlocks == 0)
    125   1.3    pooka 		nlocks = giantcnt;
    126   1.1    pooka 	if (nlocks == -1) {
    127   1.3    pooka 		KASSERT(giantcnt == 1);
    128   1.1    pooka 		nlocks = 1;
    129   1.1    pooka 	}
    130   1.3    pooka 	KASSERT(nlocks <= giantcnt);
    131   1.1    pooka 	while (nlocks--) {
    132   1.3    pooka 		giantcnt--;
    133   1.3    pooka 	}
    134   1.3    pooka 
    135   1.3    pooka 	if (giantcnt == 0) {
    136   1.3    pooka 		giantowner = NULL;
    137   1.1    pooka 		rumpuser_mutex_exit(rump_giantlock);
    138   1.1    pooka 	}
    139   1.1    pooka }
    140   1.1    pooka 
    141   1.4      mrg bool
    142   1.4      mrg _kernel_locked_p(void)
    143   1.4      mrg {
    144   1.4      mrg 
    145   1.4      mrg 	return giantowner == curlwp;
    146   1.4      mrg }
    147   1.4      mrg 
    148   1.1    pooka void
    149   1.1    pooka rump_user_unschedule(int nlocks, int *countp, void *interlock)
    150   1.1    pooka {
    151   1.1    pooka 
    152   1.1    pooka 	_kernel_unlock(nlocks, countp);
    153   1.1    pooka 	/*
    154   1.1    pooka 	 * XXX: technically we should unschedule_cpu1() here, but that
    155   1.1    pooka 	 * requires rump_intr_enter/exit to be implemented.
    156   1.1    pooka 	 */
    157   1.1    pooka 	rump_unschedule_cpu_interlock(curlwp, interlock);
    158   1.1    pooka }
    159   1.1    pooka 
    160   1.1    pooka void
    161   1.1    pooka rump_user_schedule(int nlocks, void *interlock)
    162   1.1    pooka {
    163   1.1    pooka 
    164   1.1    pooka 	rump_schedule_cpu_interlock(curlwp, interlock);
    165   1.1    pooka 
    166   1.1    pooka 	if (nlocks)
    167   1.1    pooka 		_kernel_lock(nlocks);
    168   1.1    pooka }
    169