1 /* $NetBSD: OsdSynch.c,v 1.1 2006/03/23 13:41:13 kochi 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.1 2006/03/23 13:41:13 kochi 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