OsdSynch.c revision 1.6 1 1.6 xtraeme /* $NetBSD: OsdSynch.c,v 1.6 2007/02/19 12:29:24 xtraeme 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.6 xtraeme __KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.6 2007/02/19 12:29:24 xtraeme 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.6 xtraeme mutex_destroy(&as->as_slock);
154 1.1 kochi free(as, M_ACPI);
155 1.1 kochi
156 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as));
157 1.1 kochi
158 1.1 kochi return_ACPI_STATUS(AE_OK);
159 1.1 kochi }
160 1.1 kochi
161 1.1 kochi /*
162 1.1 kochi * AcpiOsWaitSemaphore:
163 1.1 kochi *
164 1.1 kochi * Wait for units from a semaphore.
165 1.1 kochi */
166 1.1 kochi ACPI_STATUS
167 1.1 kochi AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
168 1.1 kochi {
169 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
170 1.1 kochi ACPI_STATUS rv;
171 1.1 kochi int timo, error;
172 1.1 kochi
173 1.1 kochi /*
174 1.1 kochi * This implementation has a bug: It has to stall for the entire
175 1.1 kochi * timeout before it will return AE_TIME. A better implementation
176 1.1 kochi * would adjust the amount of time left after being awakened.
177 1.1 kochi */
178 1.1 kochi
179 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
180 1.1 kochi
181 1.1 kochi if (as == NULL)
182 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
183 1.1 kochi
184 1.1 kochi /* A timeout of 0xFFFF means "forever". */
185 1.1 kochi if (Timeout == 0xFFFF)
186 1.1 kochi timo = 0;
187 1.1 kochi else {
188 1.1 kochi /* Compute the timeout using uSec per tick. */
189 1.1 kochi timo = (Timeout * 1000) / (1000000 / hz);
190 1.1 kochi if (timo <= 0)
191 1.1 kochi timo = 1;
192 1.1 kochi }
193 1.1 kochi
194 1.4 xtraeme mutex_enter(&as->as_slock);
195 1.1 kochi
196 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
197 1.1 kochi "get %d units from semaphore %p (has %d) timeout %d\n",
198 1.1 kochi Units, as, as->as_units, Timeout));
199 1.1 kochi
200 1.1 kochi for (;;) {
201 1.1 kochi if (as->as_units >= Units) {
202 1.1 kochi as->as_units -= Units;
203 1.1 kochi rv = AE_OK;
204 1.1 kochi break;
205 1.1 kochi }
206 1.1 kochi
207 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
208 1.1 kochi "semaphore blocked, sleeping %d ticks\n", timo));
209 1.1 kochi
210 1.5 xtraeme error = cv_timedwait(&as->as_cv, &as->as_slock, timo);
211 1.1 kochi if (error == EWOULDBLOCK) {
212 1.1 kochi rv = AE_TIME;
213 1.1 kochi break;
214 1.1 kochi }
215 1.1 kochi }
216 1.1 kochi
217 1.4 xtraeme mutex_exit(&as->as_slock);
218 1.1 kochi
219 1.1 kochi return_ACPI_STATUS(rv);
220 1.1 kochi }
221 1.1 kochi
222 1.1 kochi /*
223 1.1 kochi * AcpiOsSignalSemaphore:
224 1.1 kochi *
225 1.1 kochi * Send units to a semaphore.
226 1.1 kochi */
227 1.1 kochi ACPI_STATUS
228 1.1 kochi AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
229 1.1 kochi {
230 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
231 1.1 kochi
232 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
233 1.1 kochi
234 1.1 kochi if (as == NULL)
235 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
236 1.1 kochi
237 1.4 xtraeme mutex_enter(&as->as_slock);
238 1.1 kochi
239 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
240 1.1 kochi "return %d units to semaphore %p (has %d)\n",
241 1.1 kochi Units, as, as->as_units));
242 1.1 kochi
243 1.1 kochi as->as_units += Units;
244 1.1 kochi if (as->as_units > as->as_maxunits)
245 1.1 kochi as->as_units = as->as_maxunits;
246 1.4 xtraeme cv_broadcast(&as->as_cv);
247 1.1 kochi
248 1.4 xtraeme mutex_exit(&as->as_slock);
249 1.1 kochi
250 1.1 kochi return_ACPI_STATUS(AE_OK);
251 1.1 kochi }
252 1.1 kochi
253 1.1 kochi /*
254 1.1 kochi * AcpiOsCreateLock:
255 1.1 kochi *
256 1.1 kochi * Create a lock.
257 1.1 kochi */
258 1.1 kochi ACPI_STATUS
259 1.1 kochi AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
260 1.1 kochi {
261 1.1 kochi struct acpi_lock *al;
262 1.1 kochi
263 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
264 1.1 kochi
265 1.1 kochi if (OutHandle == NULL)
266 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
267 1.1 kochi
268 1.1 kochi al = malloc(sizeof(*al), M_ACPI, M_NOWAIT);
269 1.1 kochi if (al == NULL)
270 1.1 kochi return_ACPI_STATUS(AE_NO_MEMORY);
271 1.1 kochi
272 1.4 xtraeme mutex_init(&al->al_slock, MUTEX_DRIVER, IPL_NONE);
273 1.1 kochi
274 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
275 1.1 kochi "created lock %p\n", al));
276 1.1 kochi
277 1.1 kochi *OutHandle = (ACPI_HANDLE) al;
278 1.1 kochi return_ACPI_STATUS(AE_OK);
279 1.1 kochi }
280 1.1 kochi
281 1.1 kochi /*
282 1.1 kochi * AcpiOsDeleteLock:
283 1.1 kochi *
284 1.1 kochi * Delete a lock.
285 1.1 kochi */
286 1.1 kochi void
287 1.1 kochi AcpiOsDeleteLock(ACPI_HANDLE Handle)
288 1.1 kochi {
289 1.1 kochi struct acpi_lock *al = (void *) Handle;
290 1.1 kochi
291 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
292 1.1 kochi
293 1.1 kochi if (al == NULL)
294 1.1 kochi return;
295 1.1 kochi
296 1.6 xtraeme mutex_destroy(&al->al_slock);
297 1.1 kochi free(al, M_ACPI);
298 1.1 kochi
299 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed lock %p\n", al));
300 1.1 kochi
301 1.1 kochi return;
302 1.1 kochi }
303 1.1 kochi
304 1.1 kochi /*
305 1.1 kochi * AcpiOsAcquireLock:
306 1.1 kochi *
307 1.1 kochi * Acquire a lock.
308 1.1 kochi */
309 1.1 kochi ACPI_NATIVE_UINT
310 1.1 kochi AcpiOsAcquireLock(ACPI_HANDLE Handle)
311 1.1 kochi {
312 1.1 kochi struct acpi_lock *al = (void *) Handle;
313 1.1 kochi
314 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
315 1.1 kochi
316 1.1 kochi if (al == NULL)
317 1.1 kochi return 0;
318 1.1 kochi
319 1.4 xtraeme mutex_enter(&al->al_slock);
320 1.1 kochi
321 1.1 kochi return 0;
322 1.1 kochi }
323 1.1 kochi
324 1.1 kochi /*
325 1.1 kochi * AcpiOsReleaseLock:
326 1.1 kochi *
327 1.1 kochi * Release a lock.
328 1.1 kochi */
329 1.1 kochi void
330 1.3 christos AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_NATIVE_UINT Flags)
331 1.1 kochi {
332 1.1 kochi struct acpi_lock *al = (void *) Handle;
333 1.1 kochi
334 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
335 1.1 kochi
336 1.1 kochi if (al == NULL)
337 1.1 kochi return;
338 1.1 kochi
339 1.4 xtraeme mutex_exit(&al->al_slock);
340 1.1 kochi
341 1.1 kochi return;
342 1.1 kochi }
343