diff options
author | Valery Podrezov <valery.a.podrezov@intel.com> | 2007-02-02 11:48:21 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:27 -0500 |
commit | 9bc75cff4919f9d947982d805aed89582a20d04d (patch) | |
tree | d07b8eb59b0dd6384f8fc5694113759ef7b8668e | |
parent | 4d0b4af958453afe871022e44abd57fac09baf67 (diff) |
ACPICA: Eliminate control method 2-pass parse/execute.
Completed an AML interpreter performance enhancement for control method
execution. Previously a 2-pass parse/execution, control methods are now
completely parsed and executed in single pass. This improves overall
interpreter performance by ~25%, reduces code size, and reduces CPU stack use.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 50 | ||||
-rw-r--r-- | drivers/acpi/parser/psloop.c | 2 | ||||
-rw-r--r-- | drivers/acpi/parser/psxface.c | 114 |
3 files changed, 42 insertions, 124 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index cf888add3191..aa60dca1f8aa 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -327,7 +327,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
327 | ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); | 327 | ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); |
328 | 328 | ||
329 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 329 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
330 | "Execute method %p, currentstate=%p\n", | 330 | "Calling method %p, currentstate=%p\n", |
331 | this_walk_state->prev_op, this_walk_state)); | 331 | this_walk_state->prev_op, this_walk_state)); |
332 | 332 | ||
333 | /* | 333 | /* |
@@ -351,49 +351,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
351 | return_ACPI_STATUS(status); | 351 | return_ACPI_STATUS(status); |
352 | } | 352 | } |
353 | 353 | ||
354 | /* | 354 | /* Begin method parse/execution. Create a new walk state */ |
355 | * 1) Parse the method. All "normal" methods are parsed for each execution. | ||
356 | * Internal methods (_OSI, etc.) do not require parsing. | ||
357 | */ | ||
358 | if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { | ||
359 | |||
360 | /* Create a new walk state for the parse */ | ||
361 | |||
362 | next_walk_state = | ||
363 | acpi_ds_create_walk_state(obj_desc->method.owner_id, op, | ||
364 | obj_desc, NULL); | ||
365 | if (!next_walk_state) { | ||
366 | status = AE_NO_MEMORY; | ||
367 | goto cleanup; | ||
368 | } | ||
369 | |||
370 | /* Create and init a parse tree root */ | ||
371 | |||
372 | op = acpi_ps_create_scope_op(); | ||
373 | if (!op) { | ||
374 | status = AE_NO_MEMORY; | ||
375 | goto cleanup; | ||
376 | } | ||
377 | |||
378 | status = acpi_ds_init_aml_walk(next_walk_state, op, method_node, | ||
379 | obj_desc->method.aml_start, | ||
380 | obj_desc->method.aml_length, | ||
381 | NULL, 1); | ||
382 | if (ACPI_FAILURE(status)) { | ||
383 | acpi_ps_delete_parse_tree(op); | ||
384 | goto cleanup; | ||
385 | } | ||
386 | |||
387 | /* Begin AML parse (deletes next_walk_state) */ | ||
388 | |||
389 | status = acpi_ps_parse_aml(next_walk_state); | ||
390 | acpi_ps_delete_parse_tree(op); | ||
391 | if (ACPI_FAILURE(status)) { | ||
392 | goto cleanup; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /* 2) Begin method execution. Create a new walk state */ | ||
397 | 355 | ||
398 | next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, | 356 | next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, |
399 | NULL, obj_desc, thread); | 357 | NULL, obj_desc, thread); |
@@ -445,8 +403,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
445 | this_walk_state->num_operands = 0; | 403 | this_walk_state->num_operands = 0; |
446 | 404 | ||
447 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 405 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
448 | "Starting nested execution, newstate=%p\n", | 406 | "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", |
449 | next_walk_state)); | 407 | method_node->name.ascii, next_walk_state)); |
450 | 408 | ||
451 | /* Invoke an internal method if necessary */ | 409 | /* Invoke an internal method if necessary */ |
452 | 410 | ||
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index a83be5201856..881687ca3154 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c | |||
@@ -226,7 +226,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, | |||
226 | return_ACPI_STATUS(status); | 226 | return_ACPI_STATUS(status); |
227 | } | 227 | } |
228 | 228 | ||
229 | if (!op) { | 229 | if (!*op) { |
230 | return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); | 230 | return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); |
231 | } | 231 | } |
232 | 232 | ||
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 5d996c1140af..9069c697cf1d 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c | |||
@@ -54,8 +54,6 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info); | |||
54 | 54 | ||
55 | static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); | 55 | static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); |
56 | 56 | ||
57 | static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info); | ||
58 | |||
59 | static void | 57 | static void |
60 | acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); | 58 | acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); |
61 | 59 | ||
@@ -215,6 +213,8 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) | |||
215 | acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) | 213 | acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) |
216 | { | 214 | { |
217 | acpi_status status; | 215 | acpi_status status; |
216 | union acpi_parse_object *op; | ||
217 | struct acpi_walk_state *walk_state; | ||
218 | 218 | ||
219 | ACPI_FUNCTION_TRACE(ps_execute_method); | 219 | ACPI_FUNCTION_TRACE(ps_execute_method); |
220 | 220 | ||
@@ -234,8 +234,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) | |||
234 | } | 234 | } |
235 | 235 | ||
236 | /* | 236 | /* |
237 | * The caller "owns" the parameters, so give each one an extra | 237 | * The caller "owns" the parameters, so give each one an extra reference |
238 | * reference | ||
239 | */ | 238 | */ |
240 | acpi_ps_update_parameter_list(info, REF_INCREMENT); | 239 | acpi_ps_update_parameter_list(info, REF_INCREMENT); |
241 | 240 | ||
@@ -244,30 +243,50 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) | |||
244 | acpi_ps_start_trace(info); | 243 | acpi_ps_start_trace(info); |
245 | 244 | ||
246 | /* | 245 | /* |
247 | * 1) Perform the first pass parse of the method to enter any | 246 | * Execute the method. Performs parse simultaneously |
248 | * named objects that it creates into the namespace | ||
249 | */ | 247 | */ |
250 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | 248 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
251 | "**** Begin Method Parse **** Entry=%p obj=%p\n", | 249 | "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", |
252 | info->resolved_node, info->obj_desc)); | 250 | info->resolved_node->name.ascii, info->resolved_node, |
251 | info->obj_desc)); | ||
253 | 252 | ||
254 | info->pass_number = 1; | 253 | /* Create and init a Root Node */ |
255 | status = acpi_ps_execute_pass(info); | 254 | |
256 | if (ACPI_FAILURE(status)) { | 255 | op = acpi_ps_create_scope_op(); |
256 | if (!op) { | ||
257 | status = AE_NO_MEMORY; | ||
257 | goto cleanup; | 258 | goto cleanup; |
258 | } | 259 | } |
259 | 260 | ||
260 | /* | 261 | /* Create and initialize a new walk state */ |
261 | * 2) Execute the method. Performs second pass parse simultaneously | ||
262 | */ | ||
263 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
264 | "**** Begin Method Execution **** Entry=%p obj=%p\n", | ||
265 | info->resolved_node, info->obj_desc)); | ||
266 | 262 | ||
267 | info->pass_number = 3; | 263 | info->pass_number = 3; |
268 | status = acpi_ps_execute_pass(info); | 264 | walk_state = |
265 | acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, | ||
266 | NULL, NULL); | ||
267 | if (!walk_state) { | ||
268 | status = AE_NO_MEMORY; | ||
269 | goto cleanup; | ||
270 | } | ||
271 | |||
272 | status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, | ||
273 | info->obj_desc->method.aml_start, | ||
274 | info->obj_desc->method.aml_length, info, | ||
275 | info->pass_number); | ||
276 | if (ACPI_FAILURE(status)) { | ||
277 | acpi_ds_delete_walk_state(walk_state); | ||
278 | goto cleanup; | ||
279 | } | ||
280 | |||
281 | /* Parse the AML */ | ||
282 | |||
283 | status = acpi_ps_parse_aml(walk_state); | ||
284 | |||
285 | /* walk_state was deleted by parse_aml */ | ||
269 | 286 | ||
270 | cleanup: | 287 | cleanup: |
288 | acpi_ps_delete_parse_tree(op); | ||
289 | |||
271 | /* End optional tracing */ | 290 | /* End optional tracing */ |
272 | 291 | ||
273 | acpi_ps_stop_trace(info); | 292 | acpi_ps_stop_trace(info); |
@@ -330,62 +349,3 @@ acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) | |||
330 | } | 349 | } |
331 | } | 350 | } |
332 | } | 351 | } |
333 | |||
334 | /******************************************************************************* | ||
335 | * | ||
336 | * FUNCTION: acpi_ps_execute_pass | ||
337 | * | ||
338 | * PARAMETERS: Info - See struct acpi_evaluate_info | ||
339 | * (Used: pass_number, Node, and obj_desc) | ||
340 | * | ||
341 | * RETURN: Status | ||
342 | * | ||
343 | * DESCRIPTION: Single AML pass: Parse or Execute a control method | ||
344 | * | ||
345 | ******************************************************************************/ | ||
346 | |||
347 | static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info) | ||
348 | { | ||
349 | acpi_status status; | ||
350 | union acpi_parse_object *op; | ||
351 | struct acpi_walk_state *walk_state; | ||
352 | |||
353 | ACPI_FUNCTION_TRACE(ps_execute_pass); | ||
354 | |||
355 | /* Create and init a Root Node */ | ||
356 | |||
357 | op = acpi_ps_create_scope_op(); | ||
358 | if (!op) { | ||
359 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
360 | } | ||
361 | |||
362 | /* Create and initialize a new walk state */ | ||
363 | |||
364 | walk_state = | ||
365 | acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, | ||
366 | NULL, NULL); | ||
367 | if (!walk_state) { | ||
368 | status = AE_NO_MEMORY; | ||
369 | goto cleanup; | ||
370 | } | ||
371 | |||
372 | status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, | ||
373 | info->obj_desc->method.aml_start, | ||
374 | info->obj_desc->method.aml_length, | ||
375 | info->pass_number == 1 ? NULL : info, | ||
376 | info->pass_number); | ||
377 | if (ACPI_FAILURE(status)) { | ||
378 | acpi_ds_delete_walk_state(walk_state); | ||
379 | goto cleanup; | ||
380 | } | ||
381 | |||
382 | /* Parse the AML */ | ||
383 | |||
384 | status = acpi_ps_parse_aml(walk_state); | ||
385 | |||
386 | /* Walk state was deleted by parse_aml */ | ||
387 | |||
388 | cleanup: | ||
389 | acpi_ps_delete_parse_tree(op); | ||
390 | return_ACPI_STATUS(status); | ||
391 | } | ||