1 /******************************************************************************
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define _COMPONENT ACPI_DISPATCHER
30 MODULE_NAME ("dswstate")
33 /*******************************************************************************
35 * FUNCTION: Acpi_ds_result_insert
37 * PARAMETERS: Object - Object to push
38 * Walk_state - Current Walk state
42 * DESCRIPTION: Push an object onto this walk's result stack
44 ******************************************************************************/
47 acpi_ds_result_insert (
50 ACPI_WALK_STATE
*walk_state
)
52 ACPI_GENERIC_STATE
*state
;
55 state
= walk_state
->results
;
57 return (AE_NOT_EXIST
);
60 if (index
>= OBJ_NUM_OPERANDS
) {
61 return (AE_BAD_PARAMETER
);
65 return (AE_BAD_PARAMETER
);
68 state
->results
.obj_desc
[index
] = object
;
69 state
->results
.num_results
++;
75 /*******************************************************************************
77 * FUNCTION: Acpi_ds_result_remove
79 * PARAMETERS: Object - Where to return the popped object
80 * Walk_state - Current Walk state
84 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
85 * other words, this is a FIFO.
87 ******************************************************************************/
90 acpi_ds_result_remove (
91 ACPI_OPERAND_OBJECT
**object
,
93 ACPI_WALK_STATE
*walk_state
)
95 ACPI_GENERIC_STATE
*state
;
98 state
= walk_state
->results
;
100 return (AE_NOT_EXIST
);
105 /* Check for a valid result object */
107 if (!state
->results
.obj_desc
[index
]) {
108 return (AE_AML_NO_RETURN_VALUE
);
111 /* Remove the object */
113 state
->results
.num_results
--;
115 *object
= state
->results
.obj_desc
[index
];
116 state
->results
.obj_desc
[index
] = NULL
;
122 /*******************************************************************************
124 * FUNCTION: Acpi_ds_result_pop
126 * PARAMETERS: Object - Where to return the popped object
127 * Walk_state - Current Walk state
131 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
132 * other words, this is a FIFO.
134 ******************************************************************************/
138 ACPI_OPERAND_OBJECT
**object
,
139 ACPI_WALK_STATE
*walk_state
)
142 ACPI_GENERIC_STATE
*state
;
145 state
= walk_state
->results
;
151 if (!state
->results
.num_results
) {
152 return (AE_AML_NO_RETURN_VALUE
);
155 /* Remove top element */
157 state
->results
.num_results
--;
159 for (index
= OBJ_NUM_OPERANDS
; index
; index
--) {
160 /* Check for a valid result object */
162 if (state
->results
.obj_desc
[index
-1]) {
163 *object
= state
->results
.obj_desc
[index
-1];
164 state
->results
.obj_desc
[index
-1] = NULL
;
171 return (AE_AML_NO_RETURN_VALUE
);
174 /*******************************************************************************
176 * FUNCTION: Acpi_ds_result_pop_from_bottom
178 * PARAMETERS: Object - Where to return the popped object
179 * Walk_state - Current Walk state
183 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
184 * other words, this is a FIFO.
186 ******************************************************************************/
189 acpi_ds_result_pop_from_bottom (
190 ACPI_OPERAND_OBJECT
**object
,
191 ACPI_WALK_STATE
*walk_state
)
194 ACPI_GENERIC_STATE
*state
;
197 state
= walk_state
->results
;
199 return (AE_NOT_EXIST
);
203 if (!state
->results
.num_results
) {
204 return (AE_AML_NO_RETURN_VALUE
);
207 /* Remove Bottom element */
209 *object
= state
->results
.obj_desc
[0];
212 /* Push entire stack down one element */
214 for (index
= 0; index
< state
->results
.num_results
; index
++) {
215 state
->results
.obj_desc
[index
] = state
->results
.obj_desc
[index
+ 1];
218 state
->results
.num_results
--;
220 /* Check for a valid result object */
223 return (AE_AML_NO_RETURN_VALUE
);
231 /*******************************************************************************
233 * FUNCTION: Acpi_ds_result_push
235 * PARAMETERS: Object - Where to return the popped object
236 * Walk_state - Current Walk state
240 * DESCRIPTION: Push an object onto the current result stack
242 ******************************************************************************/
245 acpi_ds_result_push (
246 ACPI_OPERAND_OBJECT
*object
,
247 ACPI_WALK_STATE
*walk_state
)
249 ACPI_GENERIC_STATE
*state
;
252 state
= walk_state
->results
;
254 return (AE_AML_INTERNAL
);
257 if (state
->results
.num_results
== OBJ_NUM_OPERANDS
) {
258 return (AE_STACK_OVERFLOW
);
262 return (AE_BAD_PARAMETER
);
266 state
->results
.obj_desc
[state
->results
.num_results
] = object
;
267 state
->results
.num_results
++;
273 /*******************************************************************************
275 * FUNCTION: Acpi_ds_result_stack_push
277 * PARAMETERS: Object - Object to push
278 * Walk_state - Current Walk state
284 ******************************************************************************/
287 acpi_ds_result_stack_push (
288 ACPI_WALK_STATE
*walk_state
)
290 ACPI_GENERIC_STATE
*state
;
293 state
= acpi_cm_create_generic_state ();
295 return (AE_NO_MEMORY
);
298 acpi_cm_push_generic_state (&walk_state
->results
, state
);
304 /*******************************************************************************
306 * FUNCTION: Acpi_ds_result_stack_pop
308 * PARAMETERS: Walk_state - Current Walk state
314 ******************************************************************************/
317 acpi_ds_result_stack_pop (
318 ACPI_WALK_STATE
*walk_state
)
320 ACPI_GENERIC_STATE
*state
;
323 /* Check for stack underflow */
325 if (walk_state
->results
== NULL
) {
326 return (AE_AML_NO_OPERAND
);
330 state
= acpi_cm_pop_generic_state (&walk_state
->results
);
332 acpi_cm_delete_generic_state (state
);
338 /*******************************************************************************
340 * FUNCTION: Acpi_ds_obj_stack_delete_all
342 * PARAMETERS: Walk_state - Current Walk state
346 * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
347 * Should be used with great care, if at all!
349 ******************************************************************************/
352 acpi_ds_obj_stack_delete_all (
353 ACPI_WALK_STATE
*walk_state
)
358 /* The stack size is configurable, but fixed */
360 for (i
= 0; i
< OBJ_NUM_OPERANDS
; i
++) {
361 if (walk_state
->operands
[i
]) {
362 acpi_cm_remove_reference (walk_state
->operands
[i
]);
363 walk_state
->operands
[i
] = NULL
;
371 /*******************************************************************************
373 * FUNCTION: Acpi_ds_obj_stack_push
375 * PARAMETERS: Object - Object to push
376 * Walk_state - Current Walk state
380 * DESCRIPTION: Push an object onto this walk's object/operand stack
382 ******************************************************************************/
385 acpi_ds_obj_stack_push (
387 ACPI_WALK_STATE
*walk_state
)
391 /* Check for stack overflow */
393 if (walk_state
->num_operands
>= OBJ_NUM_OPERANDS
) {
394 return (AE_STACK_OVERFLOW
);
397 /* Put the object onto the stack */
399 walk_state
->operands
[walk_state
->num_operands
] = object
;
400 walk_state
->num_operands
++;
406 /*******************************************************************************
408 * FUNCTION: Acpi_ds_obj_stack_pop_object
410 * PARAMETERS: Pop_count - Number of objects/entries to pop
411 * Walk_state - Current Walk state
415 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
416 * deleted by this routine.
418 ******************************************************************************/
421 acpi_ds_obj_stack_pop_object (
422 ACPI_OPERAND_OBJECT
**object
,
423 ACPI_WALK_STATE
*walk_state
)
427 /* Check for stack underflow */
429 if (walk_state
->num_operands
== 0) {
430 return (AE_AML_NO_OPERAND
);
436 walk_state
->num_operands
--;
438 /* Check for a valid operand */
440 if (!walk_state
->operands
[walk_state
->num_operands
]) {
441 return (AE_AML_NO_OPERAND
);
444 /* Get operand and set stack entry to null */
446 *object
= walk_state
->operands
[walk_state
->num_operands
];
447 walk_state
->operands
[walk_state
->num_operands
] = NULL
;
453 /*******************************************************************************
455 * FUNCTION: Acpi_ds_obj_stack_pop
457 * PARAMETERS: Pop_count - Number of objects/entries to pop
458 * Walk_state - Current Walk state
462 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
463 * deleted by this routine.
465 ******************************************************************************/
468 acpi_ds_obj_stack_pop (
470 ACPI_WALK_STATE
*walk_state
)
475 for (i
= 0; i
< pop_count
; i
++) {
476 /* Check for stack underflow */
478 if (walk_state
->num_operands
== 0) {
479 return (AE_STACK_UNDERFLOW
);
482 /* Just set the stack entry to null */
484 walk_state
->num_operands
--;
485 walk_state
->operands
[walk_state
->num_operands
] = NULL
;
492 /*******************************************************************************
494 * FUNCTION: Acpi_ds_obj_stack_pop_and_delete
496 * PARAMETERS: Pop_count - Number of objects/entries to pop
497 * Walk_state - Current Walk state
501 * DESCRIPTION: Pop this walk's object stack and delete each object that is
504 ******************************************************************************/
507 acpi_ds_obj_stack_pop_and_delete (
509 ACPI_WALK_STATE
*walk_state
)
512 ACPI_OPERAND_OBJECT
*obj_desc
;
515 for (i
= 0; i
< pop_count
; i
++) {
516 /* Check for stack underflow */
518 if (walk_state
->num_operands
== 0) {
519 return (AE_STACK_UNDERFLOW
);
522 /* Pop the stack and delete an object if present in this stack entry */
524 walk_state
->num_operands
--;
525 obj_desc
= walk_state
->operands
[walk_state
->num_operands
];
527 acpi_cm_remove_reference (walk_state
->operands
[walk_state
->num_operands
]);
528 walk_state
->operands
[walk_state
->num_operands
] = NULL
;
536 /*******************************************************************************
538 * FUNCTION: Acpi_ds_obj_stack_get_value
540 * PARAMETERS: Index - Stack index whose value is desired. Based
541 * on the top of the stack (index=0 == top)
542 * Walk_state - Current Walk state
546 * DESCRIPTION: Retrieve an object from this walk's object stack. Index must
547 * be within the range of the current stack pointer.
549 ******************************************************************************/
552 acpi_ds_obj_stack_get_value (
554 ACPI_WALK_STATE
*walk_state
)
558 /* Can't do it if the stack is empty */
560 if (walk_state
->num_operands
== 0) {
564 /* or if the index is past the top of the stack */
566 if (index
> (walk_state
->num_operands
- (u32
) 1)) {
571 return (walk_state
->operands
[(NATIVE_UINT
)(walk_state
->num_operands
- 1) -
576 /*******************************************************************************
578 * FUNCTION: Acpi_ds_get_current_walk_state
580 * PARAMETERS: Walk_list - Get current active state for this walk list
582 * RETURN: Pointer to the current walk state
584 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
587 ******************************************************************************/
590 acpi_ds_get_current_walk_state (
591 ACPI_WALK_LIST
*walk_list
)
599 return (walk_list
->walk_state
);
603 /*******************************************************************************
605 * FUNCTION: Acpi_ds_push_walk_state
607 * PARAMETERS: Walk_state - State to push
608 * Walk_list - The list that owns the walk stack
612 * DESCRIPTION: Place the Walk_state at the head of the state list.
614 ******************************************************************************/
617 acpi_ds_push_walk_state (
618 ACPI_WALK_STATE
*walk_state
,
619 ACPI_WALK_LIST
*walk_list
)
623 walk_state
->next
= walk_list
->walk_state
;
624 walk_list
->walk_state
= walk_state
;
630 /*******************************************************************************
632 * FUNCTION: Acpi_ds_pop_walk_state
634 * PARAMETERS: Walk_list - The list that owns the walk stack
636 * RETURN: A Walk_state object popped from the stack
638 * DESCRIPTION: Remove and return the walkstate object that is at the head of
639 * the walk stack for the given walk list. NULL indicates that
642 ******************************************************************************/
645 acpi_ds_pop_walk_state (
646 ACPI_WALK_LIST
*walk_list
)
648 ACPI_WALK_STATE
*walk_state
;
651 walk_state
= walk_list
->walk_state
;
654 /* Next walk state becomes the current walk state */
656 walk_list
->walk_state
= walk_state
->next
;
659 * Don't clear the NEXT field, this serves as an indicator
660 * that there is a parent WALK STATE
661 * Walk_state->Next = NULL;
669 /*******************************************************************************
671 * FUNCTION: Acpi_ds_create_walk_state
673 * PARAMETERS: Origin - Starting point for this walk
674 * Walk_list - Owning walk list
676 * RETURN: Pointer to the new walk state.
678 * DESCRIPTION: Allocate and initialize a new walk state. The current walk state
679 * is set to this new state.
681 ******************************************************************************/
684 acpi_ds_create_walk_state (
685 ACPI_OWNER_ID owner_id
,
686 ACPI_PARSE_OBJECT
*origin
,
687 ACPI_OPERAND_OBJECT
*mth_desc
,
688 ACPI_WALK_LIST
*walk_list
)
690 ACPI_WALK_STATE
*walk_state
;
694 acpi_cm_acquire_mutex (ACPI_MTX_CACHES
);
695 acpi_gbl_walk_state_cache_requests
++;
697 /* Check the cache first */
699 if (acpi_gbl_walk_state_cache
) {
700 /* There is an object available, use it */
702 walk_state
= acpi_gbl_walk_state_cache
;
703 acpi_gbl_walk_state_cache
= walk_state
->next
;
705 acpi_gbl_walk_state_cache_hits
++;
706 acpi_gbl_walk_state_cache_depth
--;
708 acpi_cm_release_mutex (ACPI_MTX_CACHES
);
712 /* The cache is empty, create a new object */
714 /* Avoid deadlock with Acpi_cm_callocate */
716 acpi_cm_release_mutex (ACPI_MTX_CACHES
);
718 walk_state
= acpi_cm_callocate (sizeof (ACPI_WALK_STATE
));
724 walk_state
->data_type
= ACPI_DESC_TYPE_WALK
;
725 walk_state
->owner_id
= owner_id
;
726 walk_state
->origin
= origin
;
727 walk_state
->method_desc
= mth_desc
;
728 walk_state
->walk_list
= walk_list
;
730 /* Init the method args/local */
732 #ifndef _ACPI_ASL_COMPILER
733 acpi_ds_method_data_init (walk_state
);
736 /* Create an initial result stack entry */
738 status
= acpi_ds_result_stack_push (walk_state
);
739 if (ACPI_FAILURE (status
)) {
744 /* Put the new state at the head of the walk list */
746 acpi_ds_push_walk_state (walk_state
, walk_list
);
752 /*******************************************************************************
754 * FUNCTION: Acpi_ds_delete_walk_state
756 * PARAMETERS: Walk_state - State to delete
760 * DESCRIPTION: Delete a walk state including all internal data structures
762 ******************************************************************************/
765 acpi_ds_delete_walk_state (
766 ACPI_WALK_STATE
*walk_state
)
768 ACPI_GENERIC_STATE
*state
;
775 if (walk_state
->data_type
!= ACPI_DESC_TYPE_WALK
) {
780 /* Always must free any linked control states */
782 while (walk_state
->control_state
) {
783 state
= walk_state
->control_state
;
784 walk_state
->control_state
= state
->common
.next
;
786 acpi_cm_delete_generic_state (state
);
789 /* Always must free any linked parse states */
791 while (walk_state
->scope_info
) {
792 state
= walk_state
->scope_info
;
793 walk_state
->scope_info
= state
->common
.next
;
795 acpi_cm_delete_generic_state (state
);
798 /* Always must free any stacked result states */
800 while (walk_state
->results
) {
801 state
= walk_state
->results
;
802 walk_state
->results
= state
->common
.next
;
804 acpi_cm_delete_generic_state (state
);
808 /* If walk cache is full, just free this wallkstate object */
810 if (acpi_gbl_walk_state_cache_depth
>= MAX_WALK_CACHE_DEPTH
) {
811 acpi_cm_free (walk_state
);
814 /* Otherwise put this object back into the cache */
817 acpi_cm_acquire_mutex (ACPI_MTX_CACHES
);
819 /* Clear the state */
821 MEMSET (walk_state
, 0, sizeof (ACPI_WALK_STATE
));
822 walk_state
->data_type
= ACPI_DESC_TYPE_WALK
;
824 /* Put the object at the head of the global cache list */
826 walk_state
->next
= acpi_gbl_walk_state_cache
;
827 acpi_gbl_walk_state_cache
= walk_state
;
828 acpi_gbl_walk_state_cache_depth
++;
831 acpi_cm_release_mutex (ACPI_MTX_CACHES
);
838 /******************************************************************************
840 * FUNCTION: Acpi_ds_delete_walk_state_cache
846 * DESCRIPTION: Purge the global state object cache. Used during subsystem
849 ******************************************************************************/
852 acpi_ds_delete_walk_state_cache (
855 ACPI_WALK_STATE
*next
;
858 /* Traverse the global cache list */
860 while (acpi_gbl_walk_state_cache
) {
861 /* Delete one cached state object */
863 next
= acpi_gbl_walk_state_cache
->next
;
864 acpi_cm_free (acpi_gbl_walk_state_cache
);
865 acpi_gbl_walk_state_cache
= next
;
866 acpi_gbl_walk_state_cache_depth
--;