OsdSynch.c revision 1.1 1 1.1 kochi /* $NetBSD: OsdSynch.c,v 1.1 2006/03/23 13:41:13 kochi 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.1 kochi __KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.1 2006/03/23 13:41:13 kochi Exp $");
73 1.1 kochi
74 1.1 kochi #include <sys/param.h>
75 1.1 kochi #include <sys/malloc.h>
76 1.1 kochi #include <sys/lock.h>
77 1.1 kochi #include <sys/kernel.h>
78 1.1 kochi #include <sys/proc.h>
79 1.1 kochi
80 1.1 kochi #include <dev/acpi/acpica.h>
81 1.1 kochi
82 1.1 kochi MALLOC_DECLARE(M_ACPI);
83 1.1 kochi
84 1.1 kochi #define _COMPONENT ACPI_OS_SERVICES
85 1.1 kochi ACPI_MODULE_NAME("SYNCH")
86 1.1 kochi
87 1.1 kochi /*
88 1.1 kochi * Simple counting semaphore implemented using a mutex. This is
89 1.1 kochi * subsequently used in the OSI code to implement a mutex. Go figure.
90 1.1 kochi */
91 1.1 kochi struct acpi_semaphore {
92 1.1 kochi struct simplelock as_slock;
93 1.1 kochi UINT32 as_units;
94 1.1 kochi UINT32 as_maxunits;
95 1.1 kochi };
96 1.1 kochi
97 1.1 kochi struct acpi_lock {
98 1.1 kochi struct simplelock al_slock;
99 1.1 kochi };
100 1.1 kochi
101 1.1 kochi /*
102 1.1 kochi * AcpiOsCreateSemaphore:
103 1.1 kochi *
104 1.1 kochi * Create a semaphore.
105 1.1 kochi */
106 1.1 kochi ACPI_STATUS
107 1.1 kochi AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
108 1.1 kochi ACPI_HANDLE *OutHandle)
109 1.1 kochi {
110 1.1 kochi struct acpi_semaphore *as;
111 1.1 kochi
112 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
113 1.1 kochi
114 1.1 kochi if (OutHandle == NULL)
115 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
116 1.1 kochi if (InitialUnits > MaxUnits)
117 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
118 1.1 kochi
119 1.1 kochi as = malloc(sizeof(*as), M_ACPI, M_NOWAIT);
120 1.1 kochi if (as == NULL)
121 1.1 kochi return_ACPI_STATUS(AE_NO_MEMORY);
122 1.1 kochi
123 1.1 kochi simple_lock_init(&as->as_slock);
124 1.1 kochi as->as_units = InitialUnits;
125 1.1 kochi as->as_maxunits = MaxUnits;
126 1.1 kochi
127 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
128 1.1 kochi "created semaphore %p max %u initial %u\n",
129 1.1 kochi as, as->as_maxunits, as->as_units));
130 1.1 kochi
131 1.1 kochi *OutHandle = (ACPI_HANDLE) as;
132 1.1 kochi return_ACPI_STATUS(AE_OK);
133 1.1 kochi }
134 1.1 kochi
135 1.1 kochi /*
136 1.1 kochi * AcpiOsDeleteSemaphore:
137 1.1 kochi *
138 1.1 kochi * Delete a semaphore.
139 1.1 kochi */
140 1.1 kochi ACPI_STATUS
141 1.1 kochi AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
142 1.1 kochi {
143 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
144 1.1 kochi
145 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
146 1.1 kochi
147 1.1 kochi if (as == NULL)
148 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
149 1.1 kochi
150 1.1 kochi free(as, M_ACPI);
151 1.1 kochi
152 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as));
153 1.1 kochi
154 1.1 kochi return_ACPI_STATUS(AE_OK);
155 1.1 kochi }
156 1.1 kochi
157 1.1 kochi /*
158 1.1 kochi * AcpiOsWaitSemaphore:
159 1.1 kochi *
160 1.1 kochi * Wait for units from a semaphore.
161 1.1 kochi */
162 1.1 kochi ACPI_STATUS
163 1.1 kochi AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
164 1.1 kochi {
165 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
166 1.1 kochi ACPI_STATUS rv;
167 1.1 kochi int timo, error;
168 1.1 kochi
169 1.1 kochi /*
170 1.1 kochi * This implementation has a bug: It has to stall for the entire
171 1.1 kochi * timeout before it will return AE_TIME. A better implementation
172 1.1 kochi * would adjust the amount of time left after being awakened.
173 1.1 kochi */
174 1.1 kochi
175 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
176 1.1 kochi
177 1.1 kochi if (as == NULL)
178 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
179 1.1 kochi
180 1.1 kochi /* A timeout of 0xFFFF means "forever". */
181 1.1 kochi if (Timeout == 0xFFFF)
182 1.1 kochi timo = 0;
183 1.1 kochi else {
184 1.1 kochi /* Compute the timeout using uSec per tick. */
185 1.1 kochi timo = (Timeout * 1000) / (1000000 / hz);
186 1.1 kochi if (timo <= 0)
187 1.1 kochi timo = 1;
188 1.1 kochi }
189 1.1 kochi
190 1.1 kochi simple_lock(&as->as_slock);
191 1.1 kochi
192 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
193 1.1 kochi "get %d units from semaphore %p (has %d) timeout %d\n",
194 1.1 kochi Units, as, as->as_units, Timeout));
195 1.1 kochi
196 1.1 kochi for (;;) {
197 1.1 kochi if (as->as_units >= Units) {
198 1.1 kochi as->as_units -= Units;
199 1.1 kochi rv = AE_OK;
200 1.1 kochi break;
201 1.1 kochi }
202 1.1 kochi
203 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
204 1.1 kochi "semaphore blocked, sleeping %d ticks\n", timo));
205 1.1 kochi
206 1.1 kochi error = ltsleep(as, PVM, "acpisem", timo, &as->as_slock);
207 1.1 kochi if (error == EWOULDBLOCK) {
208 1.1 kochi rv = AE_TIME;
209 1.1 kochi break;
210 1.1 kochi }
211 1.1 kochi }
212 1.1 kochi
213 1.1 kochi simple_unlock(&as->as_slock);
214 1.1 kochi
215 1.1 kochi return_ACPI_STATUS(rv);
216 1.1 kochi }
217 1.1 kochi
218 1.1 kochi /*
219 1.1 kochi * AcpiOsSignalSemaphore:
220 1.1 kochi *
221 1.1 kochi * Send units to a semaphore.
222 1.1 kochi */
223 1.1 kochi ACPI_STATUS
224 1.1 kochi AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
225 1.1 kochi {
226 1.1 kochi struct acpi_semaphore *as = (void *) Handle;
227 1.1 kochi
228 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
229 1.1 kochi
230 1.1 kochi if (as == NULL)
231 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
232 1.1 kochi
233 1.1 kochi simple_lock(&as->as_slock);
234 1.1 kochi
235 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
236 1.1 kochi "return %d units to semaphore %p (has %d)\n",
237 1.1 kochi Units, as, as->as_units));
238 1.1 kochi
239 1.1 kochi as->as_units += Units;
240 1.1 kochi if (as->as_units > as->as_maxunits)
241 1.1 kochi as->as_units = as->as_maxunits;
242 1.1 kochi wakeup(as);
243 1.1 kochi
244 1.1 kochi simple_unlock(&as->as_slock);
245 1.1 kochi
246 1.1 kochi return_ACPI_STATUS(AE_OK);
247 1.1 kochi }
248 1.1 kochi
249 1.1 kochi /*
250 1.1 kochi * AcpiOsCreateLock:
251 1.1 kochi *
252 1.1 kochi * Create a lock.
253 1.1 kochi */
254 1.1 kochi ACPI_STATUS
255 1.1 kochi AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
256 1.1 kochi {
257 1.1 kochi struct acpi_lock *al;
258 1.1 kochi
259 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
260 1.1 kochi
261 1.1 kochi if (OutHandle == NULL)
262 1.1 kochi return_ACPI_STATUS(AE_BAD_PARAMETER);
263 1.1 kochi
264 1.1 kochi al = malloc(sizeof(*al), M_ACPI, M_NOWAIT);
265 1.1 kochi if (al == NULL)
266 1.1 kochi return_ACPI_STATUS(AE_NO_MEMORY);
267 1.1 kochi
268 1.1 kochi simple_lock_init(&al->al_slock);
269 1.1 kochi
270 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
271 1.1 kochi "created lock %p\n", al));
272 1.1 kochi
273 1.1 kochi *OutHandle = (ACPI_HANDLE) al;
274 1.1 kochi return_ACPI_STATUS(AE_OK);
275 1.1 kochi }
276 1.1 kochi
277 1.1 kochi /*
278 1.1 kochi * AcpiOsDeleteLock:
279 1.1 kochi *
280 1.1 kochi * Delete a lock.
281 1.1 kochi */
282 1.1 kochi void
283 1.1 kochi AcpiOsDeleteLock(ACPI_HANDLE Handle)
284 1.1 kochi {
285 1.1 kochi struct acpi_lock *al = (void *) Handle;
286 1.1 kochi
287 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
288 1.1 kochi
289 1.1 kochi if (al == NULL)
290 1.1 kochi return;
291 1.1 kochi
292 1.1 kochi free(al, M_ACPI);
293 1.1 kochi
294 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed lock %p\n", al));
295 1.1 kochi
296 1.1 kochi return;
297 1.1 kochi }
298 1.1 kochi
299 1.1 kochi /*
300 1.1 kochi * AcpiOsAcquireLock:
301 1.1 kochi *
302 1.1 kochi * Acquire a lock.
303 1.1 kochi */
304 1.1 kochi ACPI_NATIVE_UINT
305 1.1 kochi AcpiOsAcquireLock(ACPI_HANDLE Handle)
306 1.1 kochi {
307 1.1 kochi struct acpi_lock *al = (void *) Handle;
308 1.1 kochi
309 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
310 1.1 kochi
311 1.1 kochi if (al == NULL)
312 1.1 kochi return 0;
313 1.1 kochi
314 1.1 kochi simple_lock(&al->al_slock);
315 1.1 kochi
316 1.1 kochi return 0;
317 1.1 kochi }
318 1.1 kochi
319 1.1 kochi /*
320 1.1 kochi * AcpiOsReleaseLock:
321 1.1 kochi *
322 1.1 kochi * Release a lock.
323 1.1 kochi */
324 1.1 kochi void
325 1.1 kochi AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_NATIVE_UINT Flags)
326 1.1 kochi {
327 1.1 kochi struct acpi_lock *al = (void *) Handle;
328 1.1 kochi
329 1.1 kochi ACPI_FUNCTION_TRACE(__FUNCTION__);
330 1.1 kochi
331 1.1 kochi if (al == NULL)
332 1.1 kochi return;
333 1.1 kochi
334 1.1 kochi simple_unlock(&al->al_slock);
335 1.1 kochi
336 1.1 kochi return;
337 1.1 kochi }
338