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
34 #define _COMPONENT ACPI_DISPATCHER
35 MODULE_NAME ("dswstate")
38 /*******************************************************************************
40 * FUNCTION: Acpi_ds_result_insert
42 * PARAMETERS: Object - Object to push
43 * Walk_state - Current Walk state
47 * DESCRIPTION: Push an object onto this walk's result stack
49 ******************************************************************************/
52 acpi_ds_result_insert (
55 ACPI_WALK_STATE *walk_state)
57 ACPI_GENERIC_STATE *state;
60 state = walk_state->results;
62 return (AE_NOT_EXIST);
65 if (index >= OBJ_NUM_OPERANDS) {
66 return (AE_BAD_PARAMETER);
70 return (AE_BAD_PARAMETER);
73 state->results.obj_desc [index] = object;
74 state->results.num_results++;
80 /*******************************************************************************
82 * FUNCTION: Acpi_ds_result_remove
84 * PARAMETERS: Object - Where to return the popped object
85 * Walk_state - Current Walk state
89 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
90 * other words, this is a FIFO.
92 ******************************************************************************/
95 acpi_ds_result_remove (
96 ACPI_OPERAND_OBJECT **object,
98 ACPI_WALK_STATE *walk_state)
100 ACPI_GENERIC_STATE *state;
103 state = walk_state->results;
105 return (AE_NOT_EXIST);
110 /* Check for a valid result object */
112 if (!state->results.obj_desc [index]) {
113 return (AE_AML_NO_RETURN_VALUE);
116 /* Remove the object */
118 state->results.num_results--;
120 *object = state->results.obj_desc [index];
121 state->results.obj_desc [index] = NULL;
127 /*******************************************************************************
129 * FUNCTION: Acpi_ds_result_pop
131 * PARAMETERS: Object - Where to return the popped object
132 * Walk_state - Current Walk state
136 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
137 * other words, this is a FIFO.
139 ******************************************************************************/
143 ACPI_OPERAND_OBJECT **object,
144 ACPI_WALK_STATE *walk_state)
147 ACPI_GENERIC_STATE *state;
150 state = walk_state->results;
156 if (!state->results.num_results) {
157 return (AE_AML_NO_RETURN_VALUE);
160 /* Remove top element */
162 state->results.num_results--;
164 for (index = OBJ_NUM_OPERANDS; index; index--) {
165 /* Check for a valid result object */
167 if (state->results.obj_desc [index -1]) {
168 *object = state->results.obj_desc [index -1];
169 state->results.obj_desc [index -1] = NULL;
176 return (AE_AML_NO_RETURN_VALUE);
179 /*******************************************************************************
181 * FUNCTION: Acpi_ds_result_pop_from_bottom
183 * PARAMETERS: Object - Where to return the popped object
184 * Walk_state - Current Walk state
188 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
189 * other words, this is a FIFO.
191 ******************************************************************************/
194 acpi_ds_result_pop_from_bottom (
195 ACPI_OPERAND_OBJECT **object,
196 ACPI_WALK_STATE *walk_state)
199 ACPI_GENERIC_STATE *state;
202 state = walk_state->results;
204 return (AE_NOT_EXIST);
208 if (!state->results.num_results) {
209 return (AE_AML_NO_RETURN_VALUE);
212 /* Remove Bottom element */
214 *object = state->results.obj_desc [0];
217 /* Push entire stack down one element */
219 for (index = 0; index < state->results.num_results; index++) {
220 state->results.obj_desc [index] = state->results.obj_desc [index + 1];
223 state->results.num_results--;
225 /* Check for a valid result object */
228 return (AE_AML_NO_RETURN_VALUE);
236 /*******************************************************************************
238 * FUNCTION: Acpi_ds_result_push
240 * PARAMETERS: Object - Where to return the popped object
241 * Walk_state - Current Walk state
245 * DESCRIPTION: Push an object onto the current result stack
247 ******************************************************************************/
250 acpi_ds_result_push (
251 ACPI_OPERAND_OBJECT *object,
252 ACPI_WALK_STATE *walk_state)
254 ACPI_GENERIC_STATE *state;
257 state = walk_state->results;
259 return (AE_AML_INTERNAL);
262 if (state->results.num_results == OBJ_NUM_OPERANDS) {
263 return (AE_STACK_OVERFLOW);
267 return (AE_BAD_PARAMETER);
271 state->results.obj_desc [state->results.num_results] = object;
272 state->results.num_results++;
278 /*******************************************************************************
280 * FUNCTION: Acpi_ds_result_stack_push
282 * PARAMETERS: Object - Object to push
283 * Walk_state - Current Walk state
289 ******************************************************************************/
292 acpi_ds_result_stack_push (
293 ACPI_WALK_STATE *walk_state)
295 ACPI_GENERIC_STATE *state;
298 state = acpi_cm_create_generic_state ();
300 return (AE_NO_MEMORY);
303 acpi_cm_push_generic_state (&walk_state->results, state);
309 /*******************************************************************************
311 * FUNCTION: Acpi_ds_result_stack_pop
313 * PARAMETERS: Walk_state - Current Walk state
319 ******************************************************************************/
322 acpi_ds_result_stack_pop (
323 ACPI_WALK_STATE *walk_state)
325 ACPI_GENERIC_STATE *state;
328 /* Check for stack underflow */
330 if (walk_state->results == NULL) {
331 return (AE_AML_NO_OPERAND);
335 state = acpi_cm_pop_generic_state (&walk_state->results);
337 acpi_cm_delete_generic_state (state);
343 /*******************************************************************************
345 * FUNCTION: Acpi_ds_obj_stack_delete_all
347 * PARAMETERS: Walk_state - Current Walk state
351 * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
352 * Should be used with great care, if at all!
354 ******************************************************************************/
357 acpi_ds_obj_stack_delete_all (
358 ACPI_WALK_STATE *walk_state)
363 /* The stack size is configurable, but fixed */
365 for (i = 0; i < OBJ_NUM_OPERANDS; i++) {
366 if (walk_state->operands[i]) {
367 acpi_cm_remove_reference (walk_state->operands[i]);
368 walk_state->operands[i] = NULL;
376 /*******************************************************************************
378 * FUNCTION: Acpi_ds_obj_stack_push
380 * PARAMETERS: Object - Object to push
381 * Walk_state - Current Walk state
385 * DESCRIPTION: Push an object onto this walk's object/operand stack
387 ******************************************************************************/
390 acpi_ds_obj_stack_push (
392 ACPI_WALK_STATE *walk_state)
396 /* Check for stack overflow */
398 if (walk_state->num_operands >= OBJ_NUM_OPERANDS) {
399 return (AE_STACK_OVERFLOW);
402 /* Put the object onto the stack */
404 walk_state->operands [walk_state->num_operands] = object;
405 walk_state->num_operands++;
411 /*******************************************************************************
413 * FUNCTION: Acpi_ds_obj_stack_pop_object
415 * PARAMETERS: Pop_count - Number of objects/entries to pop
416 * Walk_state - Current Walk state
420 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
421 * deleted by this routine.
423 ******************************************************************************/
426 acpi_ds_obj_stack_pop_object (
427 ACPI_OPERAND_OBJECT **object,
428 ACPI_WALK_STATE *walk_state)
432 /* Check for stack underflow */
434 if (walk_state->num_operands == 0) {
435 return (AE_AML_NO_OPERAND);
441 walk_state->num_operands--;
443 /* Check for a valid operand */
445 if (!walk_state->operands [walk_state->num_operands]) {
446 return (AE_AML_NO_OPERAND);
449 /* Get operand and set stack entry to null */
451 *object = walk_state->operands [walk_state->num_operands];
452 walk_state->operands [walk_state->num_operands] = NULL;
458 /*******************************************************************************
460 * FUNCTION: Acpi_ds_obj_stack_pop
462 * PARAMETERS: Pop_count - Number of objects/entries to pop
463 * Walk_state - Current Walk state
467 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
468 * deleted by this routine.
470 ******************************************************************************/
473 acpi_ds_obj_stack_pop (
475 ACPI_WALK_STATE *walk_state)
480 for (i = 0; i < pop_count; i++) {
481 /* Check for stack underflow */
483 if (walk_state->num_operands == 0) {
484 return (AE_STACK_UNDERFLOW);
487 /* Just set the stack entry to null */
489 walk_state->num_operands--;
490 walk_state->operands [walk_state->num_operands] = NULL;
497 /*******************************************************************************
499 * FUNCTION: Acpi_ds_obj_stack_pop_and_delete
501 * PARAMETERS: Pop_count - Number of objects/entries to pop
502 * Walk_state - Current Walk state
506 * DESCRIPTION: Pop this walk's object stack and delete each object that is
509 ******************************************************************************/
512 acpi_ds_obj_stack_pop_and_delete (
514 ACPI_WALK_STATE *walk_state)
517 ACPI_OPERAND_OBJECT *obj_desc;
520 for (i = 0; i < pop_count; i++) {
521 /* Check for stack underflow */
523 if (walk_state->num_operands == 0) {
524 return (AE_STACK_UNDERFLOW);
527 /* Pop the stack and delete an object if present in this stack entry */
529 walk_state->num_operands--;
530 obj_desc = walk_state->operands [walk_state->num_operands];
532 acpi_cm_remove_reference (walk_state->operands [walk_state->num_operands]);
533 walk_state->operands [walk_state->num_operands] = NULL;
541 /*******************************************************************************
543 * FUNCTION: Acpi_ds_obj_stack_get_value
545 * PARAMETERS: Index - Stack index whose value is desired. Based
546 * on the top of the stack (index=0 == top)
547 * Walk_state - Current Walk state
551 * DESCRIPTION: Retrieve an object from this walk's object stack. Index must
552 * be within the range of the current stack pointer.
554 ******************************************************************************/
557 acpi_ds_obj_stack_get_value (
559 ACPI_WALK_STATE *walk_state)
563 /* Can't do it if the stack is empty */
565 if (walk_state->num_operands == 0) {
569 /* or if the index is past the top of the stack */
571 if (index > (walk_state->num_operands - (u32) 1)) {
576 return (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) -
581 /*******************************************************************************
583 * FUNCTION: Acpi_ds_get_current_walk_state
585 * PARAMETERS: Walk_list - Get current active state for this walk list
587 * RETURN: Pointer to the current walk state
589 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
592 ******************************************************************************/
595 acpi_ds_get_current_walk_state (
596 ACPI_WALK_LIST *walk_list)
604 return (walk_list->walk_state);
608 /*******************************************************************************
610 * FUNCTION: Acpi_ds_push_walk_state
612 * PARAMETERS: Walk_state - State to push
613 * Walk_list - The list that owns the walk stack
617 * DESCRIPTION: Place the Walk_state at the head of the state list.
619 ******************************************************************************/
622 acpi_ds_push_walk_state (
623 ACPI_WALK_STATE *walk_state,
624 ACPI_WALK_LIST *walk_list)
628 walk_state->next = walk_list->walk_state;
629 walk_list->walk_state = walk_state;
635 /*******************************************************************************
637 * FUNCTION: Acpi_ds_pop_walk_state
639 * PARAMETERS: Walk_list - The list that owns the walk stack
641 * RETURN: A Walk_state object popped from the stack
643 * DESCRIPTION: Remove and return the walkstate object that is at the head of
644 * the walk stack for the given walk list. NULL indicates that
647 ******************************************************************************/
650 acpi_ds_pop_walk_state (
651 ACPI_WALK_LIST *walk_list)
653 ACPI_WALK_STATE *walk_state;
656 walk_state = walk_list->walk_state;
659 /* Next walk state becomes the current walk state */
661 walk_list->walk_state = walk_state->next;
664 * Don't clear the NEXT field, this serves as an indicator
665 * that there is a parent WALK STATE
666 * Walk_state->Next = NULL;
674 /*******************************************************************************
676 * FUNCTION: Acpi_ds_create_walk_state
678 * PARAMETERS: Origin - Starting point for this walk
679 * Walk_list - Owning walk list
681 * RETURN: Pointer to the new walk state.
683 * DESCRIPTION: Allocate and initialize a new walk state. The current walk state
684 * is set to this new state.
686 ******************************************************************************/
689 acpi_ds_create_walk_state (
690 ACPI_OWNER_ID owner_id,
691 ACPI_PARSE_OBJECT *origin,
692 ACPI_OPERAND_OBJECT *mth_desc,
693 ACPI_WALK_LIST *walk_list)
695 ACPI_WALK_STATE *walk_state;
699 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
700 acpi_gbl_walk_state_cache_requests++;
702 /* Check the cache first */
704 if (acpi_gbl_walk_state_cache) {
705 /* There is an object available, use it */
707 walk_state = acpi_gbl_walk_state_cache;
708 acpi_gbl_walk_state_cache = walk_state->next;
710 acpi_gbl_walk_state_cache_hits++;
711 acpi_gbl_walk_state_cache_depth--;
713 acpi_cm_release_mutex (ACPI_MTX_CACHES);
717 /* The cache is empty, create a new object */
719 /* Avoid deadlock with Acpi_cm_callocate */
721 acpi_cm_release_mutex (ACPI_MTX_CACHES);
723 walk_state = acpi_cm_callocate (sizeof (ACPI_WALK_STATE));
729 walk_state->data_type = ACPI_DESC_TYPE_WALK;
730 walk_state->owner_id = owner_id;
731 walk_state->origin = origin;
732 walk_state->method_desc = mth_desc;
733 walk_state->walk_list = walk_list;
735 /* Init the method args/local */
737 #ifndef _ACPI_ASL_COMPILER
738 acpi_ds_method_data_init (walk_state);
741 /* Create an initial result stack entry */
743 status = acpi_ds_result_stack_push (walk_state);
744 if (ACPI_FAILURE (status)) {
749 /* Put the new state at the head of the walk list */
751 acpi_ds_push_walk_state (walk_state, walk_list);
757 /*******************************************************************************
759 * FUNCTION: Acpi_ds_delete_walk_state
761 * PARAMETERS: Walk_state - State to delete
765 * DESCRIPTION: Delete a walk state including all internal data structures
767 ******************************************************************************/
770 acpi_ds_delete_walk_state (
771 ACPI_WALK_STATE *walk_state)
773 ACPI_GENERIC_STATE *state;
780 if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
785 /* Always must free any linked control states */
787 while (walk_state->control_state) {
788 state = walk_state->control_state;
789 walk_state->control_state = state->common.next;
791 acpi_cm_delete_generic_state (state);
794 /* Always must free any linked parse states */
796 while (walk_state->scope_info) {
797 state = walk_state->scope_info;
798 walk_state->scope_info = state->common.next;
800 acpi_cm_delete_generic_state (state);
803 /* Always must free any stacked result states */
805 while (walk_state->results) {
806 state = walk_state->results;
807 walk_state->results = state->common.next;
809 acpi_cm_delete_generic_state (state);
813 /* If walk cache is full, just free this wallkstate object */
815 if (acpi_gbl_walk_state_cache_depth >= MAX_WALK_CACHE_DEPTH) {
816 acpi_cm_free (walk_state);
819 /* Otherwise put this object back into the cache */
822 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
824 /* Clear the state */
826 MEMSET (walk_state, 0, sizeof (ACPI_WALK_STATE));
827 walk_state->data_type = ACPI_DESC_TYPE_WALK;
829 /* Put the object at the head of the global cache list */
831 walk_state->next = acpi_gbl_walk_state_cache;
832 acpi_gbl_walk_state_cache = walk_state;
833 acpi_gbl_walk_state_cache_depth++;
836 acpi_cm_release_mutex (ACPI_MTX_CACHES);
843 /******************************************************************************
845 * FUNCTION: Acpi_ds_delete_walk_state_cache
851 * DESCRIPTION: Purge the global state object cache. Used during subsystem
854 ******************************************************************************/
857 acpi_ds_delete_walk_state_cache (
860 ACPI_WALK_STATE *next;
863 /* Traverse the global cache list */
865 while (acpi_gbl_walk_state_cache) {
866 /* Delete one cached state object */
868 next = acpi_gbl_walk_state_cache->next;
869 acpi_cm_free (acpi_gbl_walk_state_cache);
870 acpi_gbl_walk_state_cache = next;
871 acpi_gbl_walk_state_cache_depth--;