xref: /netbsd/sys/rump/librump/rumpkern/klock.c (revision 6550d01e)
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