klock.c revision 1.3 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