diff options
Diffstat (limited to 'drivers/acpi/utilities/utmutex.c')
-rw-r--r-- | drivers/acpi/utilities/utmutex.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c new file mode 100644 index 00000000000..a80b97cb2e5 --- /dev/null +++ b/drivers/acpi/utilities/utmutex.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: utmutex - local mutex support | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_UTILITIES | ||
48 | ACPI_MODULE_NAME ("utmutex") | ||
49 | |||
50 | /* Local prototypes */ | ||
51 | |||
52 | static acpi_status | ||
53 | acpi_ut_create_mutex ( | ||
54 | acpi_mutex_handle mutex_id); | ||
55 | |||
56 | static acpi_status | ||
57 | acpi_ut_delete_mutex ( | ||
58 | acpi_mutex_handle mutex_id); | ||
59 | |||
60 | |||
61 | /******************************************************************************* | ||
62 | * | ||
63 | * FUNCTION: acpi_ut_mutex_initialize | ||
64 | * | ||
65 | * PARAMETERS: None. | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Create the system mutex objects. | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | |||
73 | acpi_status | ||
74 | acpi_ut_mutex_initialize ( | ||
75 | void) | ||
76 | { | ||
77 | u32 i; | ||
78 | acpi_status status; | ||
79 | |||
80 | |||
81 | ACPI_FUNCTION_TRACE ("ut_mutex_initialize"); | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Create each of the predefined mutex objects | ||
86 | */ | ||
87 | for (i = 0; i < NUM_MUTEX; i++) { | ||
88 | status = acpi_ut_create_mutex (i); | ||
89 | if (ACPI_FAILURE (status)) { | ||
90 | return_ACPI_STATUS (status); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | status = acpi_os_create_lock (&acpi_gbl_gpe_lock); | ||
95 | return_ACPI_STATUS (status); | ||
96 | } | ||
97 | |||
98 | |||
99 | /******************************************************************************* | ||
100 | * | ||
101 | * FUNCTION: acpi_ut_mutex_terminate | ||
102 | * | ||
103 | * PARAMETERS: None. | ||
104 | * | ||
105 | * RETURN: None. | ||
106 | * | ||
107 | * DESCRIPTION: Delete all of the system mutex objects. | ||
108 | * | ||
109 | ******************************************************************************/ | ||
110 | |||
111 | void | ||
112 | acpi_ut_mutex_terminate ( | ||
113 | void) | ||
114 | { | ||
115 | u32 i; | ||
116 | |||
117 | |||
118 | ACPI_FUNCTION_TRACE ("ut_mutex_terminate"); | ||
119 | |||
120 | |||
121 | /* | ||
122 | * Delete each predefined mutex object | ||
123 | */ | ||
124 | for (i = 0; i < NUM_MUTEX; i++) { | ||
125 | (void) acpi_ut_delete_mutex (i); | ||
126 | } | ||
127 | |||
128 | acpi_os_delete_lock (acpi_gbl_gpe_lock); | ||
129 | return_VOID; | ||
130 | } | ||
131 | |||
132 | |||
133 | /******************************************************************************* | ||
134 | * | ||
135 | * FUNCTION: acpi_ut_create_mutex | ||
136 | * | ||
137 | * PARAMETERS: mutex_iD - ID of the mutex to be created | ||
138 | * | ||
139 | * RETURN: Status | ||
140 | * | ||
141 | * DESCRIPTION: Create a mutex object. | ||
142 | * | ||
143 | ******************************************************************************/ | ||
144 | |||
145 | static acpi_status | ||
146 | acpi_ut_create_mutex ( | ||
147 | acpi_mutex_handle mutex_id) | ||
148 | { | ||
149 | acpi_status status = AE_OK; | ||
150 | |||
151 | |||
152 | ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id); | ||
153 | |||
154 | |||
155 | if (mutex_id > MAX_MUTEX) { | ||
156 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
157 | } | ||
158 | |||
159 | if (!acpi_gbl_mutex_info[mutex_id].mutex) { | ||
160 | status = acpi_os_create_semaphore (1, 1, | ||
161 | &acpi_gbl_mutex_info[mutex_id].mutex); | ||
162 | acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; | ||
163 | acpi_gbl_mutex_info[mutex_id].use_count = 0; | ||
164 | } | ||
165 | |||
166 | return_ACPI_STATUS (status); | ||
167 | } | ||
168 | |||
169 | |||
170 | /******************************************************************************* | ||
171 | * | ||
172 | * FUNCTION: acpi_ut_delete_mutex | ||
173 | * | ||
174 | * PARAMETERS: mutex_iD - ID of the mutex to be deleted | ||
175 | * | ||
176 | * RETURN: Status | ||
177 | * | ||
178 | * DESCRIPTION: Delete a mutex object. | ||
179 | * | ||
180 | ******************************************************************************/ | ||
181 | |||
182 | static acpi_status | ||
183 | acpi_ut_delete_mutex ( | ||
184 | acpi_mutex_handle mutex_id) | ||
185 | { | ||
186 | acpi_status status; | ||
187 | |||
188 | |||
189 | ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id); | ||
190 | |||
191 | |||
192 | if (mutex_id > MAX_MUTEX) { | ||
193 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
194 | } | ||
195 | |||
196 | status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex); | ||
197 | |||
198 | acpi_gbl_mutex_info[mutex_id].mutex = NULL; | ||
199 | acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; | ||
200 | |||
201 | return_ACPI_STATUS (status); | ||
202 | } | ||
203 | |||
204 | |||
205 | /******************************************************************************* | ||
206 | * | ||
207 | * FUNCTION: acpi_ut_acquire_mutex | ||
208 | * | ||
209 | * PARAMETERS: mutex_iD - ID of the mutex to be acquired | ||
210 | * | ||
211 | * RETURN: Status | ||
212 | * | ||
213 | * DESCRIPTION: Acquire a mutex object. | ||
214 | * | ||
215 | ******************************************************************************/ | ||
216 | |||
217 | acpi_status | ||
218 | acpi_ut_acquire_mutex ( | ||
219 | acpi_mutex_handle mutex_id) | ||
220 | { | ||
221 | acpi_status status; | ||
222 | u32 this_thread_id; | ||
223 | |||
224 | |||
225 | ACPI_FUNCTION_NAME ("ut_acquire_mutex"); | ||
226 | |||
227 | |||
228 | if (mutex_id > MAX_MUTEX) { | ||
229 | return (AE_BAD_PARAMETER); | ||
230 | } | ||
231 | |||
232 | this_thread_id = acpi_os_get_thread_id (); | ||
233 | |||
234 | #ifdef ACPI_MUTEX_DEBUG | ||
235 | { | ||
236 | u32 i; | ||
237 | /* | ||
238 | * Mutex debug code, for internal debugging only. | ||
239 | * | ||
240 | * Deadlock prevention. Check if this thread owns any mutexes of value | ||
241 | * greater than or equal to this one. If so, the thread has violated | ||
242 | * the mutex ordering rule. This indicates a coding error somewhere in | ||
243 | * the ACPI subsystem code. | ||
244 | */ | ||
245 | for (i = mutex_id; i < MAX_MUTEX; i++) { | ||
246 | if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { | ||
247 | if (i == mutex_id) { | ||
248 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
249 | "Mutex [%s] already acquired by this thread [%X]\n", | ||
250 | acpi_ut_get_mutex_name (mutex_id), this_thread_id)); | ||
251 | |||
252 | return (AE_ALREADY_ACQUIRED); | ||
253 | } | ||
254 | |||
255 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
256 | "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", | ||
257 | this_thread_id, acpi_ut_get_mutex_name (i), | ||
258 | acpi_ut_get_mutex_name (mutex_id))); | ||
259 | |||
260 | return (AE_ACQUIRE_DEADLOCK); | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | #endif | ||
265 | |||
266 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, | ||
267 | "Thread %X attempting to acquire Mutex [%s]\n", | ||
268 | this_thread_id, acpi_ut_get_mutex_name (mutex_id))); | ||
269 | |||
270 | status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, | ||
271 | 1, ACPI_WAIT_FOREVER); | ||
272 | if (ACPI_SUCCESS (status)) { | ||
273 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", | ||
274 | this_thread_id, acpi_ut_get_mutex_name (mutex_id))); | ||
275 | |||
276 | acpi_gbl_mutex_info[mutex_id].use_count++; | ||
277 | acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; | ||
278 | } | ||
279 | else { | ||
280 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
281 | "Thread %X could not acquire Mutex [%s] %s\n", | ||
282 | this_thread_id, acpi_ut_get_mutex_name (mutex_id), | ||
283 | acpi_format_exception (status))); | ||
284 | } | ||
285 | |||
286 | return (status); | ||
287 | } | ||
288 | |||
289 | |||
290 | /******************************************************************************* | ||
291 | * | ||
292 | * FUNCTION: acpi_ut_release_mutex | ||
293 | * | ||
294 | * PARAMETERS: mutex_iD - ID of the mutex to be released | ||
295 | * | ||
296 | * RETURN: Status | ||
297 | * | ||
298 | * DESCRIPTION: Release a mutex object. | ||
299 | * | ||
300 | ******************************************************************************/ | ||
301 | |||
302 | acpi_status | ||
303 | acpi_ut_release_mutex ( | ||
304 | acpi_mutex_handle mutex_id) | ||
305 | { | ||
306 | acpi_status status; | ||
307 | u32 this_thread_id; | ||
308 | |||
309 | |||
310 | ACPI_FUNCTION_NAME ("ut_release_mutex"); | ||
311 | |||
312 | |||
313 | this_thread_id = acpi_os_get_thread_id (); | ||
314 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, | ||
315 | "Thread %X releasing Mutex [%s]\n", this_thread_id, | ||
316 | acpi_ut_get_mutex_name (mutex_id))); | ||
317 | |||
318 | if (mutex_id > MAX_MUTEX) { | ||
319 | return (AE_BAD_PARAMETER); | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Mutex must be acquired in order to release it! | ||
324 | */ | ||
325 | if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { | ||
326 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
327 | "Mutex [%s] is not acquired, cannot release\n", | ||
328 | acpi_ut_get_mutex_name (mutex_id))); | ||
329 | |||
330 | return (AE_NOT_ACQUIRED); | ||
331 | } | ||
332 | |||
333 | #ifdef ACPI_MUTEX_DEBUG | ||
334 | { | ||
335 | u32 i; | ||
336 | /* | ||
337 | * Mutex debug code, for internal debugging only. | ||
338 | * | ||
339 | * Deadlock prevention. Check if this thread owns any mutexes of value | ||
340 | * greater than this one. If so, the thread has violated the mutex | ||
341 | * ordering rule. This indicates a coding error somewhere in | ||
342 | * the ACPI subsystem code. | ||
343 | */ | ||
344 | for (i = mutex_id; i < MAX_MUTEX; i++) { | ||
345 | if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { | ||
346 | if (i == mutex_id) { | ||
347 | continue; | ||
348 | } | ||
349 | |||
350 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
351 | "Invalid release order: owns [%s], releasing [%s]\n", | ||
352 | acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); | ||
353 | |||
354 | return (AE_RELEASE_DEADLOCK); | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | #endif | ||
359 | |||
360 | /* Mark unlocked FIRST */ | ||
361 | |||
362 | acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; | ||
363 | |||
364 | status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); | ||
365 | |||
366 | if (ACPI_FAILURE (status)) { | ||
367 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
368 | "Thread %X could not release Mutex [%s] %s\n", | ||
369 | this_thread_id, acpi_ut_get_mutex_name (mutex_id), | ||
370 | acpi_format_exception (status))); | ||
371 | } | ||
372 | else { | ||
373 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", | ||
374 | this_thread_id, acpi_ut_get_mutex_name (mutex_id))); | ||
375 | } | ||
376 | |||
377 | return (status); | ||
378 | } | ||
379 | |||
380 | |||