dswstate.c revision 67754
1/******************************************************************************
2 *
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
4 *              $Revision: 31 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
13 * reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#define __DSWSTATE_C__
119
120#include "acpi.h"
121#include "amlcode.h"
122#include "acparser.h"
123#include "acdispat.h"
124#include "acnamesp.h"
125#include "acinterp.h"
126
127#define _COMPONENT          DISPATCHER
128        MODULE_NAME         ("dswstate")
129
130
131/*******************************************************************************
132 *
133 * FUNCTION:    AcpiDsResultStackClear
134 *
135 * PARAMETERS:  WalkState           - Current Walk state
136 *
137 * RETURN:      Status
138 *
139 * DESCRIPTION: Reset this walk's result stack pointers to zero, thus setting
140 *              the stack to zero.
141 *
142 ******************************************************************************/
143
144ACPI_STATUS
145AcpiDsResultStackClear (
146    ACPI_WALK_STATE         *WalkState)
147{
148
149    WalkState->NumResults = 0;
150    WalkState->CurrentResult = 0;
151
152    return (AE_OK);
153}
154
155
156/*******************************************************************************
157 *
158 * FUNCTION:    AcpiDsResultStackPush
159 *
160 * PARAMETERS:  Object              - Object to push
161 *              WalkState           - Current Walk state
162 *
163 * RETURN:      Status
164 *
165 * DESCRIPTION: Push an object onto this walk's result stack
166 *
167 ******************************************************************************/
168
169ACPI_STATUS
170AcpiDsResultStackPush (
171    void                    *Object,
172    ACPI_WALK_STATE         *WalkState)
173{
174
175
176    if (WalkState->NumResults >= OBJ_NUM_OPERANDS)
177    {
178        DEBUG_PRINT (ACPI_ERROR,
179            ("DsResultStackPush: overflow! Obj=%p State=%p Num=%X\n",
180            Object, WalkState, WalkState->NumResults));
181        return (AE_STACK_OVERFLOW);
182    }
183
184    WalkState->Results [WalkState->NumResults] = Object;
185    WalkState->NumResults++;
186
187    DEBUG_PRINT (TRACE_EXEC,
188        ("DsResultStackPush: Obj=%p State=%p Num=%X Cur=%X\n",
189        Object, WalkState, WalkState->NumResults, WalkState->CurrentResult));
190
191    return (AE_OK);
192}
193
194
195/*******************************************************************************
196 *
197 * FUNCTION:    AcpiDsResultStackPop
198 *
199 * PARAMETERS:  Object              - Where to return the popped object
200 *              WalkState           - Current Walk state
201 *
202 * RETURN:      Status
203 *
204 * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
205 *              other words, this is a FIFO.
206 *
207 ******************************************************************************/
208
209ACPI_STATUS
210AcpiDsResultStackPop (
211    ACPI_OPERAND_OBJECT     **Object,
212    ACPI_WALK_STATE         *WalkState)
213{
214
215
216    /* Check for stack underflow */
217
218    if (WalkState->NumResults == 0)
219    {
220        DEBUG_PRINT (ACPI_ERROR,
221            ("DsResultStackPop: Underflow! State=%p Cur=%X Num=%X\n",
222            WalkState, WalkState->CurrentResult, WalkState->NumResults));
223        return (AE_AML_NO_OPERAND);
224    }
225
226
227    /* Pop the stack */
228
229    WalkState->NumResults--;
230
231    /* Check for a valid result object */
232
233    if (!WalkState->Results [WalkState->NumResults])
234    {
235        DEBUG_PRINT (ACPI_ERROR,
236            ("DsResultStackPop: Null operand! State=%p #Ops=%X\n",
237            WalkState, WalkState->NumResults));
238        return (AE_AML_NO_OPERAND);
239    }
240
241    *Object = WalkState->Results [WalkState->NumResults];
242    WalkState->Results [WalkState->NumResults] = NULL;
243
244    DEBUG_PRINT (TRACE_EXEC,
245        ("DsResultStackPop: Obj=%p State=%p Num=%X Cur=%X\n",
246        *Object, WalkState, WalkState->NumResults, WalkState->CurrentResult));
247
248    return (AE_OK);
249}
250
251
252/*******************************************************************************
253 *
254 * FUNCTION:    AcpiDsObjStackDeleteAll
255 *
256 * PARAMETERS:  WalkState           - Current Walk state
257 *
258 * RETURN:      Status
259 *
260 * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
261 *              Should be used with great care, if at all!
262 *
263 ******************************************************************************/
264
265ACPI_STATUS
266AcpiDsObjStackDeleteAll (
267    ACPI_WALK_STATE         *WalkState)
268{
269    UINT32                  i;
270
271
272    FUNCTION_TRACE_PTR ("DsObjStackDeleteAll", WalkState);
273
274
275    /* The stack size is configurable, but fixed */
276
277    for (i = 0; i < OBJ_NUM_OPERANDS; i++)
278    {
279        if (WalkState->Operands[i])
280        {
281            AcpiCmRemoveReference (WalkState->Operands[i]);
282            WalkState->Operands[i] = NULL;
283        }
284    }
285
286    return_ACPI_STATUS (AE_OK);
287}
288
289
290/*******************************************************************************
291 *
292 * FUNCTION:    AcpiDsObjStackPush
293 *
294 * PARAMETERS:  Object              - Object to push
295 *              WalkState           - Current Walk state
296 *
297 * RETURN:      Status
298 *
299 * DESCRIPTION: Push an object onto this walk's object/operand stack
300 *
301 ******************************************************************************/
302
303ACPI_STATUS
304AcpiDsObjStackPush (
305    void                    *Object,
306    ACPI_WALK_STATE         *WalkState)
307{
308
309
310    /* Check for stack overflow */
311
312    if (WalkState->NumOperands >= OBJ_NUM_OPERANDS)
313    {
314        DEBUG_PRINT (ACPI_ERROR,
315            ("DsObjStackPush: overflow! Obj=%p State=%p #Ops=%X\n",
316            Object, WalkState, WalkState->NumOperands));
317        return (AE_STACK_OVERFLOW);
318    }
319
320    /* Put the object onto the stack */
321
322    WalkState->Operands [WalkState->NumOperands] = Object;
323    WalkState->NumOperands++;
324
325    DEBUG_PRINT (TRACE_EXEC, ("DsObjStackPush: Obj=%p State=%p #Ops=%X\n",
326                    Object, WalkState, WalkState->NumOperands));
327
328    return (AE_OK);
329}
330
331
332/*******************************************************************************
333 *
334 * FUNCTION:    AcpiDsObjStackPopObject
335 *
336 * PARAMETERS:  PopCount            - Number of objects/entries to pop
337 *              WalkState           - Current Walk state
338 *
339 * RETURN:      Status
340 *
341 * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
342 *              deleted by this routine.
343 *
344 ******************************************************************************/
345
346ACPI_STATUS
347AcpiDsObjStackPopObject (
348    ACPI_OPERAND_OBJECT     **Object,
349    ACPI_WALK_STATE         *WalkState)
350{
351
352
353    /* Check for stack underflow */
354
355    if (WalkState->NumOperands == 0)
356    {
357        DEBUG_PRINT (ACPI_ERROR,
358            ("DsObjStackPop: Missing operand/stack empty! State=%p #Ops=%X\n",
359            WalkState, WalkState->NumOperands));
360        return (AE_AML_NO_OPERAND);
361    }
362
363
364    /* Pop the stack */
365
366    WalkState->NumOperands--;
367
368    /* Check for a valid operand */
369
370    if (!WalkState->Operands [WalkState->NumOperands])
371    {
372        DEBUG_PRINT (ACPI_ERROR,
373            ("DsObjStackPop: Null operand! State=%p #Ops=%X\n",
374            WalkState, WalkState->NumOperands));
375        return (AE_AML_NO_OPERAND);
376    }
377
378    /* Get operand and set stack entry to null */
379
380    *Object = WalkState->Operands [WalkState->NumOperands];
381    WalkState->Operands [WalkState->NumOperands] = NULL;
382
383    DEBUG_PRINT (TRACE_EXEC, ("DsObjStackPopObject: State=%p #Ops=%X\n",
384                    WalkState, WalkState->NumOperands));
385
386    return (AE_OK);
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION:    AcpiDsObjStackPop
393 *
394 * PARAMETERS:  PopCount            - Number of objects/entries to pop
395 *              WalkState           - Current Walk state
396 *
397 * RETURN:      Status
398 *
399 * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
400 *              deleted by this routine.
401 *
402 ******************************************************************************/
403
404ACPI_STATUS
405AcpiDsObjStackPop (
406    UINT32                  PopCount,
407    ACPI_WALK_STATE         *WalkState)
408{
409    UINT32                  i;
410
411
412    for (i = 0; i < PopCount; i++)
413    {
414        /* Check for stack underflow */
415
416        if (WalkState->NumOperands == 0)
417        {
418            DEBUG_PRINT (ACPI_ERROR,
419                ("DsObjStackPop: Underflow! Count=%X State=%p #Ops=%X\n",
420                PopCount, WalkState, WalkState->NumOperands));
421            return (AE_STACK_UNDERFLOW);
422        }
423
424        /* Just set the stack entry to null */
425
426        WalkState->NumOperands--;
427        WalkState->Operands [WalkState->NumOperands] = NULL;
428    }
429
430    DEBUG_PRINT (TRACE_EXEC, ("DsObjStackPop: Count=%X State=%p #Ops=%X\n",
431                    PopCount, WalkState, WalkState->NumOperands));
432
433    return (AE_OK);
434}
435
436
437/*******************************************************************************
438 *
439 * FUNCTION:    AcpiDsObjStackPopAndDelete
440 *
441 * PARAMETERS:  PopCount            - Number of objects/entries to pop
442 *              WalkState           - Current Walk state
443 *
444 * RETURN:      Status
445 *
446 * DESCRIPTION: Pop this walk's object stack and delete each object that is
447 *              popped off.
448 *
449 ******************************************************************************/
450
451ACPI_STATUS
452AcpiDsObjStackPopAndDelete (
453    UINT32                  PopCount,
454    ACPI_WALK_STATE         *WalkState)
455{
456    UINT32                  i;
457    ACPI_OPERAND_OBJECT     *ObjDesc;
458
459
460    for (i = 0; i < PopCount; i++)
461    {
462        /* Check for stack underflow */
463
464        if (WalkState->NumOperands == 0)
465        {
466            DEBUG_PRINT (ACPI_ERROR,
467                ("DsObjStackPop: Underflow! Count=%X State=%p #Ops=%X\n",
468                PopCount, WalkState, WalkState->NumOperands));
469            return (AE_STACK_UNDERFLOW);
470        }
471
472        /* Pop the stack and delete an object if present in this stack entry */
473
474        WalkState->NumOperands--;
475        ObjDesc = WalkState->Operands [WalkState->NumOperands];
476        if (ObjDesc)
477        {
478            AcpiCmRemoveReference (WalkState->Operands [WalkState->NumOperands]);
479            WalkState->Operands [WalkState->NumOperands] = NULL;
480        }
481    }
482
483    DEBUG_PRINT (TRACE_EXEC, ("DsObjStackPop: Count=%X State=%p #Ops=%X\n",
484                    PopCount, WalkState, WalkState->NumOperands));
485
486    return (AE_OK);
487}
488
489
490/*******************************************************************************
491 *
492 * FUNCTION:    AcpiDsObjStackGetValue
493 *
494 * PARAMETERS:  Index               - Stack index whose value is desired.  Based
495 *                                    on the top of the stack (index=0 == top)
496 *              WalkState           - Current Walk state
497 *
498 * RETURN:      Status
499 *
500 * DESCRIPTION: Retrieve an object from this walk's object stack.  Index must
501 *              be within the range of the current stack pointer.
502 *
503 ******************************************************************************/
504
505void *
506AcpiDsObjStackGetValue (
507    UINT32                  Index,
508    ACPI_WALK_STATE         *WalkState)
509{
510
511    FUNCTION_TRACE_PTR ("DsObjStackGetValue", WalkState);
512
513
514    /* Can't do it if the stack is empty */
515
516    if (WalkState->NumOperands == 0)
517    {
518        return_VALUE (NULL);
519    }
520
521    /* or if the index is past the top of the stack */
522
523    if (Index > (WalkState->NumOperands - (UINT32) 1))
524    {
525        return_VALUE (NULL);
526    }
527
528
529    return_PTR (WalkState->Operands[(NATIVE_UINT)(WalkState->NumOperands - 1) -
530                    Index]);
531}
532
533
534/*******************************************************************************
535 *
536 * FUNCTION:    AcpiDsGetCurrentWalkState
537 *
538 * PARAMETERS:  WalkList        - Get current active state for this walk list
539 *
540 * RETURN:      Pointer to the current walk state
541 *
542 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
543 *              walk state.
544 *
545 ******************************************************************************/
546
547ACPI_WALK_STATE *
548AcpiDsGetCurrentWalkState (
549    ACPI_WALK_LIST          *WalkList)
550
551{
552
553    DEBUG_PRINT (TRACE_PARSE, ("DsGetCurrentWalkState, =%p\n", WalkList->WalkState));
554
555    if (!WalkList)
556    {
557        return (NULL);
558    }
559
560    return (WalkList->WalkState);
561}
562
563
564/*******************************************************************************
565 *
566 * FUNCTION:    AcpiDsPushWalkState
567 *
568 * PARAMETERS:  WalkState       - State to push
569 *              WalkList        - The list that owns the walk stack
570 *
571 * RETURN:      None
572 *
573 * DESCRIPTION: Place the WalkState at the head of the state list.
574 *
575 ******************************************************************************/
576
577void
578AcpiDsPushWalkState (
579    ACPI_WALK_STATE         *WalkState,
580    ACPI_WALK_LIST          *WalkList)
581{
582
583
584    FUNCTION_TRACE ("DsPushWalkState");
585
586
587    WalkState->Next     = WalkList->WalkState;
588    WalkList->WalkState = WalkState;
589
590    return_VOID;
591}
592
593
594/*******************************************************************************
595 *
596 * FUNCTION:    AcpiDsPopWalkState
597 *
598 * PARAMETERS:  WalkList        - The list that owns the walk stack
599 *
600 * RETURN:      A WalkState object popped from the stack
601 *
602 * DESCRIPTION: Remove and return the walkstate object that is at the head of
603 *              the walk stack for the given walk list.  NULL indicates that
604 *              the list is empty.
605 *
606 ******************************************************************************/
607
608ACPI_WALK_STATE *
609AcpiDsPopWalkState (
610    ACPI_WALK_LIST          *WalkList)
611{
612    ACPI_WALK_STATE         *WalkState;
613
614
615    FUNCTION_TRACE ("DsPopWalkState");
616
617
618    WalkState = WalkList->WalkState;
619
620    if (WalkState)
621    {
622        /* Next walk state becomes the current walk state */
623
624        WalkList->WalkState = WalkState->Next;
625
626        /*
627         * Don't clear the NEXT field, this serves as an indicator
628         * that there is a parent WALK STATE
629         *     WalkState->Next = NULL;
630         */
631    }
632
633    return_PTR (WalkState);
634}
635
636
637/*******************************************************************************
638 *
639 * FUNCTION:    AcpiDsCreateWalkState
640 *
641 * PARAMETERS:  Origin          - Starting point for this walk
642 *              WalkList        - Owning walk list
643 *
644 * RETURN:      Pointer to the new walk state.
645 *
646 * DESCRIPTION: Allocate and initialize a new walk state.  The current walk state
647 *              is set to this new state.
648 *
649 ******************************************************************************/
650
651ACPI_WALK_STATE *
652AcpiDsCreateWalkState (
653    ACPI_OWNER_ID           OwnerId,
654    ACPI_PARSE_OBJECT       *Origin,
655    ACPI_OPERAND_OBJECT     *MthDesc,
656    ACPI_WALK_LIST          *WalkList)
657{
658    ACPI_WALK_STATE         *WalkState;
659
660
661    FUNCTION_TRACE ("DsCreateWalkState");
662
663
664    AcpiCmAcquireMutex (ACPI_MTX_CACHES);
665    AcpiGbl_WalkStateCacheRequests++;
666
667    /* Check the cache first */
668
669    if (AcpiGbl_WalkStateCache)
670    {
671        /* There is an object available, use it */
672
673        WalkState = AcpiGbl_WalkStateCache;
674        AcpiGbl_WalkStateCache = WalkState->Next;
675
676        AcpiGbl_WalkStateCacheHits++;
677        AcpiGbl_WalkStateCacheDepth--;
678
679        DEBUG_PRINT (TRACE_EXEC, ("DsCreateWalkState: State %p from cache\n", WalkState));
680
681        AcpiCmReleaseMutex (ACPI_MTX_CACHES);
682   }
683
684    else
685    {
686        /* The cache is empty, create a new object */
687
688        /* Avoid deadlock with AcpiCmCallocate */
689
690        AcpiCmReleaseMutex (ACPI_MTX_CACHES);
691
692        WalkState = AcpiCmCallocate (sizeof (ACPI_WALK_STATE));
693        if (!WalkState)
694        {
695            return_VALUE (NULL);
696        }
697    }
698
699    WalkState->DataType         = ACPI_DESC_TYPE_WALK;
700    WalkState->OwnerId          = OwnerId;
701    WalkState->Origin           = Origin;
702    WalkState->MethodDesc       = MthDesc;
703
704    /* Init the method args/local */
705
706    AcpiDsMethodDataInit (WalkState);
707
708    /* Put the new state at the head of the walk list */
709
710    AcpiDsPushWalkState (WalkState, WalkList);
711
712    return_PTR (WalkState);
713}
714
715
716/*******************************************************************************
717 *
718 * FUNCTION:    AcpiDsDeleteWalkState
719 *
720 * PARAMETERS:  WalkState       - State to delete
721 *
722 * RETURN:      Status
723 *
724 * DESCRIPTION: Delete a walk state including all internal data structures
725 *
726 ******************************************************************************/
727
728void
729AcpiDsDeleteWalkState (
730    ACPI_WALK_STATE         *WalkState)
731{
732    ACPI_GENERIC_STATE      *State;
733
734
735    FUNCTION_TRACE_PTR ("DsDeleteWalkState", WalkState);
736
737
738    if (!WalkState)
739    {
740        return;
741    }
742
743    if (WalkState->DataType != ACPI_DESC_TYPE_WALK)
744    {
745        DEBUG_PRINT (ACPI_ERROR,
746            ("DsDeleteWalkState: **** %p not a valid walk state\n", WalkState));
747        return;
748    }
749
750    /* Always must free any linked control states */
751
752    while (WalkState->ControlState)
753    {
754        State = WalkState->ControlState;
755        WalkState->ControlState = State->Common.Next;
756
757        AcpiCmDeleteGenericState (State);
758    }
759
760
761    /* Always must free any linked parse states */
762
763    while (WalkState->ScopeInfo)
764    {
765        State = WalkState->ScopeInfo;
766        WalkState->ScopeInfo = State->Common.Next;
767
768        AcpiCmDeleteGenericState (State);
769    }
770
771    /* If walk cache is full, just free this wallkstate object */
772
773    if (AcpiGbl_WalkStateCacheDepth >= MAX_WALK_CACHE_DEPTH)
774    {
775        AcpiCmFree (WalkState);
776    }
777
778    /* Otherwise put this object back into the cache */
779
780    else
781    {
782        AcpiCmAcquireMutex (ACPI_MTX_CACHES);
783
784        /* Clear the state */
785
786        MEMSET (WalkState, 0, sizeof (ACPI_WALK_STATE));
787        WalkState->DataType = ACPI_DESC_TYPE_WALK;
788
789        /* Put the object at the head of the global cache list */
790
791        WalkState->Next = AcpiGbl_WalkStateCache;
792        AcpiGbl_WalkStateCache = WalkState;
793        AcpiGbl_WalkStateCacheDepth++;
794
795
796        AcpiCmReleaseMutex (ACPI_MTX_CACHES);
797    }
798
799    return_VOID;
800}
801
802
803/******************************************************************************
804 *
805 * FUNCTION:    AcpiDsDeleteWalkStateCache
806 *
807 * PARAMETERS:  None
808 *
809 * RETURN:      Status
810 *
811 * DESCRIPTION: Purge the global state object cache.  Used during subsystem
812 *              termination.
813 *
814 ******************************************************************************/
815
816void
817AcpiDsDeleteWalkStateCache (
818    void)
819{
820    ACPI_WALK_STATE         *Next;
821
822
823    FUNCTION_TRACE ("DsDeleteWalkStateCache");
824
825
826    /* Traverse the global cache list */
827
828    while (AcpiGbl_WalkStateCache)
829    {
830        /* Delete one cached state object */
831
832        Next = AcpiGbl_WalkStateCache->Next;
833        AcpiCmFree (AcpiGbl_WalkStateCache);
834        AcpiGbl_WalkStateCache = Next;
835        AcpiGbl_WalkStateCacheDepth--;
836    }
837
838    return_VOID;
839}
840
841
842