195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
299575102SLv Zheng /*******************************************************************************
399575102SLv Zheng *
499575102SLv Zheng * Module Name: dbexec - debugger control method execution
599575102SLv Zheng *
699575102SLv Zheng ******************************************************************************/
799575102SLv Zheng
899575102SLv Zheng #include <acpi/acpi.h>
999575102SLv Zheng #include "accommon.h"
1099575102SLv Zheng #include "acdebug.h"
1199575102SLv Zheng #include "acnamesp.h"
1299575102SLv Zheng
1399575102SLv Zheng #define _COMPONENT ACPI_CA_DEBUGGER
1499575102SLv Zheng ACPI_MODULE_NAME("dbexec")
1599575102SLv Zheng
1699575102SLv Zheng static struct acpi_db_method_info acpi_gbl_db_method_info;
1799575102SLv Zheng
1899575102SLv Zheng /* Local prototypes */
1999575102SLv Zheng
2099575102SLv Zheng static acpi_status
2199575102SLv Zheng acpi_db_execute_method(struct acpi_db_method_info *info,
2299575102SLv Zheng struct acpi_buffer *return_obj);
2399575102SLv Zheng
2499575102SLv Zheng static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
2599575102SLv Zheng
2699575102SLv Zheng static u32 acpi_db_get_outstanding_allocations(void);
2799575102SLv Zheng
2899575102SLv Zheng static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
2999575102SLv Zheng
3099575102SLv Zheng static acpi_status
3199575102SLv Zheng acpi_db_execution_walk(acpi_handle obj_handle,
3299575102SLv Zheng u32 nesting_level, void *context, void **return_value);
3399575102SLv Zheng
34060c859dSBob Moore static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context);
35060c859dSBob Moore
3699575102SLv Zheng /*******************************************************************************
3799575102SLv Zheng *
3899575102SLv Zheng * FUNCTION: acpi_db_delete_objects
3999575102SLv Zheng *
4099575102SLv Zheng * PARAMETERS: count - Count of objects in the list
4199575102SLv Zheng * objects - Array of ACPI_OBJECTs to be deleted
4299575102SLv Zheng *
4399575102SLv Zheng * RETURN: None
4499575102SLv Zheng *
4599575102SLv Zheng * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
4699575102SLv Zheng * packages via recursion.
4799575102SLv Zheng *
4899575102SLv Zheng ******************************************************************************/
4999575102SLv Zheng
acpi_db_delete_objects(u32 count,union acpi_object * objects)5099575102SLv Zheng void acpi_db_delete_objects(u32 count, union acpi_object *objects)
5199575102SLv Zheng {
5299575102SLv Zheng u32 i;
5399575102SLv Zheng
5499575102SLv Zheng for (i = 0; i < count; i++) {
5599575102SLv Zheng switch (objects[i].type) {
5699575102SLv Zheng case ACPI_TYPE_BUFFER:
5799575102SLv Zheng
5899575102SLv Zheng ACPI_FREE(objects[i].buffer.pointer);
5999575102SLv Zheng break;
6099575102SLv Zheng
6199575102SLv Zheng case ACPI_TYPE_PACKAGE:
6299575102SLv Zheng
6399575102SLv Zheng /* Recursive call to delete package elements */
6499575102SLv Zheng
6599575102SLv Zheng acpi_db_delete_objects(objects[i].package.count,
6699575102SLv Zheng objects[i].package.elements);
6799575102SLv Zheng
6899575102SLv Zheng /* Free the elements array */
6999575102SLv Zheng
7099575102SLv Zheng ACPI_FREE(objects[i].package.elements);
7199575102SLv Zheng break;
7299575102SLv Zheng
7399575102SLv Zheng default:
7499575102SLv Zheng
7599575102SLv Zheng break;
7699575102SLv Zheng }
7799575102SLv Zheng }
7899575102SLv Zheng }
7999575102SLv Zheng
8099575102SLv Zheng /*******************************************************************************
8199575102SLv Zheng *
8299575102SLv Zheng * FUNCTION: acpi_db_execute_method
8399575102SLv Zheng *
8499575102SLv Zheng * PARAMETERS: info - Valid info segment
8599575102SLv Zheng * return_obj - Where to put return object
8699575102SLv Zheng *
8799575102SLv Zheng * RETURN: Status
8899575102SLv Zheng *
89*6218ab30SBob Moore * DESCRIPTION: Execute a control method. Used to evaluate objects via the
90*6218ab30SBob Moore * "EXECUTE" or "EVALUATE" commands.
9199575102SLv Zheng *
9299575102SLv Zheng ******************************************************************************/
9399575102SLv Zheng
9499575102SLv Zheng static acpi_status
acpi_db_execute_method(struct acpi_db_method_info * info,struct acpi_buffer * return_obj)9599575102SLv Zheng acpi_db_execute_method(struct acpi_db_method_info *info,
9699575102SLv Zheng struct acpi_buffer *return_obj)
9799575102SLv Zheng {
9899575102SLv Zheng acpi_status status;
9999575102SLv Zheng struct acpi_object_list param_objects;
10099575102SLv Zheng union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
10199575102SLv Zheng u32 i;
10299575102SLv Zheng
10399575102SLv Zheng ACPI_FUNCTION_TRACE(db_execute_method);
10499575102SLv Zheng
10599575102SLv Zheng if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
10699575102SLv Zheng acpi_os_printf("Warning: debug output is not enabled!\n");
10799575102SLv Zheng }
10899575102SLv Zheng
10999575102SLv Zheng param_objects.count = 0;
11099575102SLv Zheng param_objects.pointer = NULL;
11199575102SLv Zheng
11299575102SLv Zheng /* Pass through any command-line arguments */
11399575102SLv Zheng
11499575102SLv Zheng if (info->args && info->args[0]) {
11599575102SLv Zheng
11699575102SLv Zheng /* Get arguments passed on the command line */
11799575102SLv Zheng
11899575102SLv Zheng for (i = 0; (info->args[i] && *(info->args[i])); i++) {
11999575102SLv Zheng
12099575102SLv Zheng /* Convert input string (token) to an actual union acpi_object */
12199575102SLv Zheng
12299575102SLv Zheng status = acpi_db_convert_to_object(info->types[i],
12399575102SLv Zheng info->args[i],
12499575102SLv Zheng ¶ms[i]);
12599575102SLv Zheng if (ACPI_FAILURE(status)) {
12699575102SLv Zheng ACPI_EXCEPTION((AE_INFO, status,
12799575102SLv Zheng "While parsing method arguments"));
12899575102SLv Zheng goto cleanup;
12999575102SLv Zheng }
13099575102SLv Zheng }
13199575102SLv Zheng
13299575102SLv Zheng param_objects.count = i;
13399575102SLv Zheng param_objects.pointer = params;
13499575102SLv Zheng }
13599575102SLv Zheng
13699575102SLv Zheng /* Prepare for a return object of arbitrary size */
13799575102SLv Zheng
13899575102SLv Zheng return_obj->pointer = acpi_gbl_db_buffer;
13999575102SLv Zheng return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
14099575102SLv Zheng
14199575102SLv Zheng /* Do the actual method execution */
14299575102SLv Zheng
14399575102SLv Zheng acpi_gbl_method_executing = TRUE;
14499575102SLv Zheng status = acpi_evaluate_object(NULL, info->pathname,
14599575102SLv Zheng ¶m_objects, return_obj);
14699575102SLv Zheng
14799575102SLv Zheng acpi_gbl_cm_single_step = FALSE;
14899575102SLv Zheng acpi_gbl_method_executing = FALSE;
14999575102SLv Zheng
15099575102SLv Zheng if (ACPI_FAILURE(status)) {
151fd13aaa8SBob Moore if ((status == AE_ABORT_METHOD) || acpi_gbl_abort_method) {
152fd13aaa8SBob Moore
153fd13aaa8SBob Moore /* Clear the abort and fall back to the debugger prompt */
154fd13aaa8SBob Moore
155fd13aaa8SBob Moore ACPI_EXCEPTION((AE_INFO, status,
156fd13aaa8SBob Moore "Aborting top-level method"));
157fd13aaa8SBob Moore
158fd13aaa8SBob Moore acpi_gbl_abort_method = FALSE;
159fd13aaa8SBob Moore status = AE_OK;
160fd13aaa8SBob Moore goto cleanup;
161fd13aaa8SBob Moore }
162fd13aaa8SBob Moore
16399575102SLv Zheng ACPI_EXCEPTION((AE_INFO, status,
164991371e0SBob Moore "while executing %s from AML Debugger",
16599575102SLv Zheng info->pathname));
16699575102SLv Zheng
16799575102SLv Zheng if (status == AE_BUFFER_OVERFLOW) {
16899575102SLv Zheng ACPI_ERROR((AE_INFO,
169991371e0SBob Moore "Possible buffer overflow within AML Debugger "
17099575102SLv Zheng "buffer (size 0x%X needed 0x%X)",
17199575102SLv Zheng ACPI_DEBUG_BUFFER_SIZE,
17299575102SLv Zheng (u32)return_obj->length));
17399575102SLv Zheng }
17499575102SLv Zheng }
17599575102SLv Zheng
17699575102SLv Zheng cleanup:
17799575102SLv Zheng acpi_db_delete_objects(param_objects.count, params);
17899575102SLv Zheng return_ACPI_STATUS(status);
17999575102SLv Zheng }
18099575102SLv Zheng
18199575102SLv Zheng /*******************************************************************************
18299575102SLv Zheng *
18399575102SLv Zheng * FUNCTION: acpi_db_execute_setup
18499575102SLv Zheng *
18599575102SLv Zheng * PARAMETERS: info - Valid method info
18699575102SLv Zheng *
18799575102SLv Zheng * RETURN: None
18899575102SLv Zheng *
18999575102SLv Zheng * DESCRIPTION: Setup info segment prior to method execution
19099575102SLv Zheng *
19199575102SLv Zheng ******************************************************************************/
19299575102SLv Zheng
acpi_db_execute_setup(struct acpi_db_method_info * info)19399575102SLv Zheng static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
19499575102SLv Zheng {
19599575102SLv Zheng acpi_status status;
19699575102SLv Zheng
19799575102SLv Zheng ACPI_FUNCTION_NAME(db_execute_setup);
19899575102SLv Zheng
199060c859dSBob Moore /* Concatenate the current scope to the supplied name */
20099575102SLv Zheng
20199575102SLv Zheng info->pathname[0] = 0;
20299575102SLv Zheng if ((info->name[0] != '\\') && (info->name[0] != '/')) {
20399575102SLv Zheng if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
20499575102SLv Zheng acpi_gbl_db_scope_buf)) {
20599575102SLv Zheng status = AE_BUFFER_OVERFLOW;
20699575102SLv Zheng goto error_exit;
20799575102SLv Zheng }
20899575102SLv Zheng }
20999575102SLv Zheng
21099575102SLv Zheng if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
21199575102SLv Zheng info->name)) {
21299575102SLv Zheng status = AE_BUFFER_OVERFLOW;
21399575102SLv Zheng goto error_exit;
21499575102SLv Zheng }
21599575102SLv Zheng
21699575102SLv Zheng acpi_db_prep_namestring(info->pathname);
21799575102SLv Zheng
21899575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
21999575102SLv Zheng acpi_os_printf("Evaluating %s\n", info->pathname);
22099575102SLv Zheng
22199575102SLv Zheng if (info->flags & EX_SINGLE_STEP) {
22299575102SLv Zheng acpi_gbl_cm_single_step = TRUE;
22399575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
22499575102SLv Zheng }
22599575102SLv Zheng
22699575102SLv Zheng else {
22799575102SLv Zheng /* No single step, allow redirection to a file */
22899575102SLv Zheng
22999575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
23099575102SLv Zheng }
23199575102SLv Zheng
23299575102SLv Zheng return (AE_OK);
23399575102SLv Zheng
23499575102SLv Zheng error_exit:
23599575102SLv Zheng
23699575102SLv Zheng ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
23799575102SLv Zheng return (status);
23899575102SLv Zheng }
23999575102SLv Zheng
24099575102SLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
acpi_db_get_cache_info(struct acpi_memory_list * cache)24199575102SLv Zheng u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
24299575102SLv Zheng {
24399575102SLv Zheng
24499575102SLv Zheng return (cache->total_allocated - cache->total_freed -
24599575102SLv Zheng cache->current_depth);
24699575102SLv Zheng }
24799575102SLv Zheng #endif
24899575102SLv Zheng
24999575102SLv Zheng /*******************************************************************************
25099575102SLv Zheng *
25199575102SLv Zheng * FUNCTION: acpi_db_get_outstanding_allocations
25299575102SLv Zheng *
25399575102SLv Zheng * PARAMETERS: None
25499575102SLv Zheng *
25599575102SLv Zheng * RETURN: Current global allocation count minus cache entries
25699575102SLv Zheng *
25799575102SLv Zheng * DESCRIPTION: Determine the current number of "outstanding" allocations --
25899575102SLv Zheng * those allocations that have not been freed and also are not
25999575102SLv Zheng * in one of the various object caches.
26099575102SLv Zheng *
26199575102SLv Zheng ******************************************************************************/
26299575102SLv Zheng
acpi_db_get_outstanding_allocations(void)26399575102SLv Zheng static u32 acpi_db_get_outstanding_allocations(void)
26499575102SLv Zheng {
26599575102SLv Zheng u32 outstanding = 0;
26699575102SLv Zheng
26799575102SLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
26899575102SLv Zheng
26999575102SLv Zheng outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
27099575102SLv Zheng outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
27199575102SLv Zheng outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
27299575102SLv Zheng outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
27399575102SLv Zheng #endif
27499575102SLv Zheng
27599575102SLv Zheng return (outstanding);
27699575102SLv Zheng }
27799575102SLv Zheng
27899575102SLv Zheng /*******************************************************************************
27999575102SLv Zheng *
28099575102SLv Zheng * FUNCTION: acpi_db_execution_walk
28199575102SLv Zheng *
28299575102SLv Zheng * PARAMETERS: WALK_CALLBACK
28399575102SLv Zheng *
28499575102SLv Zheng * RETURN: Status
28599575102SLv Zheng *
28699575102SLv Zheng * DESCRIPTION: Execute a control method. Name is relative to the current
28799575102SLv Zheng * scope.
28899575102SLv Zheng *
28999575102SLv Zheng ******************************************************************************/
29099575102SLv Zheng
29199575102SLv Zheng static acpi_status
acpi_db_execution_walk(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)29299575102SLv Zheng acpi_db_execution_walk(acpi_handle obj_handle,
29399575102SLv Zheng u32 nesting_level, void *context, void **return_value)
29499575102SLv Zheng {
29599575102SLv Zheng union acpi_operand_object *obj_desc;
29699575102SLv Zheng struct acpi_namespace_node *node =
29799575102SLv Zheng (struct acpi_namespace_node *)obj_handle;
29899575102SLv Zheng struct acpi_buffer return_obj;
29999575102SLv Zheng acpi_status status;
30099575102SLv Zheng
30199575102SLv Zheng obj_desc = acpi_ns_get_attached_object(node);
30299575102SLv Zheng if (obj_desc->method.param_count) {
30399575102SLv Zheng return (AE_OK);
30499575102SLv Zheng }
30599575102SLv Zheng
30699575102SLv Zheng return_obj.pointer = NULL;
30799575102SLv Zheng return_obj.length = ACPI_ALLOCATE_BUFFER;
30899575102SLv Zheng
30999575102SLv Zheng acpi_ns_print_node_pathname(node, "Evaluating");
31099575102SLv Zheng
31199575102SLv Zheng /* Do the actual method execution */
31299575102SLv Zheng
31399575102SLv Zheng acpi_os_printf("\n");
31499575102SLv Zheng acpi_gbl_method_executing = TRUE;
31599575102SLv Zheng
31699575102SLv Zheng status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
31799575102SLv Zheng
318*6218ab30SBob Moore acpi_gbl_method_executing = FALSE;
319*6218ab30SBob Moore
32099575102SLv Zheng acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
32199575102SLv Zheng acpi_ut_get_node_name(node),
32299575102SLv Zheng acpi_format_exception(status));
32399575102SLv Zheng
32499575102SLv Zheng return (AE_OK);
32599575102SLv Zheng }
32699575102SLv Zheng
32799575102SLv Zheng /*******************************************************************************
32899575102SLv Zheng *
32999575102SLv Zheng * FUNCTION: acpi_db_execute
33099575102SLv Zheng *
33199575102SLv Zheng * PARAMETERS: name - Name of method to execute
33299575102SLv Zheng * args - Parameters to the method
33399575102SLv Zheng * Types -
33499575102SLv Zheng * flags - single step/no single step
33599575102SLv Zheng *
33699575102SLv Zheng * RETURN: None
33799575102SLv Zheng *
33899575102SLv Zheng * DESCRIPTION: Execute a control method. Name is relative to the current
339*6218ab30SBob Moore * scope. Function used for the "EXECUTE", "EVALUATE", and
340*6218ab30SBob Moore * "ALL" commands
34199575102SLv Zheng *
34299575102SLv Zheng ******************************************************************************/
34399575102SLv Zheng
34499575102SLv Zheng void
acpi_db_execute(char * name,char ** args,acpi_object_type * types,u32 flags)34599575102SLv Zheng acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags)
34699575102SLv Zheng {
34799575102SLv Zheng acpi_status status;
34899575102SLv Zheng struct acpi_buffer return_obj;
34999575102SLv Zheng char *name_string;
35099575102SLv Zheng
35199575102SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
35299575102SLv Zheng u32 previous_allocations;
35399575102SLv Zheng u32 allocations;
354aaa93a61SLv Zheng #endif
35599575102SLv Zheng
356aaa93a61SLv Zheng /*
357aaa93a61SLv Zheng * Allow one execution to be performed by debugger or single step
358aaa93a61SLv Zheng * execution will be dead locked by the interpreter mutexes.
359aaa93a61SLv Zheng */
360aaa93a61SLv Zheng if (acpi_gbl_method_executing) {
361aaa93a61SLv Zheng acpi_os_printf("Only one debugger execution is allowed.\n");
362aaa93a61SLv Zheng return;
363aaa93a61SLv Zheng }
364aaa93a61SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
36599575102SLv Zheng /* Memory allocation tracking */
36699575102SLv Zheng
36799575102SLv Zheng previous_allocations = acpi_db_get_outstanding_allocations();
36899575102SLv Zheng #endif
36999575102SLv Zheng
37099575102SLv Zheng if (*name == '*') {
37199575102SLv Zheng (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
37299575102SLv Zheng ACPI_UINT32_MAX,
37399575102SLv Zheng acpi_db_execution_walk, NULL, NULL,
37499575102SLv Zheng NULL);
37599575102SLv Zheng return;
37660361b75SBob Moore }
37760361b75SBob Moore
378*6218ab30SBob Moore if ((flags & EX_ALL) && (strlen(name) > 4)) {
379*6218ab30SBob Moore acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n",
380*6218ab30SBob Moore name);
381*6218ab30SBob Moore return;
382*6218ab30SBob Moore }
383*6218ab30SBob Moore
38499575102SLv Zheng name_string = ACPI_ALLOCATE(strlen(name) + 1);
38599575102SLv Zheng if (!name_string) {
38699575102SLv Zheng return;
38799575102SLv Zheng }
38899575102SLv Zheng
38960361b75SBob Moore memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
39099575102SLv Zheng strcpy(name_string, name);
39199575102SLv Zheng acpi_ut_strupr(name_string);
39260361b75SBob Moore
39360361b75SBob Moore /* Subcommand to Execute all predefined names in the namespace */
39460361b75SBob Moore
39560361b75SBob Moore if (!strncmp(name_string, "PREDEF", 6)) {
39660361b75SBob Moore acpi_db_evaluate_predefined_names();
39760361b75SBob Moore ACPI_FREE(name_string);
39860361b75SBob Moore return;
39960361b75SBob Moore }
40060361b75SBob Moore
401*6218ab30SBob Moore /* Command (ALL <nameseg>) to execute all methods of a particular name */
402*6218ab30SBob Moore
403*6218ab30SBob Moore else if (flags & EX_ALL) {
404*6218ab30SBob Moore acpi_gbl_db_method_info.name = name_string;
405*6218ab30SBob Moore return_obj.pointer = NULL;
406*6218ab30SBob Moore return_obj.length = ACPI_ALLOCATE_BUFFER;
407*6218ab30SBob Moore acpi_db_evaluate_all(name_string);
408*6218ab30SBob Moore ACPI_FREE(name_string);
409*6218ab30SBob Moore return;
410*6218ab30SBob Moore } else {
41199575102SLv Zheng acpi_gbl_db_method_info.name = name_string;
41299575102SLv Zheng acpi_gbl_db_method_info.args = args;
41399575102SLv Zheng acpi_gbl_db_method_info.types = types;
41499575102SLv Zheng acpi_gbl_db_method_info.flags = flags;
41599575102SLv Zheng
41699575102SLv Zheng return_obj.pointer = NULL;
41799575102SLv Zheng return_obj.length = ACPI_ALLOCATE_BUFFER;
418*6218ab30SBob Moore }
41999575102SLv Zheng
42099575102SLv Zheng status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
42199575102SLv Zheng if (ACPI_FAILURE(status)) {
42299575102SLv Zheng ACPI_FREE(name_string);
42399575102SLv Zheng return;
42499575102SLv Zheng }
42599575102SLv Zheng
42699575102SLv Zheng /* Get the NS node, determines existence also */
42799575102SLv Zheng
42899575102SLv Zheng status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
42999575102SLv Zheng &acpi_gbl_db_method_info.method);
43099575102SLv Zheng if (ACPI_SUCCESS(status)) {
43160361b75SBob Moore status = acpi_db_execute_method(&acpi_gbl_db_method_info,
43299575102SLv Zheng &return_obj);
43399575102SLv Zheng }
43499575102SLv Zheng ACPI_FREE(name_string);
43599575102SLv Zheng
43699575102SLv Zheng /*
43799575102SLv Zheng * Allow any handlers in separate threads to complete.
43899575102SLv Zheng * (Such as Notify handlers invoked from AML executed above).
43999575102SLv Zheng */
44099575102SLv Zheng acpi_os_sleep((u64)10);
44199575102SLv Zheng
44299575102SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
44399575102SLv Zheng
44499575102SLv Zheng /* Memory allocation tracking */
44599575102SLv Zheng
44699575102SLv Zheng allocations =
44799575102SLv Zheng acpi_db_get_outstanding_allocations() - previous_allocations;
44899575102SLv Zheng
44999575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
45099575102SLv Zheng
45199575102SLv Zheng if (allocations > 0) {
45299575102SLv Zheng acpi_os_printf
45399575102SLv Zheng ("0x%X Outstanding allocations after evaluation of %s\n",
45499575102SLv Zheng allocations, acpi_gbl_db_method_info.pathname);
45599575102SLv Zheng }
45699575102SLv Zheng #endif
45799575102SLv Zheng
45899575102SLv Zheng if (ACPI_FAILURE(status)) {
45999575102SLv Zheng acpi_os_printf("Evaluation of %s failed with status %s\n",
46099575102SLv Zheng acpi_gbl_db_method_info.pathname,
46199575102SLv Zheng acpi_format_exception(status));
46299575102SLv Zheng } else {
46399575102SLv Zheng /* Display a return object, if any */
46499575102SLv Zheng
46599575102SLv Zheng if (return_obj.length) {
46699575102SLv Zheng acpi_os_printf("Evaluation of %s returned object %p, "
46799575102SLv Zheng "external buffer length %X\n",
46899575102SLv Zheng acpi_gbl_db_method_info.pathname,
46999575102SLv Zheng return_obj.pointer,
47099575102SLv Zheng (u32)return_obj.length);
47199575102SLv Zheng
47299575102SLv Zheng acpi_db_dump_external_object(return_obj.pointer, 1);
473*6218ab30SBob Moore acpi_os_printf("\n");
47499575102SLv Zheng
47599575102SLv Zheng /* Dump a _PLD buffer if present */
47699575102SLv Zheng
4775599fb69SBob Moore if (ACPI_COMPARE_NAMESEG
47899575102SLv Zheng ((ACPI_CAST_PTR
47999575102SLv Zheng (struct acpi_namespace_node,
48099575102SLv Zheng acpi_gbl_db_method_info.method)->name.ascii),
48199575102SLv Zheng METHOD_NAME__PLD)) {
48299575102SLv Zheng acpi_db_dump_pld_buffer(return_obj.pointer);
48399575102SLv Zheng }
48499575102SLv Zheng } else {
48599575102SLv Zheng acpi_os_printf
48699575102SLv Zheng ("No object was returned from evaluation of %s\n",
48799575102SLv Zheng acpi_gbl_db_method_info.pathname);
48899575102SLv Zheng }
48999575102SLv Zheng }
49099575102SLv Zheng
49199575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
49299575102SLv Zheng }
49399575102SLv Zheng
49499575102SLv Zheng /*******************************************************************************
49599575102SLv Zheng *
49699575102SLv Zheng * FUNCTION: acpi_db_method_thread
49799575102SLv Zheng *
49899575102SLv Zheng * PARAMETERS: context - Execution info segment
49999575102SLv Zheng *
50099575102SLv Zheng * RETURN: None
50199575102SLv Zheng *
50299575102SLv Zheng * DESCRIPTION: Debugger execute thread. Waits for a command line, then
50399575102SLv Zheng * simply dispatches it.
50499575102SLv Zheng *
50599575102SLv Zheng ******************************************************************************/
50699575102SLv Zheng
acpi_db_method_thread(void * context)50799575102SLv Zheng static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
50899575102SLv Zheng {
50999575102SLv Zheng acpi_status status;
51099575102SLv Zheng struct acpi_db_method_info *info = context;
51199575102SLv Zheng struct acpi_db_method_info local_info;
51299575102SLv Zheng u32 i;
51399575102SLv Zheng u8 allow;
51499575102SLv Zheng struct acpi_buffer return_obj;
51599575102SLv Zheng
51699575102SLv Zheng /*
51799575102SLv Zheng * acpi_gbl_db_method_info.Arguments will be passed as method arguments.
51899575102SLv Zheng * Prevent acpi_gbl_db_method_info from being modified by multiple threads
51999575102SLv Zheng * concurrently.
52099575102SLv Zheng *
52199575102SLv Zheng * Note: The arguments we are passing are used by the ASL test suite
52299575102SLv Zheng * (aslts). Do not change them without updating the tests.
52399575102SLv Zheng */
52499575102SLv Zheng (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
52599575102SLv Zheng
52699575102SLv Zheng if (info->init_args) {
52799575102SLv Zheng acpi_db_uint32_to_hex_string(info->num_created,
52899575102SLv Zheng info->index_of_thread_str);
52999575102SLv Zheng acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
53099575102SLv Zheng info->id_of_thread_str);
53199575102SLv Zheng }
53299575102SLv Zheng
53399575102SLv Zheng if (info->threads && (info->num_created < info->num_threads)) {
53499575102SLv Zheng info->threads[info->num_created++] = acpi_os_get_thread_id();
53599575102SLv Zheng }
53699575102SLv Zheng
53799575102SLv Zheng local_info = *info;
53899575102SLv Zheng local_info.args = local_info.arguments;
53999575102SLv Zheng local_info.arguments[0] = local_info.num_threads_str;
54099575102SLv Zheng local_info.arguments[1] = local_info.id_of_thread_str;
54199575102SLv Zheng local_info.arguments[2] = local_info.index_of_thread_str;
54299575102SLv Zheng local_info.arguments[3] = NULL;
54399575102SLv Zheng
54499575102SLv Zheng local_info.types = local_info.arg_types;
54599575102SLv Zheng
54699575102SLv Zheng (void)acpi_os_signal_semaphore(info->info_gate, 1);
54799575102SLv Zheng
54899575102SLv Zheng for (i = 0; i < info->num_loops; i++) {
54999575102SLv Zheng status = acpi_db_execute_method(&local_info, &return_obj);
55099575102SLv Zheng if (ACPI_FAILURE(status)) {
55199575102SLv Zheng acpi_os_printf
55299575102SLv Zheng ("%s During evaluation of %s at iteration %X\n",
55399575102SLv Zheng acpi_format_exception(status), info->pathname, i);
55499575102SLv Zheng if (status == AE_ABORT_METHOD) {
55599575102SLv Zheng break;
55699575102SLv Zheng }
55799575102SLv Zheng }
55899575102SLv Zheng #if 0
55999575102SLv Zheng if ((i % 100) == 0) {
56099575102SLv Zheng acpi_os_printf("%u loops, Thread 0x%x\n",
56199575102SLv Zheng i, acpi_os_get_thread_id());
56299575102SLv Zheng }
56399575102SLv Zheng
56499575102SLv Zheng if (return_obj.length) {
56599575102SLv Zheng acpi_os_printf
56699575102SLv Zheng ("Evaluation of %s returned object %p Buflen %X\n",
56799575102SLv Zheng info->pathname, return_obj.pointer,
56899575102SLv Zheng (u32)return_obj.length);
56999575102SLv Zheng acpi_db_dump_external_object(return_obj.pointer, 1);
57099575102SLv Zheng }
57199575102SLv Zheng #endif
57299575102SLv Zheng }
57399575102SLv Zheng
57499575102SLv Zheng /* Signal our completion */
57599575102SLv Zheng
57699575102SLv Zheng allow = 0;
57799575102SLv Zheng (void)acpi_os_wait_semaphore(info->thread_complete_gate,
57899575102SLv Zheng 1, ACPI_WAIT_FOREVER);
57999575102SLv Zheng info->num_completed++;
58099575102SLv Zheng
58199575102SLv Zheng if (info->num_completed == info->num_threads) {
58299575102SLv Zheng
58399575102SLv Zheng /* Do signal for main thread once only */
58499575102SLv Zheng allow = 1;
58599575102SLv Zheng }
58699575102SLv Zheng
58799575102SLv Zheng (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
58899575102SLv Zheng
58999575102SLv Zheng if (allow) {
59099575102SLv Zheng status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
59199575102SLv Zheng if (ACPI_FAILURE(status)) {
59299575102SLv Zheng acpi_os_printf
59399575102SLv Zheng ("Could not signal debugger thread sync semaphore, %s\n",
59499575102SLv Zheng acpi_format_exception(status));
59599575102SLv Zheng }
59699575102SLv Zheng }
59799575102SLv Zheng }
59899575102SLv Zheng
59999575102SLv Zheng /*******************************************************************************
60099575102SLv Zheng *
601060c859dSBob Moore * FUNCTION: acpi_db_single_execution_thread
602060c859dSBob Moore *
603060c859dSBob Moore * PARAMETERS: context - Method info struct
604060c859dSBob Moore *
605060c859dSBob Moore * RETURN: None
606060c859dSBob Moore *
607060c859dSBob Moore * DESCRIPTION: Create one thread and execute a method
608060c859dSBob Moore *
609060c859dSBob Moore ******************************************************************************/
610060c859dSBob Moore
acpi_db_single_execution_thread(void * context)611060c859dSBob Moore static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context)
612060c859dSBob Moore {
613060c859dSBob Moore struct acpi_db_method_info *info = context;
614060c859dSBob Moore acpi_status status;
615060c859dSBob Moore struct acpi_buffer return_obj;
616060c859dSBob Moore
617060c859dSBob Moore acpi_os_printf("\n");
618060c859dSBob Moore
619060c859dSBob Moore status = acpi_db_execute_method(info, &return_obj);
620060c859dSBob Moore if (ACPI_FAILURE(status)) {
621060c859dSBob Moore acpi_os_printf("%s During evaluation of %s\n",
622060c859dSBob Moore acpi_format_exception(status), info->pathname);
623060c859dSBob Moore return;
624060c859dSBob Moore }
625060c859dSBob Moore
626060c859dSBob Moore /* Display a return object, if any */
627060c859dSBob Moore
628060c859dSBob Moore if (return_obj.length) {
629060c859dSBob Moore acpi_os_printf("Evaluation of %s returned object %p, "
630060c859dSBob Moore "external buffer length %X\n",
631060c859dSBob Moore acpi_gbl_db_method_info.pathname,
632060c859dSBob Moore return_obj.pointer, (u32)return_obj.length);
633060c859dSBob Moore
634060c859dSBob Moore acpi_db_dump_external_object(return_obj.pointer, 1);
635060c859dSBob Moore }
636060c859dSBob Moore
637060c859dSBob Moore acpi_os_printf("\nBackground thread completed\n%c ",
638060c859dSBob Moore ACPI_DEBUGGER_COMMAND_PROMPT);
639060c859dSBob Moore }
640060c859dSBob Moore
641060c859dSBob Moore /*******************************************************************************
642060c859dSBob Moore *
643060c859dSBob Moore * FUNCTION: acpi_db_create_execution_thread
644060c859dSBob Moore *
645060c859dSBob Moore * PARAMETERS: method_name_arg - Control method to execute
646060c859dSBob Moore * arguments - Array of arguments to the method
647060c859dSBob Moore * types - Corresponding array of object types
648060c859dSBob Moore *
649060c859dSBob Moore * RETURN: None
650060c859dSBob Moore *
651060c859dSBob Moore * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles
652060c859dSBob Moore * arguments passed on command line for control methods.
653060c859dSBob Moore *
654060c859dSBob Moore ******************************************************************************/
655060c859dSBob Moore
656060c859dSBob Moore void
acpi_db_create_execution_thread(char * method_name_arg,char ** arguments,acpi_object_type * types)657060c859dSBob Moore acpi_db_create_execution_thread(char *method_name_arg,
658060c859dSBob Moore char **arguments, acpi_object_type *types)
659060c859dSBob Moore {
660060c859dSBob Moore acpi_status status;
661060c859dSBob Moore u32 i;
662060c859dSBob Moore
663060c859dSBob Moore memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
664060c859dSBob Moore acpi_gbl_db_method_info.name = method_name_arg;
665060c859dSBob Moore acpi_gbl_db_method_info.init_args = 1;
666060c859dSBob Moore acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
667060c859dSBob Moore acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
668060c859dSBob Moore
669060c859dSBob Moore /* Setup method arguments, up to 7 (0-6) */
670060c859dSBob Moore
671060c859dSBob Moore for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) {
672060c859dSBob Moore acpi_gbl_db_method_info.arguments[i] = *arguments;
673060c859dSBob Moore arguments++;
674060c859dSBob Moore
675060c859dSBob Moore acpi_gbl_db_method_info.arg_types[i] = *types;
676060c859dSBob Moore types++;
677060c859dSBob Moore }
678060c859dSBob Moore
679060c859dSBob Moore status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
680060c859dSBob Moore if (ACPI_FAILURE(status)) {
681060c859dSBob Moore return;
682060c859dSBob Moore }
683060c859dSBob Moore
684060c859dSBob Moore /* Get the NS node, determines existence also */
685060c859dSBob Moore
686060c859dSBob Moore status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
687060c859dSBob Moore &acpi_gbl_db_method_info.method);
688060c859dSBob Moore if (ACPI_FAILURE(status)) {
689060c859dSBob Moore acpi_os_printf("%s Could not get handle for %s\n",
690060c859dSBob Moore acpi_format_exception(status),
691060c859dSBob Moore acpi_gbl_db_method_info.pathname);
692060c859dSBob Moore return;
693060c859dSBob Moore }
694060c859dSBob Moore
695060c859dSBob Moore status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
696060c859dSBob Moore acpi_db_single_execution_thread,
697060c859dSBob Moore &acpi_gbl_db_method_info);
698060c859dSBob Moore if (ACPI_FAILURE(status)) {
699060c859dSBob Moore return;
700060c859dSBob Moore }
701060c859dSBob Moore
702060c859dSBob Moore acpi_os_printf("\nBackground thread started\n");
703060c859dSBob Moore }
704060c859dSBob Moore
705060c859dSBob Moore /*******************************************************************************
706060c859dSBob Moore *
70799575102SLv Zheng * FUNCTION: acpi_db_create_execution_threads
70899575102SLv Zheng *
70999575102SLv Zheng * PARAMETERS: num_threads_arg - Number of threads to create
71099575102SLv Zheng * num_loops_arg - Loop count for the thread(s)
71199575102SLv Zheng * method_name_arg - Control method to execute
71299575102SLv Zheng *
71399575102SLv Zheng * RETURN: None
71499575102SLv Zheng *
71599575102SLv Zheng * DESCRIPTION: Create threads to execute method(s)
71699575102SLv Zheng *
71799575102SLv Zheng ******************************************************************************/
71899575102SLv Zheng
71999575102SLv Zheng void
acpi_db_create_execution_threads(char * num_threads_arg,char * num_loops_arg,char * method_name_arg)72099575102SLv Zheng acpi_db_create_execution_threads(char *num_threads_arg,
72199575102SLv Zheng char *num_loops_arg, char *method_name_arg)
72299575102SLv Zheng {
72399575102SLv Zheng acpi_status status;
72499575102SLv Zheng u32 num_threads;
72599575102SLv Zheng u32 num_loops;
72699575102SLv Zheng u32 i;
72799575102SLv Zheng u32 size;
72899575102SLv Zheng acpi_mutex main_thread_gate;
72999575102SLv Zheng acpi_mutex thread_complete_gate;
73099575102SLv Zheng acpi_mutex info_gate;
73199575102SLv Zheng
73299575102SLv Zheng /* Get the arguments */
73399575102SLv Zheng
73499575102SLv Zheng num_threads = strtoul(num_threads_arg, NULL, 0);
73599575102SLv Zheng num_loops = strtoul(num_loops_arg, NULL, 0);
73699575102SLv Zheng
73799575102SLv Zheng if (!num_threads || !num_loops) {
73899575102SLv Zheng acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
73999575102SLv Zheng num_threads, num_loops);
74099575102SLv Zheng return;
74199575102SLv Zheng }
74299575102SLv Zheng
74399575102SLv Zheng /*
74499575102SLv Zheng * Create the semaphore for synchronization of
74599575102SLv Zheng * the created threads with the main thread.
74699575102SLv Zheng */
74799575102SLv Zheng status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
74899575102SLv Zheng if (ACPI_FAILURE(status)) {
74999575102SLv Zheng acpi_os_printf("Could not create semaphore for "
75099575102SLv Zheng "synchronization with the main thread, %s\n",
75199575102SLv Zheng acpi_format_exception(status));
75299575102SLv Zheng return;
75399575102SLv Zheng }
75499575102SLv Zheng
75599575102SLv Zheng /*
75699575102SLv Zheng * Create the semaphore for synchronization
75799575102SLv Zheng * between the created threads.
75899575102SLv Zheng */
75999575102SLv Zheng status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
76099575102SLv Zheng if (ACPI_FAILURE(status)) {
76199575102SLv Zheng acpi_os_printf("Could not create semaphore for "
76299575102SLv Zheng "synchronization between the created threads, %s\n",
76399575102SLv Zheng acpi_format_exception(status));
76499575102SLv Zheng
76599575102SLv Zheng (void)acpi_os_delete_semaphore(main_thread_gate);
76699575102SLv Zheng return;
76799575102SLv Zheng }
76899575102SLv Zheng
76999575102SLv Zheng status = acpi_os_create_semaphore(1, 1, &info_gate);
77099575102SLv Zheng if (ACPI_FAILURE(status)) {
77199575102SLv Zheng acpi_os_printf("Could not create semaphore for "
77299575102SLv Zheng "synchronization of AcpiGbl_DbMethodInfo, %s\n",
77399575102SLv Zheng acpi_format_exception(status));
77499575102SLv Zheng
77599575102SLv Zheng (void)acpi_os_delete_semaphore(thread_complete_gate);
77699575102SLv Zheng (void)acpi_os_delete_semaphore(main_thread_gate);
77799575102SLv Zheng return;
77899575102SLv Zheng }
77999575102SLv Zheng
78099575102SLv Zheng memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
78199575102SLv Zheng
78299575102SLv Zheng /* Array to store IDs of threads */
78399575102SLv Zheng
78499575102SLv Zheng acpi_gbl_db_method_info.num_threads = num_threads;
78599575102SLv Zheng size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
78699575102SLv Zheng
78799575102SLv Zheng acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
78899575102SLv Zheng if (acpi_gbl_db_method_info.threads == NULL) {
78999575102SLv Zheng acpi_os_printf("No memory for thread IDs array\n");
79099575102SLv Zheng (void)acpi_os_delete_semaphore(main_thread_gate);
79199575102SLv Zheng (void)acpi_os_delete_semaphore(thread_complete_gate);
79299575102SLv Zheng (void)acpi_os_delete_semaphore(info_gate);
79399575102SLv Zheng return;
79499575102SLv Zheng }
79599575102SLv Zheng memset(acpi_gbl_db_method_info.threads, 0, size);
79699575102SLv Zheng
79799575102SLv Zheng /* Setup the context to be passed to each thread */
79899575102SLv Zheng
79999575102SLv Zheng acpi_gbl_db_method_info.name = method_name_arg;
80099575102SLv Zheng acpi_gbl_db_method_info.flags = 0;
80199575102SLv Zheng acpi_gbl_db_method_info.num_loops = num_loops;
80299575102SLv Zheng acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
80399575102SLv Zheng acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
80499575102SLv Zheng acpi_gbl_db_method_info.info_gate = info_gate;
80599575102SLv Zheng
80699575102SLv Zheng /* Init arguments to be passed to method */
80799575102SLv Zheng
80899575102SLv Zheng acpi_gbl_db_method_info.init_args = 1;
80999575102SLv Zheng acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
81099575102SLv Zheng acpi_gbl_db_method_info.arguments[0] =
81199575102SLv Zheng acpi_gbl_db_method_info.num_threads_str;
81299575102SLv Zheng acpi_gbl_db_method_info.arguments[1] =
81399575102SLv Zheng acpi_gbl_db_method_info.id_of_thread_str;
81499575102SLv Zheng acpi_gbl_db_method_info.arguments[2] =
81599575102SLv Zheng acpi_gbl_db_method_info.index_of_thread_str;
81699575102SLv Zheng acpi_gbl_db_method_info.arguments[3] = NULL;
81799575102SLv Zheng
81899575102SLv Zheng acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
81999575102SLv Zheng acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
82099575102SLv Zheng acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
82199575102SLv Zheng acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
82299575102SLv Zheng
82399575102SLv Zheng acpi_db_uint32_to_hex_string(num_threads,
82499575102SLv Zheng acpi_gbl_db_method_info.num_threads_str);
82599575102SLv Zheng
82699575102SLv Zheng status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
82799575102SLv Zheng if (ACPI_FAILURE(status)) {
82899575102SLv Zheng goto cleanup_and_exit;
82999575102SLv Zheng }
83099575102SLv Zheng
83199575102SLv Zheng /* Get the NS node, determines existence also */
83299575102SLv Zheng
83399575102SLv Zheng status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
83499575102SLv Zheng &acpi_gbl_db_method_info.method);
83599575102SLv Zheng if (ACPI_FAILURE(status)) {
83699575102SLv Zheng acpi_os_printf("%s Could not get handle for %s\n",
83799575102SLv Zheng acpi_format_exception(status),
83899575102SLv Zheng acpi_gbl_db_method_info.pathname);
83999575102SLv Zheng goto cleanup_and_exit;
84099575102SLv Zheng }
84199575102SLv Zheng
84299575102SLv Zheng /* Create the threads */
84399575102SLv Zheng
84499575102SLv Zheng acpi_os_printf("Creating %X threads to execute %X times each\n",
84599575102SLv Zheng num_threads, num_loops);
84699575102SLv Zheng
84799575102SLv Zheng for (i = 0; i < (num_threads); i++) {
84899575102SLv Zheng status =
849f988f24eSLv Zheng acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
850f988f24eSLv Zheng acpi_db_method_thread,
85199575102SLv Zheng &acpi_gbl_db_method_info);
85299575102SLv Zheng if (ACPI_FAILURE(status)) {
85399575102SLv Zheng break;
85499575102SLv Zheng }
85599575102SLv Zheng }
85699575102SLv Zheng
85799575102SLv Zheng /* Wait for all threads to complete */
85899575102SLv Zheng
85999575102SLv Zheng (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
86099575102SLv Zheng
86199575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
86299575102SLv Zheng acpi_os_printf("All threads (%X) have completed\n", num_threads);
86399575102SLv Zheng acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
86499575102SLv Zheng
86599575102SLv Zheng cleanup_and_exit:
86699575102SLv Zheng
86799575102SLv Zheng /* Cleanup and exit */
86899575102SLv Zheng
86999575102SLv Zheng (void)acpi_os_delete_semaphore(main_thread_gate);
87099575102SLv Zheng (void)acpi_os_delete_semaphore(thread_complete_gate);
87199575102SLv Zheng (void)acpi_os_delete_semaphore(info_gate);
87299575102SLv Zheng
87399575102SLv Zheng acpi_os_free(acpi_gbl_db_method_info.threads);
87499575102SLv Zheng acpi_gbl_db_method_info.threads = NULL;
87599575102SLv Zheng }
876