1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: dbexec - debugger control method execution
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun ******************************************************************************/
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "acdebug.h"
11*4882a593Smuzhiyun #include "acnamesp.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #define _COMPONENT ACPI_CA_DEBUGGER
14*4882a593Smuzhiyun ACPI_MODULE_NAME("dbexec")
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun static struct acpi_db_method_info acpi_gbl_db_method_info;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* Local prototypes */
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static acpi_status
21*4882a593Smuzhiyun acpi_db_execute_method(struct acpi_db_method_info *info,
22*4882a593Smuzhiyun struct acpi_buffer *return_obj);
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static u32 acpi_db_get_outstanding_allocations(void);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static acpi_status
31*4882a593Smuzhiyun acpi_db_execution_walk(acpi_handle obj_handle,
32*4882a593Smuzhiyun u32 nesting_level, void *context, void **return_value);
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /*******************************************************************************
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun * FUNCTION: acpi_db_delete_objects
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * PARAMETERS: count - Count of objects in the list
41*4882a593Smuzhiyun * objects - Array of ACPI_OBJECTs to be deleted
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * RETURN: None
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
46*4882a593Smuzhiyun * packages via recursion.
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun ******************************************************************************/
49*4882a593Smuzhiyun
acpi_db_delete_objects(u32 count,union acpi_object * objects)50*4882a593Smuzhiyun void acpi_db_delete_objects(u32 count, union acpi_object *objects)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun u32 i;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun for (i = 0; i < count; i++) {
55*4882a593Smuzhiyun switch (objects[i].type) {
56*4882a593Smuzhiyun case ACPI_TYPE_BUFFER:
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun ACPI_FREE(objects[i].buffer.pointer);
59*4882a593Smuzhiyun break;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun case ACPI_TYPE_PACKAGE:
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /* Recursive call to delete package elements */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun acpi_db_delete_objects(objects[i].package.count,
66*4882a593Smuzhiyun objects[i].package.elements);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* Free the elements array */
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun ACPI_FREE(objects[i].package.elements);
71*4882a593Smuzhiyun break;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun default:
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun break;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /*******************************************************************************
81*4882a593Smuzhiyun *
82*4882a593Smuzhiyun * FUNCTION: acpi_db_execute_method
83*4882a593Smuzhiyun *
84*4882a593Smuzhiyun * PARAMETERS: info - Valid info segment
85*4882a593Smuzhiyun * return_obj - Where to put return object
86*4882a593Smuzhiyun *
87*4882a593Smuzhiyun * RETURN: Status
88*4882a593Smuzhiyun *
89*4882a593Smuzhiyun * DESCRIPTION: Execute a control method. Used to evaluate objects via the
90*4882a593Smuzhiyun * "EXECUTE" or "EVALUATE" commands.
91*4882a593Smuzhiyun *
92*4882a593Smuzhiyun ******************************************************************************/
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun static acpi_status
acpi_db_execute_method(struct acpi_db_method_info * info,struct acpi_buffer * return_obj)95*4882a593Smuzhiyun acpi_db_execute_method(struct acpi_db_method_info *info,
96*4882a593Smuzhiyun struct acpi_buffer *return_obj)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun acpi_status status;
99*4882a593Smuzhiyun struct acpi_object_list param_objects;
100*4882a593Smuzhiyun union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
101*4882a593Smuzhiyun u32 i;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(db_execute_method);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
106*4882a593Smuzhiyun acpi_os_printf("Warning: debug output is not enabled!\n");
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun param_objects.count = 0;
110*4882a593Smuzhiyun param_objects.pointer = NULL;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* Pass through any command-line arguments */
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (info->args && info->args[0]) {
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* Get arguments passed on the command line */
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun for (i = 0; (info->args[i] && *(info->args[i])); i++) {
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Convert input string (token) to an actual union acpi_object */
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun status = acpi_db_convert_to_object(info->types[i],
123*4882a593Smuzhiyun info->args[i],
124*4882a593Smuzhiyun ¶ms[i]);
125*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
126*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
127*4882a593Smuzhiyun "While parsing method arguments"));
128*4882a593Smuzhiyun goto cleanup;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun param_objects.count = i;
133*4882a593Smuzhiyun param_objects.pointer = params;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /* Prepare for a return object of arbitrary size */
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return_obj->pointer = acpi_gbl_db_buffer;
139*4882a593Smuzhiyun return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* Do the actual method execution */
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun acpi_gbl_method_executing = TRUE;
144*4882a593Smuzhiyun status = acpi_evaluate_object(NULL, info->pathname,
145*4882a593Smuzhiyun ¶m_objects, return_obj);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun acpi_gbl_cm_single_step = FALSE;
148*4882a593Smuzhiyun acpi_gbl_method_executing = FALSE;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
151*4882a593Smuzhiyun if ((status == AE_ABORT_METHOD) || acpi_gbl_abort_method) {
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Clear the abort and fall back to the debugger prompt */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
156*4882a593Smuzhiyun "Aborting top-level method"));
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun acpi_gbl_abort_method = FALSE;
159*4882a593Smuzhiyun status = AE_OK;
160*4882a593Smuzhiyun goto cleanup;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
164*4882a593Smuzhiyun "while executing %s from AML Debugger",
165*4882a593Smuzhiyun info->pathname));
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun if (status == AE_BUFFER_OVERFLOW) {
168*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
169*4882a593Smuzhiyun "Possible buffer overflow within AML Debugger "
170*4882a593Smuzhiyun "buffer (size 0x%X needed 0x%X)",
171*4882a593Smuzhiyun ACPI_DEBUG_BUFFER_SIZE,
172*4882a593Smuzhiyun (u32)return_obj->length));
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun cleanup:
177*4882a593Smuzhiyun acpi_db_delete_objects(param_objects.count, params);
178*4882a593Smuzhiyun return_ACPI_STATUS(status);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /*******************************************************************************
182*4882a593Smuzhiyun *
183*4882a593Smuzhiyun * FUNCTION: acpi_db_execute_setup
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * PARAMETERS: info - Valid method info
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * RETURN: None
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * DESCRIPTION: Setup info segment prior to method execution
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun ******************************************************************************/
192*4882a593Smuzhiyun
acpi_db_execute_setup(struct acpi_db_method_info * info)193*4882a593Smuzhiyun static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun acpi_status status;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun ACPI_FUNCTION_NAME(db_execute_setup);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /* Concatenate the current scope to the supplied name */
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun info->pathname[0] = 0;
202*4882a593Smuzhiyun if ((info->name[0] != '\\') && (info->name[0] != '/')) {
203*4882a593Smuzhiyun if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
204*4882a593Smuzhiyun acpi_gbl_db_scope_buf)) {
205*4882a593Smuzhiyun status = AE_BUFFER_OVERFLOW;
206*4882a593Smuzhiyun goto error_exit;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
211*4882a593Smuzhiyun info->name)) {
212*4882a593Smuzhiyun status = AE_BUFFER_OVERFLOW;
213*4882a593Smuzhiyun goto error_exit;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun acpi_db_prep_namestring(info->pathname);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
219*4882a593Smuzhiyun acpi_os_printf("Evaluating %s\n", info->pathname);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun if (info->flags & EX_SINGLE_STEP) {
222*4882a593Smuzhiyun acpi_gbl_cm_single_step = TRUE;
223*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun else {
227*4882a593Smuzhiyun /* No single step, allow redirection to a file */
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return (AE_OK);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun error_exit:
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
237*4882a593Smuzhiyun return (status);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun #ifdef ACPI_DBG_TRACK_ALLOCATIONS
acpi_db_get_cache_info(struct acpi_memory_list * cache)241*4882a593Smuzhiyun u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return (cache->total_allocated - cache->total_freed -
245*4882a593Smuzhiyun cache->current_depth);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun #endif
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /*******************************************************************************
250*4882a593Smuzhiyun *
251*4882a593Smuzhiyun * FUNCTION: acpi_db_get_outstanding_allocations
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * PARAMETERS: None
254*4882a593Smuzhiyun *
255*4882a593Smuzhiyun * RETURN: Current global allocation count minus cache entries
256*4882a593Smuzhiyun *
257*4882a593Smuzhiyun * DESCRIPTION: Determine the current number of "outstanding" allocations --
258*4882a593Smuzhiyun * those allocations that have not been freed and also are not
259*4882a593Smuzhiyun * in one of the various object caches.
260*4882a593Smuzhiyun *
261*4882a593Smuzhiyun ******************************************************************************/
262*4882a593Smuzhiyun
acpi_db_get_outstanding_allocations(void)263*4882a593Smuzhiyun static u32 acpi_db_get_outstanding_allocations(void)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun u32 outstanding = 0;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun #ifdef ACPI_DBG_TRACK_ALLOCATIONS
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
270*4882a593Smuzhiyun outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
271*4882a593Smuzhiyun outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
272*4882a593Smuzhiyun outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
273*4882a593Smuzhiyun #endif
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return (outstanding);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /*******************************************************************************
279*4882a593Smuzhiyun *
280*4882a593Smuzhiyun * FUNCTION: acpi_db_execution_walk
281*4882a593Smuzhiyun *
282*4882a593Smuzhiyun * PARAMETERS: WALK_CALLBACK
283*4882a593Smuzhiyun *
284*4882a593Smuzhiyun * RETURN: Status
285*4882a593Smuzhiyun *
286*4882a593Smuzhiyun * DESCRIPTION: Execute a control method. Name is relative to the current
287*4882a593Smuzhiyun * scope.
288*4882a593Smuzhiyun *
289*4882a593Smuzhiyun ******************************************************************************/
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun static acpi_status
acpi_db_execution_walk(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)292*4882a593Smuzhiyun acpi_db_execution_walk(acpi_handle obj_handle,
293*4882a593Smuzhiyun u32 nesting_level, void *context, void **return_value)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
296*4882a593Smuzhiyun struct acpi_namespace_node *node =
297*4882a593Smuzhiyun (struct acpi_namespace_node *)obj_handle;
298*4882a593Smuzhiyun struct acpi_buffer return_obj;
299*4882a593Smuzhiyun acpi_status status;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun obj_desc = acpi_ns_get_attached_object(node);
302*4882a593Smuzhiyun if (obj_desc->method.param_count) {
303*4882a593Smuzhiyun return (AE_OK);
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return_obj.pointer = NULL;
307*4882a593Smuzhiyun return_obj.length = ACPI_ALLOCATE_BUFFER;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun acpi_ns_print_node_pathname(node, "Evaluating");
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun /* Do the actual method execution */
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun acpi_os_printf("\n");
314*4882a593Smuzhiyun acpi_gbl_method_executing = TRUE;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun acpi_gbl_method_executing = FALSE;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
321*4882a593Smuzhiyun acpi_ut_get_node_name(node),
322*4882a593Smuzhiyun acpi_format_exception(status));
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return (AE_OK);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun /*******************************************************************************
328*4882a593Smuzhiyun *
329*4882a593Smuzhiyun * FUNCTION: acpi_db_execute
330*4882a593Smuzhiyun *
331*4882a593Smuzhiyun * PARAMETERS: name - Name of method to execute
332*4882a593Smuzhiyun * args - Parameters to the method
333*4882a593Smuzhiyun * Types -
334*4882a593Smuzhiyun * flags - single step/no single step
335*4882a593Smuzhiyun *
336*4882a593Smuzhiyun * RETURN: None
337*4882a593Smuzhiyun *
338*4882a593Smuzhiyun * DESCRIPTION: Execute a control method. Name is relative to the current
339*4882a593Smuzhiyun * scope. Function used for the "EXECUTE", "EVALUATE", and
340*4882a593Smuzhiyun * "ALL" commands
341*4882a593Smuzhiyun *
342*4882a593Smuzhiyun ******************************************************************************/
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun void
acpi_db_execute(char * name,char ** args,acpi_object_type * types,u32 flags)345*4882a593Smuzhiyun acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun acpi_status status;
348*4882a593Smuzhiyun struct acpi_buffer return_obj;
349*4882a593Smuzhiyun char *name_string;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun #ifdef ACPI_DEBUG_OUTPUT
352*4882a593Smuzhiyun u32 previous_allocations;
353*4882a593Smuzhiyun u32 allocations;
354*4882a593Smuzhiyun #endif
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * Allow one execution to be performed by debugger or single step
358*4882a593Smuzhiyun * execution will be dead locked by the interpreter mutexes.
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun if (acpi_gbl_method_executing) {
361*4882a593Smuzhiyun acpi_os_printf("Only one debugger execution is allowed.\n");
362*4882a593Smuzhiyun return;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun #ifdef ACPI_DEBUG_OUTPUT
365*4882a593Smuzhiyun /* Memory allocation tracking */
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun previous_allocations = acpi_db_get_outstanding_allocations();
368*4882a593Smuzhiyun #endif
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (*name == '*') {
371*4882a593Smuzhiyun (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
372*4882a593Smuzhiyun ACPI_UINT32_MAX,
373*4882a593Smuzhiyun acpi_db_execution_walk, NULL, NULL,
374*4882a593Smuzhiyun NULL);
375*4882a593Smuzhiyun return;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if ((flags & EX_ALL) && (strlen(name) > 4)) {
379*4882a593Smuzhiyun acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n",
380*4882a593Smuzhiyun name);
381*4882a593Smuzhiyun return;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun name_string = ACPI_ALLOCATE(strlen(name) + 1);
385*4882a593Smuzhiyun if (!name_string) {
386*4882a593Smuzhiyun return;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
390*4882a593Smuzhiyun strcpy(name_string, name);
391*4882a593Smuzhiyun acpi_ut_strupr(name_string);
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* Subcommand to Execute all predefined names in the namespace */
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (!strncmp(name_string, "PREDEF", 6)) {
396*4882a593Smuzhiyun acpi_db_evaluate_predefined_names();
397*4882a593Smuzhiyun ACPI_FREE(name_string);
398*4882a593Smuzhiyun return;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Command (ALL <nameseg>) to execute all methods of a particular name */
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun else if (flags & EX_ALL) {
404*4882a593Smuzhiyun acpi_gbl_db_method_info.name = name_string;
405*4882a593Smuzhiyun return_obj.pointer = NULL;
406*4882a593Smuzhiyun return_obj.length = ACPI_ALLOCATE_BUFFER;
407*4882a593Smuzhiyun acpi_db_evaluate_all(name_string);
408*4882a593Smuzhiyun ACPI_FREE(name_string);
409*4882a593Smuzhiyun return;
410*4882a593Smuzhiyun } else {
411*4882a593Smuzhiyun acpi_gbl_db_method_info.name = name_string;
412*4882a593Smuzhiyun acpi_gbl_db_method_info.args = args;
413*4882a593Smuzhiyun acpi_gbl_db_method_info.types = types;
414*4882a593Smuzhiyun acpi_gbl_db_method_info.flags = flags;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return_obj.pointer = NULL;
417*4882a593Smuzhiyun return_obj.length = ACPI_ALLOCATE_BUFFER;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
421*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
422*4882a593Smuzhiyun ACPI_FREE(name_string);
423*4882a593Smuzhiyun return;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /* Get the NS node, determines existence also */
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
429*4882a593Smuzhiyun &acpi_gbl_db_method_info.method);
430*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
431*4882a593Smuzhiyun status = acpi_db_execute_method(&acpi_gbl_db_method_info,
432*4882a593Smuzhiyun &return_obj);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun ACPI_FREE(name_string);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /*
437*4882a593Smuzhiyun * Allow any handlers in separate threads to complete.
438*4882a593Smuzhiyun * (Such as Notify handlers invoked from AML executed above).
439*4882a593Smuzhiyun */
440*4882a593Smuzhiyun acpi_os_sleep((u64)10);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun #ifdef ACPI_DEBUG_OUTPUT
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun /* Memory allocation tracking */
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun allocations =
447*4882a593Smuzhiyun acpi_db_get_outstanding_allocations() - previous_allocations;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (allocations > 0) {
452*4882a593Smuzhiyun acpi_os_printf
453*4882a593Smuzhiyun ("0x%X Outstanding allocations after evaluation of %s\n",
454*4882a593Smuzhiyun allocations, acpi_gbl_db_method_info.pathname);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun #endif
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
459*4882a593Smuzhiyun acpi_os_printf("Evaluation of %s failed with status %s\n",
460*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname,
461*4882a593Smuzhiyun acpi_format_exception(status));
462*4882a593Smuzhiyun } else {
463*4882a593Smuzhiyun /* Display a return object, if any */
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (return_obj.length) {
466*4882a593Smuzhiyun acpi_os_printf("Evaluation of %s returned object %p, "
467*4882a593Smuzhiyun "external buffer length %X\n",
468*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname,
469*4882a593Smuzhiyun return_obj.pointer,
470*4882a593Smuzhiyun (u32)return_obj.length);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun acpi_db_dump_external_object(return_obj.pointer, 1);
473*4882a593Smuzhiyun acpi_os_printf("\n");
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /* Dump a _PLD buffer if present */
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun if (ACPI_COMPARE_NAMESEG
478*4882a593Smuzhiyun ((ACPI_CAST_PTR
479*4882a593Smuzhiyun (struct acpi_namespace_node,
480*4882a593Smuzhiyun acpi_gbl_db_method_info.method)->name.ascii),
481*4882a593Smuzhiyun METHOD_NAME__PLD)) {
482*4882a593Smuzhiyun acpi_db_dump_pld_buffer(return_obj.pointer);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun } else {
485*4882a593Smuzhiyun acpi_os_printf
486*4882a593Smuzhiyun ("No object was returned from evaluation of %s\n",
487*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /*******************************************************************************
495*4882a593Smuzhiyun *
496*4882a593Smuzhiyun * FUNCTION: acpi_db_method_thread
497*4882a593Smuzhiyun *
498*4882a593Smuzhiyun * PARAMETERS: context - Execution info segment
499*4882a593Smuzhiyun *
500*4882a593Smuzhiyun * RETURN: None
501*4882a593Smuzhiyun *
502*4882a593Smuzhiyun * DESCRIPTION: Debugger execute thread. Waits for a command line, then
503*4882a593Smuzhiyun * simply dispatches it.
504*4882a593Smuzhiyun *
505*4882a593Smuzhiyun ******************************************************************************/
506*4882a593Smuzhiyun
acpi_db_method_thread(void * context)507*4882a593Smuzhiyun static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun acpi_status status;
510*4882a593Smuzhiyun struct acpi_db_method_info *info = context;
511*4882a593Smuzhiyun struct acpi_db_method_info local_info;
512*4882a593Smuzhiyun u32 i;
513*4882a593Smuzhiyun u8 allow;
514*4882a593Smuzhiyun struct acpi_buffer return_obj;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun /*
517*4882a593Smuzhiyun * acpi_gbl_db_method_info.Arguments will be passed as method arguments.
518*4882a593Smuzhiyun * Prevent acpi_gbl_db_method_info from being modified by multiple threads
519*4882a593Smuzhiyun * concurrently.
520*4882a593Smuzhiyun *
521*4882a593Smuzhiyun * Note: The arguments we are passing are used by the ASL test suite
522*4882a593Smuzhiyun * (aslts). Do not change them without updating the tests.
523*4882a593Smuzhiyun */
524*4882a593Smuzhiyun (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (info->init_args) {
527*4882a593Smuzhiyun acpi_db_uint32_to_hex_string(info->num_created,
528*4882a593Smuzhiyun info->index_of_thread_str);
529*4882a593Smuzhiyun acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
530*4882a593Smuzhiyun info->id_of_thread_str);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun if (info->threads && (info->num_created < info->num_threads)) {
534*4882a593Smuzhiyun info->threads[info->num_created++] = acpi_os_get_thread_id();
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun local_info = *info;
538*4882a593Smuzhiyun local_info.args = local_info.arguments;
539*4882a593Smuzhiyun local_info.arguments[0] = local_info.num_threads_str;
540*4882a593Smuzhiyun local_info.arguments[1] = local_info.id_of_thread_str;
541*4882a593Smuzhiyun local_info.arguments[2] = local_info.index_of_thread_str;
542*4882a593Smuzhiyun local_info.arguments[3] = NULL;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun local_info.types = local_info.arg_types;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun (void)acpi_os_signal_semaphore(info->info_gate, 1);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun for (i = 0; i < info->num_loops; i++) {
549*4882a593Smuzhiyun status = acpi_db_execute_method(&local_info, &return_obj);
550*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
551*4882a593Smuzhiyun acpi_os_printf
552*4882a593Smuzhiyun ("%s During evaluation of %s at iteration %X\n",
553*4882a593Smuzhiyun acpi_format_exception(status), info->pathname, i);
554*4882a593Smuzhiyun if (status == AE_ABORT_METHOD) {
555*4882a593Smuzhiyun break;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun #if 0
559*4882a593Smuzhiyun if ((i % 100) == 0) {
560*4882a593Smuzhiyun acpi_os_printf("%u loops, Thread 0x%x\n",
561*4882a593Smuzhiyun i, acpi_os_get_thread_id());
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (return_obj.length) {
565*4882a593Smuzhiyun acpi_os_printf
566*4882a593Smuzhiyun ("Evaluation of %s returned object %p Buflen %X\n",
567*4882a593Smuzhiyun info->pathname, return_obj.pointer,
568*4882a593Smuzhiyun (u32)return_obj.length);
569*4882a593Smuzhiyun acpi_db_dump_external_object(return_obj.pointer, 1);
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun #endif
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun /* Signal our completion */
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun allow = 0;
577*4882a593Smuzhiyun (void)acpi_os_wait_semaphore(info->thread_complete_gate,
578*4882a593Smuzhiyun 1, ACPI_WAIT_FOREVER);
579*4882a593Smuzhiyun info->num_completed++;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun if (info->num_completed == info->num_threads) {
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /* Do signal for main thread once only */
584*4882a593Smuzhiyun allow = 1;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun if (allow) {
590*4882a593Smuzhiyun status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
591*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
592*4882a593Smuzhiyun acpi_os_printf
593*4882a593Smuzhiyun ("Could not signal debugger thread sync semaphore, %s\n",
594*4882a593Smuzhiyun acpi_format_exception(status));
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun /*******************************************************************************
600*4882a593Smuzhiyun *
601*4882a593Smuzhiyun * FUNCTION: acpi_db_single_execution_thread
602*4882a593Smuzhiyun *
603*4882a593Smuzhiyun * PARAMETERS: context - Method info struct
604*4882a593Smuzhiyun *
605*4882a593Smuzhiyun * RETURN: None
606*4882a593Smuzhiyun *
607*4882a593Smuzhiyun * DESCRIPTION: Create one thread and execute a method
608*4882a593Smuzhiyun *
609*4882a593Smuzhiyun ******************************************************************************/
610*4882a593Smuzhiyun
acpi_db_single_execution_thread(void * context)611*4882a593Smuzhiyun static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun struct acpi_db_method_info *info = context;
614*4882a593Smuzhiyun acpi_status status;
615*4882a593Smuzhiyun struct acpi_buffer return_obj;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun acpi_os_printf("\n");
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun status = acpi_db_execute_method(info, &return_obj);
620*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
621*4882a593Smuzhiyun acpi_os_printf("%s During evaluation of %s\n",
622*4882a593Smuzhiyun acpi_format_exception(status), info->pathname);
623*4882a593Smuzhiyun return;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /* Display a return object, if any */
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (return_obj.length) {
629*4882a593Smuzhiyun acpi_os_printf("Evaluation of %s returned object %p, "
630*4882a593Smuzhiyun "external buffer length %X\n",
631*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname,
632*4882a593Smuzhiyun return_obj.pointer, (u32)return_obj.length);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun acpi_db_dump_external_object(return_obj.pointer, 1);
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun acpi_os_printf("\nBackground thread completed\n%c ",
638*4882a593Smuzhiyun ACPI_DEBUGGER_COMMAND_PROMPT);
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun /*******************************************************************************
642*4882a593Smuzhiyun *
643*4882a593Smuzhiyun * FUNCTION: acpi_db_create_execution_thread
644*4882a593Smuzhiyun *
645*4882a593Smuzhiyun * PARAMETERS: method_name_arg - Control method to execute
646*4882a593Smuzhiyun * arguments - Array of arguments to the method
647*4882a593Smuzhiyun * types - Corresponding array of object types
648*4882a593Smuzhiyun *
649*4882a593Smuzhiyun * RETURN: None
650*4882a593Smuzhiyun *
651*4882a593Smuzhiyun * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles
652*4882a593Smuzhiyun * arguments passed on command line for control methods.
653*4882a593Smuzhiyun *
654*4882a593Smuzhiyun ******************************************************************************/
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun void
acpi_db_create_execution_thread(char * method_name_arg,char ** arguments,acpi_object_type * types)657*4882a593Smuzhiyun acpi_db_create_execution_thread(char *method_name_arg,
658*4882a593Smuzhiyun char **arguments, acpi_object_type *types)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun acpi_status status;
661*4882a593Smuzhiyun u32 i;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
664*4882a593Smuzhiyun acpi_gbl_db_method_info.name = method_name_arg;
665*4882a593Smuzhiyun acpi_gbl_db_method_info.init_args = 1;
666*4882a593Smuzhiyun acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
667*4882a593Smuzhiyun acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* Setup method arguments, up to 7 (0-6) */
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) {
672*4882a593Smuzhiyun acpi_gbl_db_method_info.arguments[i] = *arguments;
673*4882a593Smuzhiyun arguments++;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun acpi_gbl_db_method_info.arg_types[i] = *types;
676*4882a593Smuzhiyun types++;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
680*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
681*4882a593Smuzhiyun return;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /* Get the NS node, determines existence also */
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
687*4882a593Smuzhiyun &acpi_gbl_db_method_info.method);
688*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
689*4882a593Smuzhiyun acpi_os_printf("%s Could not get handle for %s\n",
690*4882a593Smuzhiyun acpi_format_exception(status),
691*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname);
692*4882a593Smuzhiyun return;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
696*4882a593Smuzhiyun acpi_db_single_execution_thread,
697*4882a593Smuzhiyun &acpi_gbl_db_method_info);
698*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
699*4882a593Smuzhiyun return;
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun acpi_os_printf("\nBackground thread started\n");
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /*******************************************************************************
706*4882a593Smuzhiyun *
707*4882a593Smuzhiyun * FUNCTION: acpi_db_create_execution_threads
708*4882a593Smuzhiyun *
709*4882a593Smuzhiyun * PARAMETERS: num_threads_arg - Number of threads to create
710*4882a593Smuzhiyun * num_loops_arg - Loop count for the thread(s)
711*4882a593Smuzhiyun * method_name_arg - Control method to execute
712*4882a593Smuzhiyun *
713*4882a593Smuzhiyun * RETURN: None
714*4882a593Smuzhiyun *
715*4882a593Smuzhiyun * DESCRIPTION: Create threads to execute method(s)
716*4882a593Smuzhiyun *
717*4882a593Smuzhiyun ******************************************************************************/
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun void
acpi_db_create_execution_threads(char * num_threads_arg,char * num_loops_arg,char * method_name_arg)720*4882a593Smuzhiyun acpi_db_create_execution_threads(char *num_threads_arg,
721*4882a593Smuzhiyun char *num_loops_arg, char *method_name_arg)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun acpi_status status;
724*4882a593Smuzhiyun u32 num_threads;
725*4882a593Smuzhiyun u32 num_loops;
726*4882a593Smuzhiyun u32 i;
727*4882a593Smuzhiyun u32 size;
728*4882a593Smuzhiyun acpi_mutex main_thread_gate;
729*4882a593Smuzhiyun acpi_mutex thread_complete_gate;
730*4882a593Smuzhiyun acpi_mutex info_gate;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun /* Get the arguments */
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun num_threads = strtoul(num_threads_arg, NULL, 0);
735*4882a593Smuzhiyun num_loops = strtoul(num_loops_arg, NULL, 0);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun if (!num_threads || !num_loops) {
738*4882a593Smuzhiyun acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
739*4882a593Smuzhiyun num_threads, num_loops);
740*4882a593Smuzhiyun return;
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun /*
744*4882a593Smuzhiyun * Create the semaphore for synchronization of
745*4882a593Smuzhiyun * the created threads with the main thread.
746*4882a593Smuzhiyun */
747*4882a593Smuzhiyun status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
748*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
749*4882a593Smuzhiyun acpi_os_printf("Could not create semaphore for "
750*4882a593Smuzhiyun "synchronization with the main thread, %s\n",
751*4882a593Smuzhiyun acpi_format_exception(status));
752*4882a593Smuzhiyun return;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun /*
756*4882a593Smuzhiyun * Create the semaphore for synchronization
757*4882a593Smuzhiyun * between the created threads.
758*4882a593Smuzhiyun */
759*4882a593Smuzhiyun status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
760*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
761*4882a593Smuzhiyun acpi_os_printf("Could not create semaphore for "
762*4882a593Smuzhiyun "synchronization between the created threads, %s\n",
763*4882a593Smuzhiyun acpi_format_exception(status));
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(main_thread_gate);
766*4882a593Smuzhiyun return;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun status = acpi_os_create_semaphore(1, 1, &info_gate);
770*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
771*4882a593Smuzhiyun acpi_os_printf("Could not create semaphore for "
772*4882a593Smuzhiyun "synchronization of AcpiGbl_DbMethodInfo, %s\n",
773*4882a593Smuzhiyun acpi_format_exception(status));
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(thread_complete_gate);
776*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(main_thread_gate);
777*4882a593Smuzhiyun return;
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun /* Array to store IDs of threads */
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun acpi_gbl_db_method_info.num_threads = num_threads;
785*4882a593Smuzhiyun size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
788*4882a593Smuzhiyun if (acpi_gbl_db_method_info.threads == NULL) {
789*4882a593Smuzhiyun acpi_os_printf("No memory for thread IDs array\n");
790*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(main_thread_gate);
791*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(thread_complete_gate);
792*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(info_gate);
793*4882a593Smuzhiyun return;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun memset(acpi_gbl_db_method_info.threads, 0, size);
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /* Setup the context to be passed to each thread */
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun acpi_gbl_db_method_info.name = method_name_arg;
800*4882a593Smuzhiyun acpi_gbl_db_method_info.flags = 0;
801*4882a593Smuzhiyun acpi_gbl_db_method_info.num_loops = num_loops;
802*4882a593Smuzhiyun acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
803*4882a593Smuzhiyun acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
804*4882a593Smuzhiyun acpi_gbl_db_method_info.info_gate = info_gate;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun /* Init arguments to be passed to method */
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun acpi_gbl_db_method_info.init_args = 1;
809*4882a593Smuzhiyun acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
810*4882a593Smuzhiyun acpi_gbl_db_method_info.arguments[0] =
811*4882a593Smuzhiyun acpi_gbl_db_method_info.num_threads_str;
812*4882a593Smuzhiyun acpi_gbl_db_method_info.arguments[1] =
813*4882a593Smuzhiyun acpi_gbl_db_method_info.id_of_thread_str;
814*4882a593Smuzhiyun acpi_gbl_db_method_info.arguments[2] =
815*4882a593Smuzhiyun acpi_gbl_db_method_info.index_of_thread_str;
816*4882a593Smuzhiyun acpi_gbl_db_method_info.arguments[3] = NULL;
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
819*4882a593Smuzhiyun acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
820*4882a593Smuzhiyun acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
821*4882a593Smuzhiyun acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun acpi_db_uint32_to_hex_string(num_threads,
824*4882a593Smuzhiyun acpi_gbl_db_method_info.num_threads_str);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
827*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
828*4882a593Smuzhiyun goto cleanup_and_exit;
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun /* Get the NS node, determines existence also */
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
834*4882a593Smuzhiyun &acpi_gbl_db_method_info.method);
835*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
836*4882a593Smuzhiyun acpi_os_printf("%s Could not get handle for %s\n",
837*4882a593Smuzhiyun acpi_format_exception(status),
838*4882a593Smuzhiyun acpi_gbl_db_method_info.pathname);
839*4882a593Smuzhiyun goto cleanup_and_exit;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun /* Create the threads */
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun acpi_os_printf("Creating %X threads to execute %X times each\n",
845*4882a593Smuzhiyun num_threads, num_loops);
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun for (i = 0; i < (num_threads); i++) {
848*4882a593Smuzhiyun status =
849*4882a593Smuzhiyun acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
850*4882a593Smuzhiyun acpi_db_method_thread,
851*4882a593Smuzhiyun &acpi_gbl_db_method_info);
852*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
853*4882a593Smuzhiyun break;
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun /* Wait for all threads to complete */
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
862*4882a593Smuzhiyun acpi_os_printf("All threads (%X) have completed\n", num_threads);
863*4882a593Smuzhiyun acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun cleanup_and_exit:
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun /* Cleanup and exit */
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(main_thread_gate);
870*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(thread_complete_gate);
871*4882a593Smuzhiyun (void)acpi_os_delete_semaphore(info_gate);
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun acpi_os_free(acpi_gbl_db_method_info.threads);
874*4882a593Smuzhiyun acpi_gbl_db_method_info.threads = NULL;
875*4882a593Smuzhiyun }
876