0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acdebug.h"
0011 #include "acnamesp.h"
0012
0013 #define _COMPONENT ACPI_CA_DEBUGGER
0014 ACPI_MODULE_NAME("dbexec")
0015
0016 static struct acpi_db_method_info acpi_gbl_db_method_info;
0017
0018
0019
0020 static acpi_status
0021 acpi_db_execute_method(struct acpi_db_method_info *info,
0022 struct acpi_buffer *return_obj);
0023
0024 static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
0025
0026 static u32 acpi_db_get_outstanding_allocations(void);
0027
0028 static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
0029
0030 static acpi_status
0031 acpi_db_execution_walk(acpi_handle obj_handle,
0032 u32 nesting_level, void *context, void **return_value);
0033
0034 static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context);
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 void acpi_db_delete_objects(u32 count, union acpi_object *objects)
0051 {
0052 u32 i;
0053
0054 for (i = 0; i < count; i++) {
0055 switch (objects[i].type) {
0056 case ACPI_TYPE_BUFFER:
0057
0058 ACPI_FREE(objects[i].buffer.pointer);
0059 break;
0060
0061 case ACPI_TYPE_PACKAGE:
0062
0063
0064
0065 acpi_db_delete_objects(objects[i].package.count,
0066 objects[i].package.elements);
0067
0068
0069
0070 ACPI_FREE(objects[i].package.elements);
0071 break;
0072
0073 default:
0074
0075 break;
0076 }
0077 }
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static acpi_status
0095 acpi_db_execute_method(struct acpi_db_method_info *info,
0096 struct acpi_buffer *return_obj)
0097 {
0098 acpi_status status;
0099 struct acpi_object_list param_objects;
0100 union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
0101 u32 i;
0102
0103 ACPI_FUNCTION_TRACE(db_execute_method);
0104
0105 if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
0106 acpi_os_printf("Warning: debug output is not enabled!\n");
0107 }
0108
0109 param_objects.count = 0;
0110 param_objects.pointer = NULL;
0111
0112
0113
0114 if (info->args && info->args[0]) {
0115
0116
0117
0118 for (i = 0; (info->args[i] && *(info->args[i])); i++) {
0119
0120
0121
0122 status = acpi_db_convert_to_object(info->types[i],
0123 info->args[i],
0124 ¶ms[i]);
0125 if (ACPI_FAILURE(status)) {
0126 ACPI_EXCEPTION((AE_INFO, status,
0127 "While parsing method arguments"));
0128 goto cleanup;
0129 }
0130 }
0131
0132 param_objects.count = i;
0133 param_objects.pointer = params;
0134 }
0135
0136
0137
0138 return_obj->pointer = acpi_gbl_db_buffer;
0139 return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
0140
0141
0142
0143 acpi_gbl_method_executing = TRUE;
0144 status = acpi_evaluate_object(NULL, info->pathname,
0145 ¶m_objects, return_obj);
0146
0147 acpi_gbl_cm_single_step = FALSE;
0148 acpi_gbl_method_executing = FALSE;
0149
0150 if (ACPI_FAILURE(status)) {
0151 if ((status == AE_ABORT_METHOD) || acpi_gbl_abort_method) {
0152
0153
0154
0155 ACPI_EXCEPTION((AE_INFO, status,
0156 "Aborting top-level method"));
0157
0158 acpi_gbl_abort_method = FALSE;
0159 status = AE_OK;
0160 goto cleanup;
0161 }
0162
0163 ACPI_EXCEPTION((AE_INFO, status,
0164 "while executing %s from AML Debugger",
0165 info->pathname));
0166
0167 if (status == AE_BUFFER_OVERFLOW) {
0168 ACPI_ERROR((AE_INFO,
0169 "Possible buffer overflow within AML Debugger "
0170 "buffer (size 0x%X needed 0x%X)",
0171 ACPI_DEBUG_BUFFER_SIZE,
0172 (u32)return_obj->length));
0173 }
0174 }
0175
0176 cleanup:
0177 acpi_db_delete_objects(param_objects.count, params);
0178 return_ACPI_STATUS(status);
0179 }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
0194 {
0195 acpi_status status;
0196
0197 ACPI_FUNCTION_NAME(db_execute_setup);
0198
0199
0200
0201 info->pathname[0] = 0;
0202 if ((info->name[0] != '\\') && (info->name[0] != '/')) {
0203 if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
0204 acpi_gbl_db_scope_buf)) {
0205 status = AE_BUFFER_OVERFLOW;
0206 goto error_exit;
0207 }
0208 }
0209
0210 if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
0211 info->name)) {
0212 status = AE_BUFFER_OVERFLOW;
0213 goto error_exit;
0214 }
0215
0216 acpi_db_prep_namestring(info->pathname);
0217
0218 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
0219 acpi_os_printf("Evaluating %s\n", info->pathname);
0220
0221 if (info->flags & EX_SINGLE_STEP) {
0222 acpi_gbl_cm_single_step = TRUE;
0223 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
0224 }
0225
0226 else {
0227
0228
0229 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
0230 }
0231
0232 return (AE_OK);
0233
0234 error_exit:
0235
0236 ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
0237 return (status);
0238 }
0239
0240 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0241 u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
0242 {
0243
0244 return (cache->total_allocated - cache->total_freed -
0245 cache->current_depth);
0246 }
0247 #endif
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263 static u32 acpi_db_get_outstanding_allocations(void)
0264 {
0265 u32 outstanding = 0;
0266
0267 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0268
0269 outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
0270 outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
0271 outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
0272 outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
0273 #endif
0274
0275 return (outstanding);
0276 }
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 static acpi_status
0292 acpi_db_execution_walk(acpi_handle obj_handle,
0293 u32 nesting_level, void *context, void **return_value)
0294 {
0295 union acpi_operand_object *obj_desc;
0296 struct acpi_namespace_node *node =
0297 (struct acpi_namespace_node *)obj_handle;
0298 struct acpi_buffer return_obj;
0299 acpi_status status;
0300
0301 obj_desc = acpi_ns_get_attached_object(node);
0302 if (obj_desc->method.param_count) {
0303 return (AE_OK);
0304 }
0305
0306 return_obj.pointer = NULL;
0307 return_obj.length = ACPI_ALLOCATE_BUFFER;
0308
0309 acpi_ns_print_node_pathname(node, "Evaluating");
0310
0311
0312
0313 acpi_os_printf("\n");
0314 acpi_gbl_method_executing = TRUE;
0315
0316 status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
0317
0318 acpi_gbl_method_executing = FALSE;
0319
0320 acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
0321 acpi_ut_get_node_name(node),
0322 acpi_format_exception(status));
0323
0324 return (AE_OK);
0325 }
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 void
0345 acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags)
0346 {
0347 acpi_status status;
0348 struct acpi_buffer return_obj;
0349 char *name_string;
0350
0351 #ifdef ACPI_DEBUG_OUTPUT
0352 u32 previous_allocations;
0353 u32 allocations;
0354 #endif
0355
0356
0357
0358
0359
0360 if (acpi_gbl_method_executing) {
0361 acpi_os_printf("Only one debugger execution is allowed.\n");
0362 return;
0363 }
0364 #ifdef ACPI_DEBUG_OUTPUT
0365
0366
0367 previous_allocations = acpi_db_get_outstanding_allocations();
0368 #endif
0369
0370 if (*name == '*') {
0371 (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
0372 ACPI_UINT32_MAX,
0373 acpi_db_execution_walk, NULL, NULL,
0374 NULL);
0375 return;
0376 }
0377
0378 if ((flags & EX_ALL) && (strlen(name) > 4)) {
0379 acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n",
0380 name);
0381 return;
0382 }
0383
0384 name_string = ACPI_ALLOCATE(strlen(name) + 1);
0385 if (!name_string) {
0386 return;
0387 }
0388
0389 memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
0390 strcpy(name_string, name);
0391 acpi_ut_strupr(name_string);
0392
0393
0394
0395 if (!strncmp(name_string, "PREDEF", 6)) {
0396 acpi_db_evaluate_predefined_names();
0397 ACPI_FREE(name_string);
0398 return;
0399 }
0400
0401
0402
0403 else if (flags & EX_ALL) {
0404 acpi_gbl_db_method_info.name = name_string;
0405 return_obj.pointer = NULL;
0406 return_obj.length = ACPI_ALLOCATE_BUFFER;
0407 acpi_db_evaluate_all(name_string);
0408 ACPI_FREE(name_string);
0409 return;
0410 } else {
0411 acpi_gbl_db_method_info.name = name_string;
0412 acpi_gbl_db_method_info.args = args;
0413 acpi_gbl_db_method_info.types = types;
0414 acpi_gbl_db_method_info.flags = flags;
0415
0416 return_obj.pointer = NULL;
0417 return_obj.length = ACPI_ALLOCATE_BUFFER;
0418 }
0419
0420 status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
0421 if (ACPI_FAILURE(status)) {
0422 ACPI_FREE(name_string);
0423 return;
0424 }
0425
0426
0427
0428 status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
0429 &acpi_gbl_db_method_info.method);
0430 if (ACPI_SUCCESS(status)) {
0431 status = acpi_db_execute_method(&acpi_gbl_db_method_info,
0432 &return_obj);
0433 }
0434 ACPI_FREE(name_string);
0435
0436
0437
0438
0439
0440 acpi_os_sleep((u64)10);
0441
0442 #ifdef ACPI_DEBUG_OUTPUT
0443
0444
0445
0446 allocations =
0447 acpi_db_get_outstanding_allocations() - previous_allocations;
0448
0449 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
0450
0451 if (allocations > 0) {
0452 acpi_os_printf
0453 ("0x%X Outstanding allocations after evaluation of %s\n",
0454 allocations, acpi_gbl_db_method_info.pathname);
0455 }
0456 #endif
0457
0458 if (ACPI_FAILURE(status)) {
0459 acpi_os_printf("Evaluation of %s failed with status %s\n",
0460 acpi_gbl_db_method_info.pathname,
0461 acpi_format_exception(status));
0462 } else {
0463
0464
0465 if (return_obj.length) {
0466 acpi_os_printf("Evaluation of %s returned object %p, "
0467 "external buffer length %X\n",
0468 acpi_gbl_db_method_info.pathname,
0469 return_obj.pointer,
0470 (u32)return_obj.length);
0471
0472 acpi_db_dump_external_object(return_obj.pointer, 1);
0473 acpi_os_printf("\n");
0474
0475
0476
0477 if (ACPI_COMPARE_NAMESEG
0478 ((ACPI_CAST_PTR
0479 (struct acpi_namespace_node,
0480 acpi_gbl_db_method_info.method)->name.ascii),
0481 METHOD_NAME__PLD)) {
0482 acpi_db_dump_pld_buffer(return_obj.pointer);
0483 }
0484 } else {
0485 acpi_os_printf
0486 ("No object was returned from evaluation of %s\n",
0487 acpi_gbl_db_method_info.pathname);
0488 }
0489 }
0490
0491 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
0492 }
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507 static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
0508 {
0509 acpi_status status;
0510 struct acpi_db_method_info *info = context;
0511 struct acpi_db_method_info local_info;
0512 u32 i;
0513 u8 allow;
0514 struct acpi_buffer return_obj;
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
0525
0526 if (info->init_args) {
0527 acpi_db_uint32_to_hex_string(info->num_created,
0528 info->index_of_thread_str);
0529 acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
0530 info->id_of_thread_str);
0531 }
0532
0533 if (info->threads && (info->num_created < info->num_threads)) {
0534 info->threads[info->num_created++] = acpi_os_get_thread_id();
0535 }
0536
0537 local_info = *info;
0538 local_info.args = local_info.arguments;
0539 local_info.arguments[0] = local_info.num_threads_str;
0540 local_info.arguments[1] = local_info.id_of_thread_str;
0541 local_info.arguments[2] = local_info.index_of_thread_str;
0542 local_info.arguments[3] = NULL;
0543
0544 local_info.types = local_info.arg_types;
0545
0546 (void)acpi_os_signal_semaphore(info->info_gate, 1);
0547
0548 for (i = 0; i < info->num_loops; i++) {
0549 status = acpi_db_execute_method(&local_info, &return_obj);
0550 if (ACPI_FAILURE(status)) {
0551 acpi_os_printf
0552 ("%s During evaluation of %s at iteration %X\n",
0553 acpi_format_exception(status), info->pathname, i);
0554 if (status == AE_ABORT_METHOD) {
0555 break;
0556 }
0557 }
0558 #if 0
0559 if ((i % 100) == 0) {
0560 acpi_os_printf("%u loops, Thread 0x%x\n",
0561 i, acpi_os_get_thread_id());
0562 }
0563
0564 if (return_obj.length) {
0565 acpi_os_printf
0566 ("Evaluation of %s returned object %p Buflen %X\n",
0567 info->pathname, return_obj.pointer,
0568 (u32)return_obj.length);
0569 acpi_db_dump_external_object(return_obj.pointer, 1);
0570 }
0571 #endif
0572 }
0573
0574
0575
0576 allow = 0;
0577 (void)acpi_os_wait_semaphore(info->thread_complete_gate,
0578 1, ACPI_WAIT_FOREVER);
0579 info->num_completed++;
0580
0581 if (info->num_completed == info->num_threads) {
0582
0583
0584 allow = 1;
0585 }
0586
0587 (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
0588
0589 if (allow) {
0590 status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
0591 if (ACPI_FAILURE(status)) {
0592 acpi_os_printf
0593 ("Could not signal debugger thread sync semaphore, %s\n",
0594 acpi_format_exception(status));
0595 }
0596 }
0597 }
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611 static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context)
0612 {
0613 struct acpi_db_method_info *info = context;
0614 acpi_status status;
0615 struct acpi_buffer return_obj;
0616
0617 acpi_os_printf("\n");
0618
0619 status = acpi_db_execute_method(info, &return_obj);
0620 if (ACPI_FAILURE(status)) {
0621 acpi_os_printf("%s During evaluation of %s\n",
0622 acpi_format_exception(status), info->pathname);
0623 return;
0624 }
0625
0626
0627
0628 if (return_obj.length) {
0629 acpi_os_printf("Evaluation of %s returned object %p, "
0630 "external buffer length %X\n",
0631 acpi_gbl_db_method_info.pathname,
0632 return_obj.pointer, (u32)return_obj.length);
0633
0634 acpi_db_dump_external_object(return_obj.pointer, 1);
0635 }
0636
0637 acpi_os_printf("\nBackground thread completed\n%c ",
0638 ACPI_DEBUGGER_COMMAND_PROMPT);
0639 }
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656 void
0657 acpi_db_create_execution_thread(char *method_name_arg,
0658 char **arguments, acpi_object_type *types)
0659 {
0660 acpi_status status;
0661 u32 i;
0662
0663 memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
0664 acpi_gbl_db_method_info.name = method_name_arg;
0665 acpi_gbl_db_method_info.init_args = 1;
0666 acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
0667 acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
0668
0669
0670
0671 for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) {
0672 acpi_gbl_db_method_info.arguments[i] = *arguments;
0673 arguments++;
0674
0675 acpi_gbl_db_method_info.arg_types[i] = *types;
0676 types++;
0677 }
0678
0679 status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
0680 if (ACPI_FAILURE(status)) {
0681 return;
0682 }
0683
0684
0685
0686 status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
0687 &acpi_gbl_db_method_info.method);
0688 if (ACPI_FAILURE(status)) {
0689 acpi_os_printf("%s Could not get handle for %s\n",
0690 acpi_format_exception(status),
0691 acpi_gbl_db_method_info.pathname);
0692 return;
0693 }
0694
0695 status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
0696 acpi_db_single_execution_thread,
0697 &acpi_gbl_db_method_info);
0698 if (ACPI_FAILURE(status)) {
0699 return;
0700 }
0701
0702 acpi_os_printf("\nBackground thread started\n");
0703 }
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719 void
0720 acpi_db_create_execution_threads(char *num_threads_arg,
0721 char *num_loops_arg, char *method_name_arg)
0722 {
0723 acpi_status status;
0724 u32 num_threads;
0725 u32 num_loops;
0726 u32 i;
0727 u32 size;
0728 acpi_mutex main_thread_gate;
0729 acpi_mutex thread_complete_gate;
0730 acpi_mutex info_gate;
0731
0732
0733
0734 num_threads = strtoul(num_threads_arg, NULL, 0);
0735 num_loops = strtoul(num_loops_arg, NULL, 0);
0736
0737 if (!num_threads || !num_loops) {
0738 acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
0739 num_threads, num_loops);
0740 return;
0741 }
0742
0743
0744
0745
0746
0747 status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
0748 if (ACPI_FAILURE(status)) {
0749 acpi_os_printf("Could not create semaphore for "
0750 "synchronization with the main thread, %s\n",
0751 acpi_format_exception(status));
0752 return;
0753 }
0754
0755
0756
0757
0758
0759 status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
0760 if (ACPI_FAILURE(status)) {
0761 acpi_os_printf("Could not create semaphore for "
0762 "synchronization between the created threads, %s\n",
0763 acpi_format_exception(status));
0764
0765 (void)acpi_os_delete_semaphore(main_thread_gate);
0766 return;
0767 }
0768
0769 status = acpi_os_create_semaphore(1, 1, &info_gate);
0770 if (ACPI_FAILURE(status)) {
0771 acpi_os_printf("Could not create semaphore for "
0772 "synchronization of AcpiGbl_DbMethodInfo, %s\n",
0773 acpi_format_exception(status));
0774
0775 (void)acpi_os_delete_semaphore(thread_complete_gate);
0776 (void)acpi_os_delete_semaphore(main_thread_gate);
0777 return;
0778 }
0779
0780 memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
0781
0782
0783
0784 acpi_gbl_db_method_info.num_threads = num_threads;
0785 size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
0786
0787 acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
0788 if (acpi_gbl_db_method_info.threads == NULL) {
0789 acpi_os_printf("No memory for thread IDs array\n");
0790 (void)acpi_os_delete_semaphore(main_thread_gate);
0791 (void)acpi_os_delete_semaphore(thread_complete_gate);
0792 (void)acpi_os_delete_semaphore(info_gate);
0793 return;
0794 }
0795 memset(acpi_gbl_db_method_info.threads, 0, size);
0796
0797
0798
0799 acpi_gbl_db_method_info.name = method_name_arg;
0800 acpi_gbl_db_method_info.flags = 0;
0801 acpi_gbl_db_method_info.num_loops = num_loops;
0802 acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
0803 acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
0804 acpi_gbl_db_method_info.info_gate = info_gate;
0805
0806
0807
0808 acpi_gbl_db_method_info.init_args = 1;
0809 acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
0810 acpi_gbl_db_method_info.arguments[0] =
0811 acpi_gbl_db_method_info.num_threads_str;
0812 acpi_gbl_db_method_info.arguments[1] =
0813 acpi_gbl_db_method_info.id_of_thread_str;
0814 acpi_gbl_db_method_info.arguments[2] =
0815 acpi_gbl_db_method_info.index_of_thread_str;
0816 acpi_gbl_db_method_info.arguments[3] = NULL;
0817
0818 acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
0819 acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
0820 acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
0821 acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
0822
0823 acpi_db_uint32_to_hex_string(num_threads,
0824 acpi_gbl_db_method_info.num_threads_str);
0825
0826 status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
0827 if (ACPI_FAILURE(status)) {
0828 goto cleanup_and_exit;
0829 }
0830
0831
0832
0833 status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
0834 &acpi_gbl_db_method_info.method);
0835 if (ACPI_FAILURE(status)) {
0836 acpi_os_printf("%s Could not get handle for %s\n",
0837 acpi_format_exception(status),
0838 acpi_gbl_db_method_info.pathname);
0839 goto cleanup_and_exit;
0840 }
0841
0842
0843
0844 acpi_os_printf("Creating %X threads to execute %X times each\n",
0845 num_threads, num_loops);
0846
0847 for (i = 0; i < (num_threads); i++) {
0848 status =
0849 acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
0850 acpi_db_method_thread,
0851 &acpi_gbl_db_method_info);
0852 if (ACPI_FAILURE(status)) {
0853 break;
0854 }
0855 }
0856
0857
0858
0859 (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
0860
0861 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
0862 acpi_os_printf("All threads (%X) have completed\n", num_threads);
0863 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
0864
0865 cleanup_and_exit:
0866
0867
0868
0869 (void)acpi_os_delete_semaphore(main_thread_gate);
0870 (void)acpi_os_delete_semaphore(thread_complete_gate);
0871 (void)acpi_os_delete_semaphore(info_gate);
0872
0873 acpi_os_free(acpi_gbl_db_method_info.threads);
0874 acpi_gbl_db_method_info.threads = NULL;
0875 }