klock.c revision 1.1 1 /* $NetBSD: klock.c,v 1.1 2010/05/18 15:12:19 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.1 2010/05/18 15:12:19 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 static volatile int lockcnt;
46
47 bool
48 kernel_biglocked()
49 {
50
51 return rumpuser_mutex_held(rump_giantlock) && lockcnt > 0;
52 }
53
54 void
55 kernel_unlock_allbutone(int *countp)
56 {
57 int minusone = lockcnt-1;
58
59 KASSERT(kernel_biglocked());
60 if (minusone) {
61 _kernel_unlock(minusone, countp);
62 }
63 KASSERT(lockcnt == 1);
64 *countp = minusone;
65
66 /*
67 * We drop lockcnt to 0 since rumpuser doesn't know that the
68 * kernel biglock is being used as the interlock for cv in
69 * tsleep.
70 */
71 lockcnt = 0;
72 }
73
74 void
75 kernel_ununlock_allbutone(int nlocks)
76 {
77
78 KASSERT(rumpuser_mutex_held(rump_giantlock) && lockcnt == 0);
79 lockcnt = 1;
80 _kernel_lock(nlocks);
81 }
82
83 void
84 _kernel_lock(int nlocks)
85 {
86
87 while (nlocks--) {
88 if (!rumpuser_mutex_tryenter(rump_giantlock)) {
89 struct lwp *l = curlwp;
90
91 rump_unschedule_cpu1(l, NULL);
92 rumpuser_mutex_enter_nowrap(rump_giantlock);
93 rump_schedule_cpu(l);
94 }
95 lockcnt++;
96 }
97 }
98
99 void
100 _kernel_unlock(int nlocks, int *countp)
101 {
102
103 if (!rumpuser_mutex_held(rump_giantlock)) {
104 KASSERT(nlocks == 0);
105 if (countp)
106 *countp = 0;
107 return;
108 }
109
110 if (countp)
111 *countp = lockcnt;
112 if (nlocks == 0)
113 nlocks = lockcnt;
114 if (nlocks == -1) {
115 KASSERT(lockcnt == 1);
116 nlocks = 1;
117 }
118 KASSERT(nlocks <= lockcnt);
119 while (nlocks--) {
120 lockcnt--;
121 rumpuser_mutex_exit(rump_giantlock);
122 }
123 }
124
125 void
126 rump_user_unschedule(int nlocks, int *countp, void *interlock)
127 {
128
129 _kernel_unlock(nlocks, countp);
130 /*
131 * XXX: technically we should unschedule_cpu1() here, but that
132 * requires rump_intr_enter/exit to be implemented.
133 */
134 rump_unschedule_cpu_interlock(curlwp, interlock);
135 }
136
137 void
138 rump_user_schedule(int nlocks, void *interlock)
139 {
140
141 rump_schedule_cpu_interlock(curlwp, interlock);
142
143 if (nlocks)
144 _kernel_lock(nlocks);
145 }
146