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 45 struct rumpuser_mtx *rump_giantlock; 46 static int giantcnt; 47 static struct lwp *giantowner; 48 49 void 50 rump_kernel_bigwrap(int *nlocks) 51 { 52 53 KASSERT(giantcnt > 0 && curlwp == giantowner); 54 giantowner = NULL; 55 *nlocks = giantcnt; 56 giantcnt = 0; 57 } 58 59 void 60 rump_kernel_bigunwrap(int nlocks) 61 { 62 63 KASSERT(giantowner == NULL); 64 giantowner = curlwp; 65 giantcnt = nlocks; 66 } 67 68 void 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 90 void 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 120 void 121 rump_user_unschedule(int nlocks, int *countp, void *interlock) 122 { 123 124 _kernel_unlock(nlocks, countp); 125 /* 126 * XXX: technically we should unschedule_cpu1() here, but that 127 * requires rump_intr_enter/exit to be implemented. 128 */ 129 rump_unschedule_cpu_interlock(curlwp, interlock); 130 } 131 132 void 133 rump_user_schedule(int nlocks, void *interlock) 134 { 135 136 rump_schedule_cpu_interlock(curlwp, interlock); 137 138 if (nlocks) 139 _kernel_lock(nlocks); 140 } 141