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