162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: dbexec - debugger control method execution 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <acpi/acpi.h> 962306a36Sopenharmony_ci#include "accommon.h" 1062306a36Sopenharmony_ci#include "acdebug.h" 1162306a36Sopenharmony_ci#include "acnamesp.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define _COMPONENT ACPI_CA_DEBUGGER 1462306a36Sopenharmony_ciACPI_MODULE_NAME("dbexec") 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic struct acpi_db_method_info acpi_gbl_db_method_info; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Local prototypes */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic acpi_status 2162306a36Sopenharmony_ciacpi_db_execute_method(struct acpi_db_method_info *info, 2262306a36Sopenharmony_ci struct acpi_buffer *return_obj); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic u32 acpi_db_get_outstanding_allocations(void); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic acpi_status 3162306a36Sopenharmony_ciacpi_db_execution_walk(acpi_handle obj_handle, 3262306a36Sopenharmony_ci u32 nesting_level, void *context, void **return_value); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/******************************************************************************* 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * FUNCTION: acpi_db_delete_objects 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * PARAMETERS: count - Count of objects in the list 4162306a36Sopenharmony_ci * objects - Array of ACPI_OBJECTs to be deleted 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * RETURN: None 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 4662306a36Sopenharmony_ci * packages via recursion. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci ******************************************************************************/ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_civoid acpi_db_delete_objects(u32 count, union acpi_object *objects) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci u32 i; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci for (i = 0; i < count; i++) { 5562306a36Sopenharmony_ci switch (objects[i].type) { 5662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci ACPI_FREE(objects[i].buffer.pointer); 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* Recursive call to delete package elements */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci acpi_db_delete_objects(objects[i].package.count, 6662306a36Sopenharmony_ci objects[i].package.elements); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci /* Free the elements array */ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ACPI_FREE(objects[i].package.elements); 7162306a36Sopenharmony_ci break; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci default: 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci break; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/******************************************************************************* 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * FUNCTION: acpi_db_execute_method 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * PARAMETERS: info - Valid info segment 8562306a36Sopenharmony_ci * return_obj - Where to put return object 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * RETURN: Status 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * DESCRIPTION: Execute a control method. Used to evaluate objects via the 9062306a36Sopenharmony_ci * "EXECUTE" or "EVALUATE" commands. 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci ******************************************************************************/ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic acpi_status 9562306a36Sopenharmony_ciacpi_db_execute_method(struct acpi_db_method_info *info, 9662306a36Sopenharmony_ci struct acpi_buffer *return_obj) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci acpi_status status; 9962306a36Sopenharmony_ci struct acpi_object_list param_objects; 10062306a36Sopenharmony_ci union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1]; 10162306a36Sopenharmony_ci u32 i; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(db_execute_method); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (acpi_gbl_db_output_to_file && !acpi_dbg_level) { 10662306a36Sopenharmony_ci acpi_os_printf("Warning: debug output is not enabled!\n"); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci param_objects.count = 0; 11062306a36Sopenharmony_ci param_objects.pointer = NULL; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* Pass through any command-line arguments */ 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (info->args && info->args[0]) { 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* Get arguments passed on the command line */ 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci for (i = 0; (info->args[i] && *(info->args[i])); i++) { 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Convert input string (token) to an actual union acpi_object */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci status = acpi_db_convert_to_object(info->types[i], 12362306a36Sopenharmony_ci info->args[i], 12462306a36Sopenharmony_ci ¶ms[i]); 12562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 12662306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 12762306a36Sopenharmony_ci "While parsing method arguments")); 12862306a36Sopenharmony_ci goto cleanup; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci param_objects.count = i; 13362306a36Sopenharmony_ci param_objects.pointer = params; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Prepare for a return object of arbitrary size */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return_obj->pointer = acpi_gbl_db_buffer; 13962306a36Sopenharmony_ci return_obj->length = ACPI_DEBUG_BUFFER_SIZE; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Do the actual method execution */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci acpi_gbl_method_executing = TRUE; 14462306a36Sopenharmony_ci status = acpi_evaluate_object(NULL, info->pathname, 14562306a36Sopenharmony_ci ¶m_objects, return_obj); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci acpi_gbl_cm_single_step = FALSE; 14862306a36Sopenharmony_ci acpi_gbl_method_executing = FALSE; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 15162306a36Sopenharmony_ci if ((status == AE_ABORT_METHOD) || acpi_gbl_abort_method) { 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* Clear the abort and fall back to the debugger prompt */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 15662306a36Sopenharmony_ci "Aborting top-level method")); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci acpi_gbl_abort_method = FALSE; 15962306a36Sopenharmony_ci status = AE_OK; 16062306a36Sopenharmony_ci goto cleanup; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 16462306a36Sopenharmony_ci "while executing %s from AML Debugger", 16562306a36Sopenharmony_ci info->pathname)); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (status == AE_BUFFER_OVERFLOW) { 16862306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 16962306a36Sopenharmony_ci "Possible buffer overflow within AML Debugger " 17062306a36Sopenharmony_ci "buffer (size 0x%X needed 0x%X)", 17162306a36Sopenharmony_ci ACPI_DEBUG_BUFFER_SIZE, 17262306a36Sopenharmony_ci (u32)return_obj->length)); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cicleanup: 17762306a36Sopenharmony_ci acpi_db_delete_objects(param_objects.count, params); 17862306a36Sopenharmony_ci return_ACPI_STATUS(status); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/******************************************************************************* 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * FUNCTION: acpi_db_execute_setup 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * PARAMETERS: info - Valid method info 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * RETURN: None 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * DESCRIPTION: Setup info segment prior to method execution 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci ******************************************************************************/ 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci acpi_status status; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci ACPI_FUNCTION_NAME(db_execute_setup); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* Concatenate the current scope to the supplied name */ 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci info->pathname[0] = 0; 20262306a36Sopenharmony_ci if ((info->name[0] != '\\') && (info->name[0] != '/')) { 20362306a36Sopenharmony_ci if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname), 20462306a36Sopenharmony_ci acpi_gbl_db_scope_buf)) { 20562306a36Sopenharmony_ci status = AE_BUFFER_OVERFLOW; 20662306a36Sopenharmony_ci goto error_exit; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname), 21162306a36Sopenharmony_ci info->name)) { 21262306a36Sopenharmony_ci status = AE_BUFFER_OVERFLOW; 21362306a36Sopenharmony_ci goto error_exit; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci acpi_db_prep_namestring(info->pathname); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 21962306a36Sopenharmony_ci acpi_os_printf("Evaluating %s\n", info->pathname); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (info->flags & EX_SINGLE_STEP) { 22262306a36Sopenharmony_ci acpi_gbl_cm_single_step = TRUE; 22362306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci else { 22762306a36Sopenharmony_ci /* No single step, allow redirection to a file */ 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return (AE_OK); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cierror_exit: 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution")); 23762306a36Sopenharmony_ci return (status); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci#ifdef ACPI_DBG_TRACK_ALLOCATIONS 24162306a36Sopenharmony_ciu32 acpi_db_get_cache_info(struct acpi_memory_list *cache) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return (cache->total_allocated - cache->total_freed - 24562306a36Sopenharmony_ci cache->current_depth); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci#endif 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/******************************************************************************* 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * FUNCTION: acpi_db_get_outstanding_allocations 25262306a36Sopenharmony_ci * 25362306a36Sopenharmony_ci * PARAMETERS: None 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * RETURN: Current global allocation count minus cache entries 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci * DESCRIPTION: Determine the current number of "outstanding" allocations -- 25862306a36Sopenharmony_ci * those allocations that have not been freed and also are not 25962306a36Sopenharmony_ci * in one of the various object caches. 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci ******************************************************************************/ 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic u32 acpi_db_get_outstanding_allocations(void) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci u32 outstanding = 0; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci#ifdef ACPI_DBG_TRACK_ALLOCATIONS 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache); 27062306a36Sopenharmony_ci outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache); 27162306a36Sopenharmony_ci outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache); 27262306a36Sopenharmony_ci outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache); 27362306a36Sopenharmony_ci#endif 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci return (outstanding); 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/******************************************************************************* 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * FUNCTION: acpi_db_execution_walk 28162306a36Sopenharmony_ci * 28262306a36Sopenharmony_ci * PARAMETERS: WALK_CALLBACK 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * RETURN: Status 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * DESCRIPTION: Execute a control method. Name is relative to the current 28762306a36Sopenharmony_ci * scope. 28862306a36Sopenharmony_ci * 28962306a36Sopenharmony_ci ******************************************************************************/ 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic acpi_status 29262306a36Sopenharmony_ciacpi_db_execution_walk(acpi_handle obj_handle, 29362306a36Sopenharmony_ci u32 nesting_level, void *context, void **return_value) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 29662306a36Sopenharmony_ci struct acpi_namespace_node *node = 29762306a36Sopenharmony_ci (struct acpi_namespace_node *)obj_handle; 29862306a36Sopenharmony_ci struct acpi_buffer return_obj; 29962306a36Sopenharmony_ci acpi_status status; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci obj_desc = acpi_ns_get_attached_object(node); 30262306a36Sopenharmony_ci if (obj_desc->method.param_count) { 30362306a36Sopenharmony_ci return (AE_OK); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return_obj.pointer = NULL; 30762306a36Sopenharmony_ci return_obj.length = ACPI_ALLOCATE_BUFFER; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci acpi_ns_print_node_pathname(node, "Evaluating"); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* Do the actual method execution */ 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci acpi_os_printf("\n"); 31462306a36Sopenharmony_ci acpi_gbl_method_executing = TRUE; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci status = acpi_evaluate_object(node, NULL, NULL, &return_obj); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci acpi_gbl_method_executing = FALSE; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci acpi_os_printf("Evaluation of [%4.4s] returned %s\n", 32162306a36Sopenharmony_ci acpi_ut_get_node_name(node), 32262306a36Sopenharmony_ci acpi_format_exception(status)); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci return (AE_OK); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/******************************************************************************* 32862306a36Sopenharmony_ci * 32962306a36Sopenharmony_ci * FUNCTION: acpi_db_execute 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * PARAMETERS: name - Name of method to execute 33262306a36Sopenharmony_ci * args - Parameters to the method 33362306a36Sopenharmony_ci * Types - 33462306a36Sopenharmony_ci * flags - single step/no single step 33562306a36Sopenharmony_ci * 33662306a36Sopenharmony_ci * RETURN: None 33762306a36Sopenharmony_ci * 33862306a36Sopenharmony_ci * DESCRIPTION: Execute a control method. Name is relative to the current 33962306a36Sopenharmony_ci * scope. Function used for the "EXECUTE", "EVALUATE", and 34062306a36Sopenharmony_ci * "ALL" commands 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci ******************************************************************************/ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_civoid 34562306a36Sopenharmony_ciacpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci acpi_status status; 34862306a36Sopenharmony_ci struct acpi_buffer return_obj; 34962306a36Sopenharmony_ci char *name_string; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci#ifdef ACPI_DEBUG_OUTPUT 35262306a36Sopenharmony_ci u32 previous_allocations; 35362306a36Sopenharmony_ci u32 allocations; 35462306a36Sopenharmony_ci#endif 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * Allow one execution to be performed by debugger or single step 35862306a36Sopenharmony_ci * execution will be dead locked by the interpreter mutexes. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci if (acpi_gbl_method_executing) { 36162306a36Sopenharmony_ci acpi_os_printf("Only one debugger execution is allowed.\n"); 36262306a36Sopenharmony_ci return; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci#ifdef ACPI_DEBUG_OUTPUT 36562306a36Sopenharmony_ci /* Memory allocation tracking */ 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci previous_allocations = acpi_db_get_outstanding_allocations(); 36862306a36Sopenharmony_ci#endif 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (*name == '*') { 37162306a36Sopenharmony_ci (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 37262306a36Sopenharmony_ci ACPI_UINT32_MAX, 37362306a36Sopenharmony_ci acpi_db_execution_walk, NULL, NULL, 37462306a36Sopenharmony_ci NULL); 37562306a36Sopenharmony_ci return; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if ((flags & EX_ALL) && (strlen(name) > 4)) { 37962306a36Sopenharmony_ci acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n", 38062306a36Sopenharmony_ci name); 38162306a36Sopenharmony_ci return; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci name_string = ACPI_ALLOCATE(strlen(name) + 1); 38562306a36Sopenharmony_ci if (!name_string) { 38662306a36Sopenharmony_ci return; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); 39062306a36Sopenharmony_ci strcpy(name_string, name); 39162306a36Sopenharmony_ci acpi_ut_strupr(name_string); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* Subcommand to Execute all predefined names in the namespace */ 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (!strncmp(name_string, "PREDEF", 6)) { 39662306a36Sopenharmony_ci acpi_db_evaluate_predefined_names(); 39762306a36Sopenharmony_ci ACPI_FREE(name_string); 39862306a36Sopenharmony_ci return; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Command (ALL <nameseg>) to execute all methods of a particular name */ 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci else if (flags & EX_ALL) { 40462306a36Sopenharmony_ci acpi_gbl_db_method_info.name = name_string; 40562306a36Sopenharmony_ci return_obj.pointer = NULL; 40662306a36Sopenharmony_ci return_obj.length = ACPI_ALLOCATE_BUFFER; 40762306a36Sopenharmony_ci acpi_db_evaluate_all(name_string); 40862306a36Sopenharmony_ci ACPI_FREE(name_string); 40962306a36Sopenharmony_ci return; 41062306a36Sopenharmony_ci } else { 41162306a36Sopenharmony_ci acpi_gbl_db_method_info.name = name_string; 41262306a36Sopenharmony_ci acpi_gbl_db_method_info.args = args; 41362306a36Sopenharmony_ci acpi_gbl_db_method_info.types = types; 41462306a36Sopenharmony_ci acpi_gbl_db_method_info.flags = flags; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci return_obj.pointer = NULL; 41762306a36Sopenharmony_ci return_obj.length = ACPI_ALLOCATE_BUFFER; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci status = acpi_db_execute_setup(&acpi_gbl_db_method_info); 42162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 42262306a36Sopenharmony_ci ACPI_FREE(name_string); 42362306a36Sopenharmony_ci return; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* Get the NS node, determines existence also */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, 42962306a36Sopenharmony_ci &acpi_gbl_db_method_info.method); 43062306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 43162306a36Sopenharmony_ci status = acpi_db_execute_method(&acpi_gbl_db_method_info, 43262306a36Sopenharmony_ci &return_obj); 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci ACPI_FREE(name_string); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* 43762306a36Sopenharmony_ci * Allow any handlers in separate threads to complete. 43862306a36Sopenharmony_ci * (Such as Notify handlers invoked from AML executed above). 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci acpi_os_sleep((u64)10); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci#ifdef ACPI_DEBUG_OUTPUT 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* Memory allocation tracking */ 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci allocations = 44762306a36Sopenharmony_ci acpi_db_get_outstanding_allocations() - previous_allocations; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (allocations > 0) { 45262306a36Sopenharmony_ci acpi_os_printf 45362306a36Sopenharmony_ci ("0x%X Outstanding allocations after evaluation of %s\n", 45462306a36Sopenharmony_ci allocations, acpi_gbl_db_method_info.pathname); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci#endif 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 45962306a36Sopenharmony_ci acpi_os_printf("Evaluation of %s failed with status %s\n", 46062306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname, 46162306a36Sopenharmony_ci acpi_format_exception(status)); 46262306a36Sopenharmony_ci } else { 46362306a36Sopenharmony_ci /* Display a return object, if any */ 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci if (return_obj.length) { 46662306a36Sopenharmony_ci acpi_os_printf("Evaluation of %s returned object %p, " 46762306a36Sopenharmony_ci "external buffer length %X\n", 46862306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname, 46962306a36Sopenharmony_ci return_obj.pointer, 47062306a36Sopenharmony_ci (u32)return_obj.length); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci acpi_db_dump_external_object(return_obj.pointer, 1); 47362306a36Sopenharmony_ci acpi_os_printf("\n"); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Dump a _PLD buffer if present */ 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (ACPI_COMPARE_NAMESEG 47862306a36Sopenharmony_ci ((ACPI_CAST_PTR 47962306a36Sopenharmony_ci (struct acpi_namespace_node, 48062306a36Sopenharmony_ci acpi_gbl_db_method_info.method)->name.ascii), 48162306a36Sopenharmony_ci METHOD_NAME__PLD)) { 48262306a36Sopenharmony_ci acpi_db_dump_pld_buffer(return_obj.pointer); 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci } else { 48562306a36Sopenharmony_ci acpi_os_printf 48662306a36Sopenharmony_ci ("No object was returned from evaluation of %s\n", 48762306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname); 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/******************************************************************************* 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * FUNCTION: acpi_db_method_thread 49762306a36Sopenharmony_ci * 49862306a36Sopenharmony_ci * PARAMETERS: context - Execution info segment 49962306a36Sopenharmony_ci * 50062306a36Sopenharmony_ci * RETURN: None 50162306a36Sopenharmony_ci * 50262306a36Sopenharmony_ci * DESCRIPTION: Debugger execute thread. Waits for a command line, then 50362306a36Sopenharmony_ci * simply dispatches it. 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci ******************************************************************************/ 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci acpi_status status; 51062306a36Sopenharmony_ci struct acpi_db_method_info *info = context; 51162306a36Sopenharmony_ci struct acpi_db_method_info local_info; 51262306a36Sopenharmony_ci u32 i; 51362306a36Sopenharmony_ci u8 allow; 51462306a36Sopenharmony_ci struct acpi_buffer return_obj; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* 51762306a36Sopenharmony_ci * acpi_gbl_db_method_info.Arguments will be passed as method arguments. 51862306a36Sopenharmony_ci * Prevent acpi_gbl_db_method_info from being modified by multiple threads 51962306a36Sopenharmony_ci * concurrently. 52062306a36Sopenharmony_ci * 52162306a36Sopenharmony_ci * Note: The arguments we are passing are used by the ASL test suite 52262306a36Sopenharmony_ci * (aslts). Do not change them without updating the tests. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (info->init_args) { 52762306a36Sopenharmony_ci acpi_db_uint32_to_hex_string(info->num_created, 52862306a36Sopenharmony_ci info->index_of_thread_str); 52962306a36Sopenharmony_ci acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(), 53062306a36Sopenharmony_ci info->id_of_thread_str); 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (info->threads && (info->num_created < info->num_threads)) { 53462306a36Sopenharmony_ci info->threads[info->num_created++] = acpi_os_get_thread_id(); 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci local_info = *info; 53862306a36Sopenharmony_ci local_info.args = local_info.arguments; 53962306a36Sopenharmony_ci local_info.arguments[0] = local_info.num_threads_str; 54062306a36Sopenharmony_ci local_info.arguments[1] = local_info.id_of_thread_str; 54162306a36Sopenharmony_ci local_info.arguments[2] = local_info.index_of_thread_str; 54262306a36Sopenharmony_ci local_info.arguments[3] = NULL; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci local_info.types = local_info.arg_types; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci (void)acpi_os_signal_semaphore(info->info_gate, 1); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci for (i = 0; i < info->num_loops; i++) { 54962306a36Sopenharmony_ci status = acpi_db_execute_method(&local_info, &return_obj); 55062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 55162306a36Sopenharmony_ci acpi_os_printf 55262306a36Sopenharmony_ci ("%s During evaluation of %s at iteration %X\n", 55362306a36Sopenharmony_ci acpi_format_exception(status), info->pathname, i); 55462306a36Sopenharmony_ci if (status == AE_ABORT_METHOD) { 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci#if 0 55962306a36Sopenharmony_ci if ((i % 100) == 0) { 56062306a36Sopenharmony_ci acpi_os_printf("%u loops, Thread 0x%x\n", 56162306a36Sopenharmony_ci i, acpi_os_get_thread_id()); 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (return_obj.length) { 56562306a36Sopenharmony_ci acpi_os_printf 56662306a36Sopenharmony_ci ("Evaluation of %s returned object %p Buflen %X\n", 56762306a36Sopenharmony_ci info->pathname, return_obj.pointer, 56862306a36Sopenharmony_ci (u32)return_obj.length); 56962306a36Sopenharmony_ci acpi_db_dump_external_object(return_obj.pointer, 1); 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci#endif 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* Signal our completion */ 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci allow = 0; 57762306a36Sopenharmony_ci (void)acpi_os_wait_semaphore(info->thread_complete_gate, 57862306a36Sopenharmony_ci 1, ACPI_WAIT_FOREVER); 57962306a36Sopenharmony_ci info->num_completed++; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (info->num_completed == info->num_threads) { 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* Do signal for main thread once only */ 58462306a36Sopenharmony_ci allow = 1; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci if (allow) { 59062306a36Sopenharmony_ci status = acpi_os_signal_semaphore(info->main_thread_gate, 1); 59162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 59262306a36Sopenharmony_ci acpi_os_printf 59362306a36Sopenharmony_ci ("Could not signal debugger thread sync semaphore, %s\n", 59462306a36Sopenharmony_ci acpi_format_exception(status)); 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci/******************************************************************************* 60062306a36Sopenharmony_ci * 60162306a36Sopenharmony_ci * FUNCTION: acpi_db_single_execution_thread 60262306a36Sopenharmony_ci * 60362306a36Sopenharmony_ci * PARAMETERS: context - Method info struct 60462306a36Sopenharmony_ci * 60562306a36Sopenharmony_ci * RETURN: None 60662306a36Sopenharmony_ci * 60762306a36Sopenharmony_ci * DESCRIPTION: Create one thread and execute a method 60862306a36Sopenharmony_ci * 60962306a36Sopenharmony_ci ******************************************************************************/ 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci struct acpi_db_method_info *info = context; 61462306a36Sopenharmony_ci acpi_status status; 61562306a36Sopenharmony_ci struct acpi_buffer return_obj; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci acpi_os_printf("\n"); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci status = acpi_db_execute_method(info, &return_obj); 62062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 62162306a36Sopenharmony_ci acpi_os_printf("%s During evaluation of %s\n", 62262306a36Sopenharmony_ci acpi_format_exception(status), info->pathname); 62362306a36Sopenharmony_ci return; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* Display a return object, if any */ 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (return_obj.length) { 62962306a36Sopenharmony_ci acpi_os_printf("Evaluation of %s returned object %p, " 63062306a36Sopenharmony_ci "external buffer length %X\n", 63162306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname, 63262306a36Sopenharmony_ci return_obj.pointer, (u32)return_obj.length); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci acpi_db_dump_external_object(return_obj.pointer, 1); 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci acpi_os_printf("\nBackground thread completed\n%c ", 63862306a36Sopenharmony_ci ACPI_DEBUGGER_COMMAND_PROMPT); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci/******************************************************************************* 64262306a36Sopenharmony_ci * 64362306a36Sopenharmony_ci * FUNCTION: acpi_db_create_execution_thread 64462306a36Sopenharmony_ci * 64562306a36Sopenharmony_ci * PARAMETERS: method_name_arg - Control method to execute 64662306a36Sopenharmony_ci * arguments - Array of arguments to the method 64762306a36Sopenharmony_ci * types - Corresponding array of object types 64862306a36Sopenharmony_ci * 64962306a36Sopenharmony_ci * RETURN: None 65062306a36Sopenharmony_ci * 65162306a36Sopenharmony_ci * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles 65262306a36Sopenharmony_ci * arguments passed on command line for control methods. 65362306a36Sopenharmony_ci * 65462306a36Sopenharmony_ci ******************************************************************************/ 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_civoid 65762306a36Sopenharmony_ciacpi_db_create_execution_thread(char *method_name_arg, 65862306a36Sopenharmony_ci char **arguments, acpi_object_type *types) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci acpi_status status; 66162306a36Sopenharmony_ci u32 i; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); 66462306a36Sopenharmony_ci acpi_gbl_db_method_info.name = method_name_arg; 66562306a36Sopenharmony_ci acpi_gbl_db_method_info.init_args = 1; 66662306a36Sopenharmony_ci acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments; 66762306a36Sopenharmony_ci acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* Setup method arguments, up to 7 (0-6) */ 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) { 67262306a36Sopenharmony_ci acpi_gbl_db_method_info.arguments[i] = *arguments; 67362306a36Sopenharmony_ci arguments++; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci acpi_gbl_db_method_info.arg_types[i] = *types; 67662306a36Sopenharmony_ci types++; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci status = acpi_db_execute_setup(&acpi_gbl_db_method_info); 68062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 68162306a36Sopenharmony_ci return; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci /* Get the NS node, determines existence also */ 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, 68762306a36Sopenharmony_ci &acpi_gbl_db_method_info.method); 68862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 68962306a36Sopenharmony_ci acpi_os_printf("%s Could not get handle for %s\n", 69062306a36Sopenharmony_ci acpi_format_exception(status), 69162306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname); 69262306a36Sopenharmony_ci return; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD, 69662306a36Sopenharmony_ci acpi_db_single_execution_thread, 69762306a36Sopenharmony_ci &acpi_gbl_db_method_info); 69862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 69962306a36Sopenharmony_ci return; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci acpi_os_printf("\nBackground thread started\n"); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci/******************************************************************************* 70662306a36Sopenharmony_ci * 70762306a36Sopenharmony_ci * FUNCTION: acpi_db_create_execution_threads 70862306a36Sopenharmony_ci * 70962306a36Sopenharmony_ci * PARAMETERS: num_threads_arg - Number of threads to create 71062306a36Sopenharmony_ci * num_loops_arg - Loop count for the thread(s) 71162306a36Sopenharmony_ci * method_name_arg - Control method to execute 71262306a36Sopenharmony_ci * 71362306a36Sopenharmony_ci * RETURN: None 71462306a36Sopenharmony_ci * 71562306a36Sopenharmony_ci * DESCRIPTION: Create threads to execute method(s) 71662306a36Sopenharmony_ci * 71762306a36Sopenharmony_ci ******************************************************************************/ 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_civoid 72062306a36Sopenharmony_ciacpi_db_create_execution_threads(char *num_threads_arg, 72162306a36Sopenharmony_ci char *num_loops_arg, char *method_name_arg) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci acpi_status status; 72462306a36Sopenharmony_ci u32 num_threads; 72562306a36Sopenharmony_ci u32 num_loops; 72662306a36Sopenharmony_ci u32 i; 72762306a36Sopenharmony_ci u32 size; 72862306a36Sopenharmony_ci acpi_mutex main_thread_gate; 72962306a36Sopenharmony_ci acpi_mutex thread_complete_gate; 73062306a36Sopenharmony_ci acpi_mutex info_gate; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci /* Get the arguments */ 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci num_threads = strtoul(num_threads_arg, NULL, 0); 73562306a36Sopenharmony_ci num_loops = strtoul(num_loops_arg, NULL, 0); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (!num_threads || !num_loops) { 73862306a36Sopenharmony_ci acpi_os_printf("Bad argument: Threads %X, Loops %X\n", 73962306a36Sopenharmony_ci num_threads, num_loops); 74062306a36Sopenharmony_ci return; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * Create the semaphore for synchronization of 74562306a36Sopenharmony_ci * the created threads with the main thread. 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_ci status = acpi_os_create_semaphore(1, 0, &main_thread_gate); 74862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 74962306a36Sopenharmony_ci acpi_os_printf("Could not create semaphore for " 75062306a36Sopenharmony_ci "synchronization with the main thread, %s\n", 75162306a36Sopenharmony_ci acpi_format_exception(status)); 75262306a36Sopenharmony_ci return; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci /* 75662306a36Sopenharmony_ci * Create the semaphore for synchronization 75762306a36Sopenharmony_ci * between the created threads. 75862306a36Sopenharmony_ci */ 75962306a36Sopenharmony_ci status = acpi_os_create_semaphore(1, 1, &thread_complete_gate); 76062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 76162306a36Sopenharmony_ci acpi_os_printf("Could not create semaphore for " 76262306a36Sopenharmony_ci "synchronization between the created threads, %s\n", 76362306a36Sopenharmony_ci acpi_format_exception(status)); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(main_thread_gate); 76662306a36Sopenharmony_ci return; 76762306a36Sopenharmony_ci } 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci status = acpi_os_create_semaphore(1, 1, &info_gate); 77062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 77162306a36Sopenharmony_ci acpi_os_printf("Could not create semaphore for " 77262306a36Sopenharmony_ci "synchronization of AcpiGbl_DbMethodInfo, %s\n", 77362306a36Sopenharmony_ci acpi_format_exception(status)); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(thread_complete_gate); 77662306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(main_thread_gate); 77762306a36Sopenharmony_ci return; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci /* Array to store IDs of threads */ 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci acpi_gbl_db_method_info.num_threads = num_threads; 78562306a36Sopenharmony_ci size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci acpi_gbl_db_method_info.threads = acpi_os_allocate(size); 78862306a36Sopenharmony_ci if (acpi_gbl_db_method_info.threads == NULL) { 78962306a36Sopenharmony_ci acpi_os_printf("No memory for thread IDs array\n"); 79062306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(main_thread_gate); 79162306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(thread_complete_gate); 79262306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(info_gate); 79362306a36Sopenharmony_ci return; 79462306a36Sopenharmony_ci } 79562306a36Sopenharmony_ci memset(acpi_gbl_db_method_info.threads, 0, size); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci /* Setup the context to be passed to each thread */ 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci acpi_gbl_db_method_info.name = method_name_arg; 80062306a36Sopenharmony_ci acpi_gbl_db_method_info.flags = 0; 80162306a36Sopenharmony_ci acpi_gbl_db_method_info.num_loops = num_loops; 80262306a36Sopenharmony_ci acpi_gbl_db_method_info.main_thread_gate = main_thread_gate; 80362306a36Sopenharmony_ci acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate; 80462306a36Sopenharmony_ci acpi_gbl_db_method_info.info_gate = info_gate; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci /* Init arguments to be passed to method */ 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci acpi_gbl_db_method_info.init_args = 1; 80962306a36Sopenharmony_ci acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments; 81062306a36Sopenharmony_ci acpi_gbl_db_method_info.arguments[0] = 81162306a36Sopenharmony_ci acpi_gbl_db_method_info.num_threads_str; 81262306a36Sopenharmony_ci acpi_gbl_db_method_info.arguments[1] = 81362306a36Sopenharmony_ci acpi_gbl_db_method_info.id_of_thread_str; 81462306a36Sopenharmony_ci acpi_gbl_db_method_info.arguments[2] = 81562306a36Sopenharmony_ci acpi_gbl_db_method_info.index_of_thread_str; 81662306a36Sopenharmony_ci acpi_gbl_db_method_info.arguments[3] = NULL; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types; 81962306a36Sopenharmony_ci acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER; 82062306a36Sopenharmony_ci acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER; 82162306a36Sopenharmony_ci acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci acpi_db_uint32_to_hex_string(num_threads, 82462306a36Sopenharmony_ci acpi_gbl_db_method_info.num_threads_str); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci status = acpi_db_execute_setup(&acpi_gbl_db_method_info); 82762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 82862306a36Sopenharmony_ci goto cleanup_and_exit; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Get the NS node, determines existence also */ 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, 83462306a36Sopenharmony_ci &acpi_gbl_db_method_info.method); 83562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 83662306a36Sopenharmony_ci acpi_os_printf("%s Could not get handle for %s\n", 83762306a36Sopenharmony_ci acpi_format_exception(status), 83862306a36Sopenharmony_ci acpi_gbl_db_method_info.pathname); 83962306a36Sopenharmony_ci goto cleanup_and_exit; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* Create the threads */ 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci acpi_os_printf("Creating %X threads to execute %X times each\n", 84562306a36Sopenharmony_ci num_threads, num_loops); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci for (i = 0; i < (num_threads); i++) { 84862306a36Sopenharmony_ci status = 84962306a36Sopenharmony_ci acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD, 85062306a36Sopenharmony_ci acpi_db_method_thread, 85162306a36Sopenharmony_ci &acpi_gbl_db_method_info); 85262306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 85362306a36Sopenharmony_ci break; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* Wait for all threads to complete */ 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 86262306a36Sopenharmony_ci acpi_os_printf("All threads (%X) have completed\n", num_threads); 86362306a36Sopenharmony_ci acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cicleanup_and_exit: 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* Cleanup and exit */ 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(main_thread_gate); 87062306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(thread_complete_gate); 87162306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(info_gate); 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci acpi_os_free(acpi_gbl_db_method_info.threads); 87462306a36Sopenharmony_ci acpi_gbl_db_method_info.threads = NULL; 87562306a36Sopenharmony_ci} 876