OsdSynch.c revision 1.7 1 1.7 ad /* $NetBSD: OsdSynch.c,v 1.7 2007/02/19 22:32:52 ad Exp $ */
2 1.1 kochi
3 1.1 kochi /*
4 1.1 kochi * Copyright 2001 Wasabi Systems, Inc.
5 1.1 kochi * All rights reserved.
6 1.1 kochi *
7 1.1 kochi * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 1.1 kochi *
9 1.1 kochi * Redistribution and use in source and binary forms, with or without
10 1.1 kochi * modification, are permitted provided that the following conditions
11 1.1 kochi * are met:
12 1.1 kochi * 1. Redistributions of source code must retain the above copyright
13 1.1 kochi * notice, this list of conditions and the following disclaimer.
14 1.1 kochi * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 kochi * notice, this list of conditions and the following disclaimer in the
16 1.1 kochi * documentation and/or other materials provided with the distribution.
17 1.1 kochi * 3. All advertising materials mentioning features or use of this software
18 1.1 kochi * must display the following acknowledgement:
19 1.1 kochi * This product includes software developed for the NetBSD Project by
20 1.1 kochi * Wasabi Systems, Inc.
21 1.1 kochi * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 1.1 kochi * or promote products derived from this software without specific prior
23 1.1 kochi * written permission.
24 1.1 kochi *
25 1.1 kochi * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 1.1 kochi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.1 kochi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.1 kochi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 1.1 kochi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.1 kochi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.1 kochi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.1 kochi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.1 kochi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.1 kochi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.1 kochi * POSSIBILITY OF SUCH DAMAGE.
36 1.1 kochi */
37 1.1 kochi
38 1.1 kochi /*-
39 1.1 kochi * Copyright (c) 2000 Michael Smith
40 1.1 kochi * Copyright (c) 2000 BSDi
41 1.1 kochi * All rights reserved.
42 1.1 kochi *
43 1.1 kochi * Redistribution and use in source and binary forms, with or without
44 1.1 kochi * modification, are permitted provided that the following conditions
45 1.1 kochi * are met:
46 1.1 kochi * 1. Redistributions of source code must retain the above copyright
47 1.1 kochi * notice, this list of conditions and the following disclaimer.
48 1.1 kochi * 2. Redistributions in binary form must reproduce the above copyright
49 1.1 kochi * notice, this list of conditions and the following disclaimer in the
50 1.1 kochi * documentation and/or other materials provided with the distribution.
51 1.1 kochi *
52 1.1 kochi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 1.1 kochi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.1 kochi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.1 kochi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 1.1 kochi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.1 kochi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.1 kochi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.1 kochi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.1 kochi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.1 kochi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.1 kochi * SUCH DAMAGE.
63 1.1 kochi */
64 1.1 kochi
65 1.1 kochi /*
66 1.1 kochi * OS Services Layer
67 1.1 kochi *
68 1.1 kochi * 6.4: Mutual Exclusion and Synchronization
69 1.1 kochi */
70 1.1 kochi
71 1.1 kochi #include <sys/cdefs.h>
72 1.7 ad __KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.7 2007/02/19 22:32:52 ad Exp $");
73 1.1 kochi
74 1.1 kochi #include <sys/param.h>
75 1.1 kochi #include <sys/malloc.h>
76 1.4 xtraeme #include <sys/mutex.h>
77 1.4 xtraeme #include <sys/condvar.h>
78 1.1 kochi #include <sys/kernel.h>
79 1.1 kochi #include <sys/proc.h>
80 1.1 kochi
81 1.1 kochi #include <dev/acpi/acpica.h>
82 1.1 kochi
83 1.1 kochi MALLOC_DECLARE(M_ACPI);
84 1.1 kochi
85 1.1 kochi #define _COMPONENT ACPI_OS_SERVICES
86 1.1 kochi ACPI_MODULE_NAME("SYNCH")
87 1.1 kochi
88 1.1 kochi /*
89 1.1 kochi * Simple counting semaphore implemented using a mutex. This is
90 1.1 kochi * subsequently used in the OSI code to implement a mutex. Go figure.
91 1.1 kochi */
92 1.1 kochi struct acpi_semaphore {
93 1.4 xtraeme kcondvar_t as_cv;
94 1.4 xtraeme kmutex_t as_slock;
95 1.1 kochi UINT32 as_units;
96 1.1 kochi UINT32 as_maxunits;
97 1.1 kochi };
98 1.1 kochi
99 1.1 kochi struct acpi_lock {
100 1.4 xtraeme kmutex_t al_slock;
101 1.1 kochi };
102 1.1 kochi
103 1.1 kochi /*
104 1.1 kochi * AcpiOsCreateSemaphore:
105 1.1 kochi *
106 1.1 kochi * Create a semaphore.
107 1.1 kochi */
108 1.1 kochi ACPI_STATUS
109 1.1 kochi AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
110 1.1 kochi ACPI_HANDLE *OutHandle)
111 1.1 kochi {
112 1.1 kochi struct acpi_semaphore *as;
113 1.1 kochi
114 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
115 1.1 kochi
116 1.1 kochi if (OutHandle == NULL)
117 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
118 1.1 kochi if (InitialUnits > MaxUnits)
119 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
120 1.1 kochi
121 1.1 kochi as = malloc(sizeof(*as), M_ACPI, M_NOWAIT);
122 1.1 kochi if (as == NULL)
123 1.1 kochi return_ACPI_STATUS(AE_NO_MEMORY);
124 1.1 kochi
125 1.4 xtraeme mutex_init(&as->as_slock, MUTEX_DRIVER, IPL_NONE);
126 1.5 xtraeme cv_init(&as->as_cv, "acpisem");
127 1.1 kochi as->as_units = InitialUnits;
128 1.1 kochi as->as_maxunits = MaxUnits;
129 1.1 kochi
130 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
131 1.1 kochi "created semaphore %p max %u initial %u\n",
132 1.1 kochi as, as->as_maxunits, as->as_units));
133 1.1 kochi
134 1.1 kochi *OutHandle = (ACPI_HANDLE) as;
135 1.1 kochi return_ACPI_STATUS(AE_OK);
136 1.1 kochi }
137 1.1 kochi
138 1.1 kochi /*
139 1.1 kochi * AcpiOsDeleteSemaphore:
140 1.1 kochi *
141 1.1 kochi * Delete a semaphore.
142 1.1 kochi */
143 1.1 kochi ACPI_STATUS
144 1.1 kochi AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
145 1.1 kochi {
146 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
147 1.1 kochi
148 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
149 1.1 kochi
150 1.1 kochi if (as == NULL)
151 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
152 1.1 kochi
153 1.7 ad cv_destroy(&as->as_cv);
154 1.6 xtraeme mutex_destroy(&as->as_slock);
155 1.1 kochi free(as, M_ACPI);
156 1.1 kochi
157 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as));
158 1.1 kochi
159 1.1 kochi return_ACPI_STATUS(AE_OK);
160 1.1 kochi }
161 1.1 kochi
162 1.1 kochi /*
163 1.1 kochi * AcpiOsWaitSemaphore:
164 1.1 kochi *
165 1.1 kochi * Wait for units from a semaphore.
166 1.1 kochi */
167 1.1 kochi ACPI_STATUS
168 1.1 kochi AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
169 1.1 kochi {
170 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
171 1.1 kochi ACPI_STATUS rv;
172 1.1 kochi int timo, error;
173 1.1 kochi
174 1.1 kochi /*
175 1.1 kochi * This implementation has a bug: It has to stall for the entire
176 1.1 kochi * timeout before it will return AE_TIME. A better implementation
177 1.1 kochi * would adjust the amount of time left after being awakened.
178 1.1 kochi */
179 1.1 kochi
180 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
181 1.1 kochi
182 1.1 kochi if (as == NULL)
183 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
184 1.1 kochi
185 1.1 kochi /* A timeout of 0xFFFF means "forever". */
186 1.1 kochi if (Timeout == 0xFFFF)
187 1.1 kochi timo = 0;
188 1.1 kochi else {
189 1.1 kochi /* Compute the timeout using uSec per tick. */
190 1.1 kochi timo = (Timeout * 1000) / (1000000 / hz);
191 1.1 kochi if (timo <= 0)
192 1.1 kochi timo = 1;
193 1.1 kochi }
194 1.1 kochi
195 1.4 xtraeme mutex_enter(&as->as_slock);
196 1.1 kochi
197 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
198 1.1 kochi "get %d units from semaphore %p (has %d) timeout %d\n",
199 1.1 kochi Units, as, as->as_units, Timeout));
200 1.1 kochi
201 1.1 kochi for (;;) {
202 1.1 kochi if (as->as_units >= Units) {
203 1.1 kochi as->as_units -= Units;
204 1.1 kochi rv = AE_OK;
205 1.1 kochi break;
206 1.1 kochi }
207 1.1 kochi
208 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
209 1.1 kochi "semaphore blocked, sleeping %d ticks\n", timo));
210 1.1 kochi
211 1.5 xtraeme error = cv_timedwait(&as->as_cv, &as->as_slock, timo);
212 1.1 kochi if (error == EWOULDBLOCK) {
213 1.1 kochi rv = AE_TIME;
214 1.1 kochi break;
215 1.1 kochi }
216 1.1 kochi }
217 1.1 kochi
218 1.4 xtraeme mutex_exit(&as->as_slock);
219 1.1 kochi
220 1.1 kochi return_ACPI_STATUS(rv);
221 1.1 kochi }
222 1.1 kochi
223 1.1 kochi /*
224 1.1 kochi * AcpiOsSignalSemaphore:
225 1.1 kochi *
226 1.1 kochi * Send units to a semaphore.
227 1.1 kochi */
228 1.1 kochi ACPI_STATUS
229 1.1 kochi AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
230 1.1 kochi {
231 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
232 1.1 kochi
233 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
234 1.1 kochi
235 1.1 kochi if (as == NULL)
236 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
237 1.1 kochi
238 1.4 xtraeme mutex_enter(&as->as_slock);
239 1.1 kochi
240 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
241 1.1 kochi "return %d units to semaphore %p (has %d)\n",
242 1.1 kochi Units, as, as->as_units));
243 1.1 kochi
244 1.1 kochi as->as_units += Units;
245 1.1 kochi if (as->as_units > as->as_maxunits)
246 1.1 kochi as->as_units = as->as_maxunits;
247 1.4 xtraeme cv_broadcast(&as->as_cv);
248 1.1 kochi
249 1.4 xtraeme mutex_exit(&as->as_slock);
250 1.1 kochi
251 1.1 kochi return_ACPI_STATUS(AE_OK);
252 1.1 kochi }
253 1.1 kochi
254 1.1 kochi /*
255 1.1 kochi * AcpiOsCreateLock:
256 1.1 kochi *
257 1.1 kochi * Create a lock.
258 1.1 kochi */
259 1.1 kochi ACPI_STATUS
260 1.1 kochi AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
261 1.1 kochi {
262 1.1 kochi struct acpi_lock *al;
263 1.1 kochi
264 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
265 1.1 kochi
266 1.1 kochi if (OutHandle == NULL)
267 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
268 1.1 kochi
269 1.1 kochi al = malloc(sizeof(*al), M_ACPI, M_NOWAIT);
270 1.1 kochi if (al == NULL)
271 1.1 kochi return_ACPI_STATUS(AE_NO_MEMORY);
272 1.1 kochi
273 1.7 ad mutex_init(&al->al_slock, MUTEX_DRIVER, IPL_VM);
274 1.1 kochi
275 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
276 1.1 kochi "created lock %p\n", al));
277 1.1 kochi
278 1.1 kochi *OutHandle = (ACPI_HANDLE) al;
279 1.1 kochi return_ACPI_STATUS(AE_OK);
280 1.1 kochi }
281 1.1 kochi
282 1.1 kochi /*
283 1.1 kochi * AcpiOsDeleteLock:
284 1.1 kochi *
285 1.1 kochi * Delete a lock.
286 1.1 kochi */
287 1.1 kochi void
288 1.1 kochi AcpiOsDeleteLock(ACPI_HANDLE Handle)
289 1.1 kochi {
290 1.1 kochi struct acpi_lock *al = (void *) Handle;
291 1.1 kochi
292 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
293 1.1 kochi
294 1.1 kochi if (al == NULL)
295 1.1 kochi return;
296 1.1 kochi
297 1.6 xtraeme mutex_destroy(&al->al_slock);
298 1.1 kochi free(al, M_ACPI);
299 1.1 kochi
300 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed lock %p\n", al));
301 1.1 kochi
302 1.1 kochi return;
303 1.1 kochi }
304 1.1 kochi
305 1.1 kochi /*
306 1.1 kochi * AcpiOsAcquireLock:
307 1.1 kochi *
308 1.1 kochi * Acquire a lock.
309 1.1 kochi */
310 1.1 kochi ACPI_NATIVE_UINT
311 1.1 kochi AcpiOsAcquireLock(ACPI_HANDLE Handle)
312 1.1 kochi {
313 1.1 kochi struct acpi_lock *al = (void *) Handle;
314 1.1 kochi
315 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
316 1.1 kochi
317 1.1 kochi if (al == NULL)
318 1.1 kochi return 0;
319 1.1 kochi
320 1.4 xtraeme mutex_enter(&al->al_slock);
321 1.1 kochi
322 1.1 kochi return 0;
323 1.1 kochi }
324 1.1 kochi
325 1.1 kochi /*
326 1.1 kochi * AcpiOsReleaseLock:
327 1.1 kochi *
328 1.1 kochi * Release a lock.
329 1.1 kochi */
330 1.1 kochi void
331 1.3 christos AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_NATIVE_UINT Flags)
332 1.1 kochi {
333 1.1 kochi struct acpi_lock *al = (void *) Handle;
334 1.1 kochi
335 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
336 1.1 kochi
337 1.1 kochi if (al == NULL)
338 1.1 kochi return;
339 1.1 kochi
340 1.4 xtraeme mutex_exit(&al->al_slock);
341 1.1 kochi
342 1.1 kochi return;
343 1.1 kochi }
344