Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /*******************************************************************************
3 : : *
4 : : * Module Name: utmutex - local mutex support
5 : : *
6 : : ******************************************************************************/
7 : :
8 : : #include <acpi/acpi.h>
9 : : #include "accommon.h"
10 : :
11 : : #define _COMPONENT ACPI_UTILITIES
12 : : ACPI_MODULE_NAME("utmutex")
13 : :
14 : : /* Local prototypes */
15 : : static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
16 : :
17 : : static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
18 : :
19 : : /*******************************************************************************
20 : : *
21 : : * FUNCTION: acpi_ut_mutex_initialize
22 : : *
23 : : * PARAMETERS: None.
24 : : *
25 : : * RETURN: Status
26 : : *
27 : : * DESCRIPTION: Create the system mutex objects. This includes mutexes,
28 : : * spin locks, and reader/writer locks.
29 : : *
30 : : ******************************************************************************/
31 : :
32 : 30 : acpi_status acpi_ut_mutex_initialize(void)
33 : : {
34 : 30 : u32 i;
35 : 30 : acpi_status status;
36 : :
37 : 30 : ACPI_FUNCTION_TRACE(ut_mutex_initialize);
38 : :
39 : : /* Create each of the predefined mutex objects */
40 : :
41 [ + + ]: 210 : for (i = 0; i < ACPI_NUM_MUTEX; i++) {
42 : 180 : status = acpi_ut_create_mutex(i);
43 [ - + ]: 180 : if (ACPI_FAILURE(status)) {
44 : 0 : return_ACPI_STATUS(status);
45 : : }
46 : : }
47 : :
48 : : /* Create the spinlocks for use at interrupt level or for speed */
49 : :
50 [ + - + - ]: 30 : status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
51 : 30 : if (ACPI_FAILURE (status)) {
52 : : return_ACPI_STATUS (status);
53 : : }
54 : :
55 [ + - + - ]: 30 : status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock);
56 : 30 : if (ACPI_FAILURE (status)) {
57 : : return_ACPI_STATUS (status);
58 : : }
59 : :
60 [ + - + - ]: 30 : status = acpi_os_create_lock(&acpi_gbl_reference_count_lock);
61 : 30 : if (ACPI_FAILURE(status)) {
62 : : return_ACPI_STATUS(status);
63 : : }
64 : :
65 : : /* Mutex for _OSI support */
66 : :
67 : 30 : status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
68 [ + - ]: 30 : if (ACPI_FAILURE(status)) {
69 : : return_ACPI_STATUS(status);
70 : : }
71 : :
72 : : /* Create the reader/writer lock for namespace access */
73 : :
74 : 30 : status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
75 : 30 : if (ACPI_FAILURE(status)) {
76 : : return_ACPI_STATUS(status);
77 : : }
78 : :
79 : : return_ACPI_STATUS(status);
80 : : }
81 : :
82 : : /*******************************************************************************
83 : : *
84 : : * FUNCTION: acpi_ut_mutex_terminate
85 : : *
86 : : * PARAMETERS: None.
87 : : *
88 : : * RETURN: None.
89 : : *
90 : : * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
91 : : * spin locks, and reader/writer locks.
92 : : *
93 : : ******************************************************************************/
94 : :
95 : 0 : void acpi_ut_mutex_terminate(void)
96 : : {
97 : 0 : u32 i;
98 : :
99 : 0 : ACPI_FUNCTION_TRACE(ut_mutex_terminate);
100 : :
101 : : /* Delete each predefined mutex object */
102 : :
103 [ # # ]: 0 : for (i = 0; i < ACPI_NUM_MUTEX; i++) {
104 : 0 : acpi_ut_delete_mutex(i);
105 : : }
106 : :
107 : 0 : acpi_os_delete_mutex(acpi_gbl_osi_mutex);
108 : :
109 : : /* Delete the spinlocks */
110 : :
111 : 0 : acpi_os_delete_lock(acpi_gbl_gpe_lock);
112 : 0 : acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
113 : 0 : acpi_os_delete_lock(acpi_gbl_reference_count_lock);
114 : :
115 : : /* Delete the reader/writer lock */
116 : :
117 : 0 : acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
118 : 0 : return_VOID;
119 : : }
120 : :
121 : : /*******************************************************************************
122 : : *
123 : : * FUNCTION: acpi_ut_create_mutex
124 : : *
125 : : * PARAMETERS: mutex_ID - ID of the mutex to be created
126 : : *
127 : : * RETURN: Status
128 : : *
129 : : * DESCRIPTION: Create a mutex object.
130 : : *
131 : : ******************************************************************************/
132 : :
133 : 180 : static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
134 : : {
135 : 180 : acpi_status status = AE_OK;
136 : :
137 : 180 : ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
138 : :
139 [ + - ]: 180 : if (!acpi_gbl_mutex_info[mutex_id].mutex) {
140 : 180 : status =
141 : 180 : acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex);
142 : 180 : acpi_gbl_mutex_info[mutex_id].thread_id =
143 : : ACPI_MUTEX_NOT_ACQUIRED;
144 : 180 : acpi_gbl_mutex_info[mutex_id].use_count = 0;
145 : : }
146 : :
147 : 180 : return_ACPI_STATUS(status);
148 : : }
149 : :
150 : : /*******************************************************************************
151 : : *
152 : : * FUNCTION: acpi_ut_delete_mutex
153 : : *
154 : : * PARAMETERS: mutex_ID - ID of the mutex to be deleted
155 : : *
156 : : * RETURN: Status
157 : : *
158 : : * DESCRIPTION: Delete a mutex object.
159 : : *
160 : : ******************************************************************************/
161 : :
162 : 0 : static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
163 : : {
164 : :
165 : 0 : ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
166 : :
167 : 0 : acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
168 : :
169 : 0 : acpi_gbl_mutex_info[mutex_id].mutex = NULL;
170 : 0 : acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
171 : :
172 : 0 : return_VOID;
173 : : }
174 : :
175 : : /*******************************************************************************
176 : : *
177 : : * FUNCTION: acpi_ut_acquire_mutex
178 : : *
179 : : * PARAMETERS: mutex_ID - ID of the mutex to be acquired
180 : : *
181 : : * RETURN: Status
182 : : *
183 : : * DESCRIPTION: Acquire a mutex object.
184 : : *
185 : : ******************************************************************************/
186 : :
187 : 361500 : acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
188 : : {
189 : 361500 : acpi_status status;
190 : 361500 : acpi_thread_id this_thread_id;
191 : :
192 : 361500 : ACPI_FUNCTION_NAME(ut_acquire_mutex);
193 : :
194 [ + - ]: 361500 : if (mutex_id > ACPI_MAX_MUTEX) {
195 : : return (AE_BAD_PARAMETER);
196 : : }
197 : :
198 : 361500 : this_thread_id = acpi_os_get_thread_id();
199 : :
200 : : #ifdef ACPI_MUTEX_DEBUG
201 : : {
202 : : u32 i;
203 : : /*
204 : : * Mutex debug code, for internal debugging only.
205 : : *
206 : : * Deadlock prevention. Check if this thread owns any mutexes of value
207 : : * greater than or equal to this one. If so, the thread has violated
208 : : * the mutex ordering rule. This indicates a coding error somewhere in
209 : : * the ACPI subsystem code.
210 : : */
211 : : for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
212 : : if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
213 : : if (i == mutex_id) {
214 : : ACPI_ERROR((AE_INFO,
215 : : "Mutex [%s] already acquired by this thread [%u]",
216 : : acpi_ut_get_mutex_name
217 : : (mutex_id),
218 : : (u32)this_thread_id));
219 : :
220 : : return (AE_ALREADY_ACQUIRED);
221 : : }
222 : :
223 : : ACPI_ERROR((AE_INFO,
224 : : "Invalid acquire order: Thread %u owns [%s], wants [%s]",
225 : : (u32)this_thread_id,
226 : : acpi_ut_get_mutex_name(i),
227 : : acpi_ut_get_mutex_name(mutex_id)));
228 : :
229 : : return (AE_ACQUIRE_DEADLOCK);
230 : : }
231 : : }
232 : : }
233 : : #endif
234 : :
235 : : ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
236 : : "Thread %u attempting to acquire Mutex [%s]\n",
237 : : (u32)this_thread_id,
238 : 361500 : acpi_ut_get_mutex_name(mutex_id)));
239 : :
240 : 361500 : status =
241 : 361500 : acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
242 : : ACPI_WAIT_FOREVER);
243 [ + - ]: 361500 : if (ACPI_SUCCESS(status)) {
244 : : ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
245 : : "Thread %u acquired Mutex [%s]\n",
246 : : (u32)this_thread_id,
247 : 361500 : acpi_ut_get_mutex_name(mutex_id)));
248 : :
249 : 361500 : acpi_gbl_mutex_info[mutex_id].use_count++;
250 : 361500 : acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
251 : : } else {
252 : 0 : ACPI_EXCEPTION((AE_INFO, status,
253 : : "Thread %u could not acquire Mutex [%s] (0x%X)",
254 : : (u32)this_thread_id,
255 : : acpi_ut_get_mutex_name(mutex_id), mutex_id));
256 : : }
257 : :
258 : : return (status);
259 : : }
260 : :
261 : : /*******************************************************************************
262 : : *
263 : : * FUNCTION: acpi_ut_release_mutex
264 : : *
265 : : * PARAMETERS: mutex_ID - ID of the mutex to be released
266 : : *
267 : : * RETURN: Status
268 : : *
269 : : * DESCRIPTION: Release a mutex object.
270 : : *
271 : : ******************************************************************************/
272 : :
273 : 361500 : acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
274 : : {
275 : 361500 : ACPI_FUNCTION_NAME(ut_release_mutex);
276 : :
277 : : ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
278 : : (u32)acpi_os_get_thread_id(),
279 : 361500 : acpi_ut_get_mutex_name(mutex_id)));
280 : :
281 [ + - ]: 361500 : if (mutex_id > ACPI_MAX_MUTEX) {
282 : : return (AE_BAD_PARAMETER);
283 : : }
284 : :
285 : : /*
286 : : * Mutex must be acquired in order to release it!
287 : : */
288 [ - + ]: 361500 : if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
289 : 0 : ACPI_ERROR((AE_INFO,
290 : : "Mutex [%s] (0x%X) is not acquired, cannot release",
291 : : acpi_ut_get_mutex_name(mutex_id), mutex_id));
292 : :
293 : 0 : return (AE_NOT_ACQUIRED);
294 : : }
295 : : #ifdef ACPI_MUTEX_DEBUG
296 : : {
297 : : u32 i;
298 : : /*
299 : : * Mutex debug code, for internal debugging only.
300 : : *
301 : : * Deadlock prevention. Check if this thread owns any mutexes of value
302 : : * greater than this one. If so, the thread has violated the mutex
303 : : * ordering rule. This indicates a coding error somewhere in
304 : : * the ACPI subsystem code.
305 : : */
306 : : for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
307 : : if (acpi_gbl_mutex_info[i].thread_id ==
308 : : acpi_os_get_thread_id()) {
309 : : if (i == mutex_id) {
310 : : continue;
311 : : }
312 : :
313 : : ACPI_ERROR((AE_INFO,
314 : : "Invalid release order: owns [%s], releasing [%s]",
315 : : acpi_ut_get_mutex_name(i),
316 : : acpi_ut_get_mutex_name(mutex_id)));
317 : :
318 : : return (AE_RELEASE_DEADLOCK);
319 : : }
320 : : }
321 : : }
322 : : #endif
323 : :
324 : : /* Mark unlocked FIRST */
325 : :
326 : 361500 : acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
327 : :
328 : 361500 : acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
329 : 361500 : return (AE_OK);
330 : : }
|