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