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