0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "acevents.h"
0014
0015 #define _COMPONENT ACPI_EXECUTER
0016 ACPI_MODULE_NAME("exmutex")
0017
0018
0019 static void
0020 acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
0021 struct acpi_thread_state *thread);
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
0036 {
0037 struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
0038
0039 if (!thread) {
0040 return;
0041 }
0042
0043
0044
0045 if (obj_desc->mutex.next) {
0046 (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
0047 }
0048
0049 if (obj_desc->mutex.prev) {
0050 (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
0051
0052
0053
0054
0055
0056
0057
0058 (obj_desc->mutex.prev)->mutex.original_sync_level =
0059 obj_desc->mutex.original_sync_level;
0060 } else {
0061 thread->acquired_mutex_list = obj_desc->mutex.next;
0062 }
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 static void
0079 acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
0080 struct acpi_thread_state *thread)
0081 {
0082 union acpi_operand_object *list_head;
0083
0084 list_head = thread->acquired_mutex_list;
0085
0086
0087
0088 obj_desc->mutex.prev = NULL;
0089 obj_desc->mutex.next = list_head;
0090
0091
0092
0093 if (list_head) {
0094 list_head->mutex.prev = obj_desc;
0095 }
0096
0097
0098
0099 thread->acquired_mutex_list = obj_desc;
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 acpi_status
0126 acpi_ex_acquire_mutex_object(u16 timeout,
0127 union acpi_operand_object *obj_desc,
0128 acpi_thread_id thread_id)
0129 {
0130 acpi_status status;
0131
0132 ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
0133
0134 if (!obj_desc) {
0135 return_ACPI_STATUS(AE_BAD_PARAMETER);
0136 }
0137
0138
0139
0140 if (obj_desc->mutex.thread_id == thread_id) {
0141
0142
0143
0144
0145 obj_desc->mutex.acquisition_depth++;
0146 return_ACPI_STATUS(AE_OK);
0147 }
0148
0149
0150
0151 if (obj_desc == acpi_gbl_global_lock_mutex) {
0152 status = acpi_ev_acquire_global_lock(timeout);
0153 } else {
0154 status =
0155 acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
0156 timeout);
0157 }
0158
0159 if (ACPI_FAILURE(status)) {
0160
0161
0162
0163 return_ACPI_STATUS(status);
0164 }
0165
0166
0167
0168 obj_desc->mutex.thread_id = thread_id;
0169 obj_desc->mutex.acquisition_depth = 1;
0170 obj_desc->mutex.original_sync_level = 0;
0171 obj_desc->mutex.owner_thread = NULL;
0172
0173 return_ACPI_STATUS(AE_OK);
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 acpi_status
0191 acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
0192 union acpi_operand_object *obj_desc,
0193 struct acpi_walk_state *walk_state)
0194 {
0195 acpi_status status;
0196
0197 ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc);
0198
0199 if (!obj_desc) {
0200 return_ACPI_STATUS(AE_BAD_PARAMETER);
0201 }
0202
0203
0204
0205 if (!walk_state->thread) {
0206 ACPI_ERROR((AE_INFO,
0207 "Cannot acquire Mutex [%4.4s], null thread info",
0208 acpi_ut_get_node_name(obj_desc->mutex.node)));
0209 return_ACPI_STATUS(AE_AML_INTERNAL);
0210 }
0211
0212
0213
0214
0215
0216 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
0217 ACPI_ERROR((AE_INFO,
0218 "Cannot acquire Mutex [%4.4s], "
0219 "current SyncLevel is too large (%u)",
0220 acpi_ut_get_node_name(obj_desc->mutex.node),
0221 walk_state->thread->current_sync_level));
0222 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
0223 }
0224
0225 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0226 "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, "
0227 "Depth %u TID %p\n",
0228 obj_desc->mutex.sync_level,
0229 walk_state->thread->current_sync_level,
0230 obj_desc->mutex.acquisition_depth,
0231 walk_state->thread));
0232
0233 status = acpi_ex_acquire_mutex_object((u16)time_desc->integer.value,
0234 obj_desc,
0235 walk_state->thread->thread_id);
0236
0237 if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
0238
0239
0240
0241 obj_desc->mutex.owner_thread = walk_state->thread;
0242 obj_desc->mutex.original_sync_level =
0243 walk_state->thread->current_sync_level;
0244 walk_state->thread->current_sync_level =
0245 obj_desc->mutex.sync_level;
0246
0247
0248
0249 acpi_ex_link_mutex(obj_desc, walk_state->thread);
0250 }
0251
0252 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0253 "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n",
0254 obj_desc->mutex.sync_level,
0255 walk_state->thread->current_sync_level,
0256 obj_desc->mutex.acquisition_depth));
0257
0258 return_ACPI_STATUS(status);
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
0284 {
0285 acpi_status status = AE_OK;
0286
0287 ACPI_FUNCTION_TRACE(ex_release_mutex_object);
0288
0289 if (obj_desc->mutex.acquisition_depth == 0) {
0290 return_ACPI_STATUS(AE_NOT_ACQUIRED);
0291 }
0292
0293
0294
0295 obj_desc->mutex.acquisition_depth--;
0296 if (obj_desc->mutex.acquisition_depth != 0) {
0297
0298
0299
0300 return_ACPI_STATUS(AE_OK);
0301 }
0302
0303 if (obj_desc->mutex.owner_thread) {
0304
0305
0306
0307 acpi_ex_unlink_mutex(obj_desc);
0308 obj_desc->mutex.owner_thread = NULL;
0309 }
0310
0311
0312
0313 if (obj_desc == acpi_gbl_global_lock_mutex) {
0314 status = acpi_ev_release_global_lock();
0315 } else {
0316 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
0317 }
0318
0319
0320
0321 obj_desc->mutex.thread_id = 0;
0322 return_ACPI_STATUS(status);
0323 }
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338 acpi_status
0339 acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
0340 struct acpi_walk_state *walk_state)
0341 {
0342 u8 previous_sync_level;
0343 struct acpi_thread_state *owner_thread;
0344 acpi_status status = AE_OK;
0345
0346 ACPI_FUNCTION_TRACE(ex_release_mutex);
0347
0348 if (!obj_desc) {
0349 return_ACPI_STATUS(AE_BAD_PARAMETER);
0350 }
0351
0352 owner_thread = obj_desc->mutex.owner_thread;
0353
0354
0355
0356 if (!owner_thread) {
0357 ACPI_ERROR((AE_INFO,
0358 "Cannot release Mutex [%4.4s], not acquired",
0359 acpi_ut_get_node_name(obj_desc->mutex.node)));
0360 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
0361 }
0362
0363
0364
0365 if (!walk_state->thread) {
0366 ACPI_ERROR((AE_INFO,
0367 "Cannot release Mutex [%4.4s], null thread info",
0368 acpi_ut_get_node_name(obj_desc->mutex.node)));
0369 return_ACPI_STATUS(AE_AML_INTERNAL);
0370 }
0371
0372
0373
0374
0375
0376 if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
0377 (obj_desc != acpi_gbl_global_lock_mutex)) {
0378 ACPI_ERROR((AE_INFO,
0379 "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
0380 (u32)walk_state->thread->thread_id,
0381 acpi_ut_get_node_name(obj_desc->mutex.node),
0382 (u32)owner_thread->thread_id));
0383 return_ACPI_STATUS(AE_AML_NOT_OWNER);
0384 }
0385
0386
0387
0388
0389
0390
0391
0392
0393 if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
0394 ACPI_ERROR((AE_INFO,
0395 "Cannot release Mutex [%4.4s], SyncLevel mismatch: "
0396 "mutex %u current %u",
0397 acpi_ut_get_node_name(obj_desc->mutex.node),
0398 obj_desc->mutex.sync_level,
0399 walk_state->thread->current_sync_level));
0400 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
0401 }
0402
0403
0404
0405
0406
0407
0408 previous_sync_level =
0409 owner_thread->acquired_mutex_list->mutex.original_sync_level;
0410
0411 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0412 "Releasing: Object SyncLevel %u, Thread SyncLevel %u, "
0413 "Prev SyncLevel %u, Depth %u TID %p\n",
0414 obj_desc->mutex.sync_level,
0415 walk_state->thread->current_sync_level,
0416 previous_sync_level,
0417 obj_desc->mutex.acquisition_depth,
0418 walk_state->thread));
0419
0420 status = acpi_ex_release_mutex_object(obj_desc);
0421 if (ACPI_FAILURE(status)) {
0422 return_ACPI_STATUS(status);
0423 }
0424
0425 if (obj_desc->mutex.acquisition_depth == 0) {
0426
0427
0428
0429 owner_thread->current_sync_level = previous_sync_level;
0430 }
0431
0432 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0433 "Released: Object SyncLevel %u, Thread SyncLevel, %u, "
0434 "Prev SyncLevel %u, Depth %u\n",
0435 obj_desc->mutex.sync_level,
0436 walk_state->thread->current_sync_level,
0437 previous_sync_level,
0438 obj_desc->mutex.acquisition_depth));
0439
0440 return_ACPI_STATUS(status);
0441 }
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
0462 {
0463 union acpi_operand_object *next = thread->acquired_mutex_list;
0464 union acpi_operand_object *obj_desc;
0465
0466 ACPI_FUNCTION_TRACE(ex_release_all_mutexes);
0467
0468
0469
0470 while (next) {
0471 obj_desc = next;
0472 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0473 "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n",
0474 obj_desc->mutex.node->name.ascii,
0475 obj_desc->mutex.sync_level,
0476 obj_desc->mutex.acquisition_depth));
0477
0478
0479
0480 if (obj_desc == acpi_gbl_global_lock_mutex) {
0481
0482
0483
0484 (void)acpi_ev_release_global_lock();
0485 } else {
0486 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
0487 }
0488
0489
0490
0491 thread->current_sync_level =
0492 obj_desc->mutex.original_sync_level;
0493
0494
0495
0496 next = obj_desc->mutex.next;
0497
0498 obj_desc->mutex.prev = NULL;
0499 obj_desc->mutex.next = NULL;
0500 obj_desc->mutex.acquisition_depth = 0;
0501 obj_desc->mutex.owner_thread = NULL;
0502 obj_desc->mutex.thread_id = 0;
0503 }
0504
0505 return_VOID;
0506 }