1 /*******************************************************************************
   2  *
   3  * Module Name: utdelete - object deletion and reference count utilities
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __UTDELETE_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acinterp.h"
  49 #include "acnamesp.h"
  50 #include "acevents.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_UTILITIES
  54         ACPI_MODULE_NAME    ("utdelete")
  55 
  56 /* Local prototypes */
  57 
  58 static void
  59 AcpiUtDeleteInternalObj (
  60     ACPI_OPERAND_OBJECT     *Object);
  61 
  62 static void
  63 AcpiUtUpdateRefCount (
  64     ACPI_OPERAND_OBJECT     *Object,
  65     UINT32                  Action);
  66 
  67 
  68 /*******************************************************************************
  69  *
  70  * FUNCTION:    AcpiUtDeleteInternalObj
  71  *
  72  * PARAMETERS:  Object         - Object to be deleted
  73  *
  74  * RETURN:      None
  75  *
  76  * DESCRIPTION: Low level object deletion, after reference counts have been
  77  *              updated (All reference counts, including sub-objects!)
  78  *
  79  ******************************************************************************/
  80 
  81 static void
  82 AcpiUtDeleteInternalObj (
  83     ACPI_OPERAND_OBJECT     *Object)
  84 {
  85     void                    *ObjPointer = NULL;
  86     ACPI_OPERAND_OBJECT     *HandlerDesc;
  87     ACPI_OPERAND_OBJECT     *SecondDesc;
  88     ACPI_OPERAND_OBJECT     *NextDesc;
  89     ACPI_OPERAND_OBJECT     **LastObjPtr;
  90 
  91 
  92     ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
  93 
  94 
  95     if (!Object)
  96     {
  97         return_VOID;
  98     }
  99 
 100     /*
 101      * Must delete or free any pointers within the object that are not
 102      * actual ACPI objects (for example, a raw buffer pointer).
 103      */
 104     switch (Object->Common.Type)
 105     {
 106     case ACPI_TYPE_STRING:
 107 
 108         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
 109             Object, Object->String.Pointer));
 110 
 111         /* Free the actual string buffer */
 112 
 113         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
 114         {
 115             /* But only if it is NOT a pointer into an ACPI table */
 116 
 117             ObjPointer = Object->String.Pointer;
 118         }
 119         break;
 120 
 121     case ACPI_TYPE_BUFFER:
 122 
 123         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
 124             Object, Object->Buffer.Pointer));
 125 
 126         /* Free the actual buffer */
 127 
 128         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
 129         {
 130             /* But only if it is NOT a pointer into an ACPI table */
 131 
 132             ObjPointer = Object->Buffer.Pointer;
 133         }
 134         break;
 135 
 136     case ACPI_TYPE_PACKAGE:
 137 
 138         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
 139             Object->Package.Count));
 140 
 141         /*
 142          * Elements of the package are not handled here, they are deleted
 143          * separately
 144          */
 145 
 146         /* Free the (variable length) element pointer array */
 147 
 148         ObjPointer = Object->Package.Elements;
 149         break;
 150 
 151     /*
 152      * These objects have a possible list of notify handlers.
 153      * Device object also may have a GPE block.
 154      */
 155     case ACPI_TYPE_DEVICE:
 156 
 157         if (Object->Device.GpeBlock)
 158         {
 159             (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
 160         }
 161 
 162         /*lint -fallthrough */
 163 
 164     case ACPI_TYPE_PROCESSOR:
 165     case ACPI_TYPE_THERMAL:
 166 
 167         /* Walk the address handler list for this object */
 168 
 169         HandlerDesc = Object->CommonNotify.Handler;
 170         while (HandlerDesc)
 171         {
 172             NextDesc = HandlerDesc->AddressSpace.Next;
 173             AcpiUtRemoveReference (HandlerDesc);
 174             HandlerDesc = NextDesc;
 175         }
 176         break;
 177 
 178     case ACPI_TYPE_MUTEX:
 179 
 180         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 181             "***** Mutex %p, OS Mutex %p\n",
 182             Object, Object->Mutex.OsMutex));
 183 
 184         if (Object == AcpiGbl_GlobalLockMutex)
 185         {
 186             /* Global Lock has extra semaphore */
 187 
 188             (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
 189             AcpiGbl_GlobalLockSemaphore = NULL;
 190 
 191             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
 192             AcpiGbl_GlobalLockMutex = NULL;
 193         }
 194         else
 195         {
 196             AcpiExUnlinkMutex (Object);
 197             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
 198         }
 199         break;
 200 
 201     case ACPI_TYPE_EVENT:
 202 
 203         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 204             "***** Event %p, OS Semaphore %p\n",
 205             Object, Object->Event.OsSemaphore));
 206 
 207         (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
 208         Object->Event.OsSemaphore = NULL;
 209         break;
 210 
 211     case ACPI_TYPE_METHOD:
 212 
 213         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 214             "***** Method %p\n", Object));
 215 
 216         /* Delete the method mutex if it exists */
 217 
 218         if (Object->Method.Mutex)
 219         {
 220             AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
 221             AcpiUtDeleteObjectDesc (Object->Method.Mutex);
 222             Object->Method.Mutex = NULL;
 223         }
 224         break;
 225 
 226     case ACPI_TYPE_REGION:
 227 
 228         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 229             "***** Region %p\n", Object));
 230 
 231         /*
 232          * Update AddressRange list. However, only permanent regions
 233          * are installed in this list. (Not created within a method)
 234          */
 235         if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
 236         {
 237             AcpiUtRemoveAddressRange (Object->Region.SpaceId,
 238                 Object->Region.Node);
 239         }
 240 
 241         SecondDesc = AcpiNsGetSecondaryObject (Object);
 242         if (SecondDesc)
 243         {
 244             /*
 245              * Free the RegionContext if and only if the handler is one of the
 246              * default handlers -- and therefore, we created the context object
 247              * locally, it was not created by an external caller.
 248              */
 249             HandlerDesc = Object->Region.Handler;
 250             if (HandlerDesc)
 251             {
 252                 NextDesc = HandlerDesc->AddressSpace.RegionList;
 253                 LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
 254 
 255                 /* Remove the region object from the handler's list */
 256 
 257                 while (NextDesc)
 258                 {
 259                     if (NextDesc == Object)
 260                     {
 261                         *LastObjPtr = NextDesc->Region.Next;
 262                         break;
 263                     }
 264 
 265                     /* Walk the linked list of handler */
 266 
 267                     LastObjPtr = &NextDesc->Region.Next;
 268                     NextDesc = NextDesc->Region.Next;
 269                 }
 270 
 271                 if (HandlerDesc->AddressSpace.HandlerFlags &
 272                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
 273                 {
 274                     /* Deactivate region and free region context */
 275 
 276                     if (HandlerDesc->AddressSpace.Setup)
 277                     {
 278                         (void) HandlerDesc->AddressSpace.Setup (Object,
 279                             ACPI_REGION_DEACTIVATE,
 280                             HandlerDesc->AddressSpace.Context,
 281                             &SecondDesc->Extra.RegionContext);
 282                     }
 283                 }
 284 
 285                 AcpiUtRemoveReference (HandlerDesc);
 286             }
 287 
 288             /* Now we can free the Extra object */
 289 
 290             AcpiUtDeleteObjectDesc (SecondDesc);
 291         }
 292         break;
 293 
 294     case ACPI_TYPE_BUFFER_FIELD:
 295 
 296         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 297             "***** Buffer Field %p\n", Object));
 298 
 299         SecondDesc = AcpiNsGetSecondaryObject (Object);
 300         if (SecondDesc)
 301         {
 302             AcpiUtDeleteObjectDesc (SecondDesc);
 303         }
 304         break;
 305 
 306     case ACPI_TYPE_LOCAL_BANK_FIELD:
 307 
 308         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 309             "***** Bank Field %p\n", Object));
 310 
 311         SecondDesc = AcpiNsGetSecondaryObject (Object);
 312         if (SecondDesc)
 313         {
 314             AcpiUtDeleteObjectDesc (SecondDesc);
 315         }
 316         break;
 317 
 318     default:
 319 
 320         break;
 321     }
 322 
 323     /* Free any allocated memory (pointer within the object) found above */
 324 
 325     if (ObjPointer)
 326     {
 327         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
 328             ObjPointer));
 329         ACPI_FREE (ObjPointer);
 330     }
 331 
 332     /* Now the object can be safely deleted */
 333 
 334     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
 335         Object, AcpiUtGetObjectTypeName (Object)));
 336 
 337     AcpiUtDeleteObjectDesc (Object);
 338     return_VOID;
 339 }
 340 
 341 
 342 /*******************************************************************************
 343  *
 344  * FUNCTION:    AcpiUtDeleteInternalObjectList
 345  *
 346  * PARAMETERS:  ObjList         - Pointer to the list to be deleted
 347  *
 348  * RETURN:      None
 349  *
 350  * DESCRIPTION: This function deletes an internal object list, including both
 351  *              simple objects and package objects
 352  *
 353  ******************************************************************************/
 354 
 355 void
 356 AcpiUtDeleteInternalObjectList (
 357     ACPI_OPERAND_OBJECT     **ObjList)
 358 {
 359     ACPI_OPERAND_OBJECT     **InternalObj;
 360 
 361 
 362     ACPI_FUNCTION_ENTRY ();
 363 
 364 
 365     /* Walk the null-terminated internal list */
 366 
 367     for (InternalObj = ObjList; *InternalObj; InternalObj++)
 368     {
 369         AcpiUtRemoveReference (*InternalObj);
 370     }
 371 
 372     /* Free the combined parameter pointer list and object array */
 373 
 374     ACPI_FREE (ObjList);
 375     return;
 376 }
 377 
 378 
 379 /*******************************************************************************
 380  *
 381  * FUNCTION:    AcpiUtUpdateRefCount
 382  *
 383  * PARAMETERS:  Object          - Object whose ref count is to be updated
 384  *              Action          - What to do (REF_INCREMENT or REF_DECREMENT)
 385  *
 386  * RETURN:      None. Sets new reference count within the object
 387  *
 388  * DESCRIPTION: Modify the reference count for an internal acpi object
 389  *
 390  ******************************************************************************/
 391 
 392 static void
 393 AcpiUtUpdateRefCount (
 394     ACPI_OPERAND_OBJECT     *Object,
 395     UINT32                  Action)
 396 {
 397     UINT16                  OriginalCount;
 398     UINT16                  NewCount = 0;
 399     ACPI_CPU_FLAGS          LockFlags;
 400 
 401 
 402     ACPI_FUNCTION_NAME (UtUpdateRefCount);
 403 
 404 
 405     if (!Object)
 406     {
 407         return;
 408     }
 409 
 410     /*
 411      * Always get the reference count lock. Note: Interpreter and/or
 412      * Namespace is not always locked when this function is called.
 413      */
 414     LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
 415     OriginalCount = Object->Common.ReferenceCount;
 416 
 417     /* Perform the reference count action (increment, decrement) */
 418 
 419     switch (Action)
 420     {
 421     case REF_INCREMENT:
 422 
 423         NewCount = OriginalCount + 1;
 424         Object->Common.ReferenceCount = NewCount;
 425         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
 426 
 427         /* The current reference count should never be zero here */
 428 
 429         if (!OriginalCount)
 430         {
 431             ACPI_WARNING ((AE_INFO,
 432                 "Obj %p, Reference Count was zero before increment\n",
 433                 Object));
 434         }
 435 
 436         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 437             "Obj %p Type %.2X Refs %.2X [Incremented]\n",
 438             Object, Object->Common.Type, NewCount));
 439         break;
 440 
 441     case REF_DECREMENT:
 442 
 443         /* The current reference count must be non-zero */
 444 
 445         if (OriginalCount)
 446         {
 447             NewCount = OriginalCount - 1;
 448             Object->Common.ReferenceCount = NewCount;
 449         }
 450 
 451         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
 452 
 453         if (!OriginalCount)
 454         {
 455             ACPI_WARNING ((AE_INFO,
 456                 "Obj %p, Reference Count is already zero, cannot decrement\n",
 457                 Object));
 458         }
 459 
 460         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 461             "Obj %p Type %.2X Refs %.2X [Decremented]\n",
 462             Object, Object->Common.Type, NewCount));
 463 
 464         /* Actually delete the object on a reference count of zero */
 465 
 466         if (NewCount == 0)
 467         {
 468             AcpiUtDeleteInternalObj (Object);
 469         }
 470         break;
 471 
 472     default:
 473 
 474         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
 475         ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
 476             Action));
 477         return;
 478     }
 479 
 480     /*
 481      * Sanity check the reference count, for debug purposes only.
 482      * (A deleted object will have a huge reference count)
 483      */
 484     if (NewCount > ACPI_MAX_REFERENCE_COUNT)
 485     {
 486         ACPI_WARNING ((AE_INFO,
 487             "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
 488             NewCount, Object, Object->Common.Type));
 489     }
 490 }
 491 
 492 
 493 /*******************************************************************************
 494  *
 495  * FUNCTION:    AcpiUtUpdateObjectReference
 496  *
 497  * PARAMETERS:  Object              - Increment ref count for this object
 498  *                                    and all sub-objects
 499  *              Action              - Either REF_INCREMENT or REF_DECREMENT
 500  *
 501  * RETURN:      Status
 502  *
 503  * DESCRIPTION: Increment the object reference count
 504  *
 505  * Object references are incremented when:
 506  * 1) An object is attached to a Node (namespace object)
 507  * 2) An object is copied (all subobjects must be incremented)
 508  *
 509  * Object references are decremented when:
 510  * 1) An object is detached from an Node
 511  *
 512  ******************************************************************************/
 513 
 514 ACPI_STATUS
 515 AcpiUtUpdateObjectReference (
 516     ACPI_OPERAND_OBJECT     *Object,
 517     UINT16                  Action)
 518 {
 519     ACPI_STATUS             Status = AE_OK;
 520     ACPI_GENERIC_STATE      *StateList = NULL;
 521     ACPI_OPERAND_OBJECT     *NextObject = NULL;
 522     ACPI_OPERAND_OBJECT     *PrevObject;
 523     ACPI_GENERIC_STATE      *State;
 524     UINT32                  i;
 525 
 526 
 527     ACPI_FUNCTION_NAME (UtUpdateObjectReference);
 528 
 529 
 530     while (Object)
 531     {
 532         /* Make sure that this isn't a namespace handle */
 533 
 534         if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
 535         {
 536             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 537                 "Object %p is NS handle\n", Object));
 538             return (AE_OK);
 539         }
 540 
 541         /*
 542          * All sub-objects must have their reference count incremented also.
 543          * Different object types have different subobjects.
 544          */
 545         switch (Object->Common.Type)
 546         {
 547         case ACPI_TYPE_DEVICE:
 548         case ACPI_TYPE_PROCESSOR:
 549         case ACPI_TYPE_POWER:
 550         case ACPI_TYPE_THERMAL:
 551             /*
 552              * Update the notify objects for these types (if present)
 553              * Two lists, system and device notify handlers.
 554              */
 555             for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 556             {
 557                 PrevObject = Object->CommonNotify.NotifyList[i];
 558                 while (PrevObject)
 559                 {
 560                     NextObject = PrevObject->Notify.Next[i];
 561                     AcpiUtUpdateRefCount (PrevObject, Action);
 562                     PrevObject = NextObject;
 563                 }
 564             }
 565             break;
 566 
 567         case ACPI_TYPE_PACKAGE:
 568             /*
 569              * We must update all the sub-objects of the package,
 570              * each of whom may have their own sub-objects.
 571              */
 572             for (i = 0; i < Object->Package.Count; i++)
 573             {
 574                 /*
 575                  * Null package elements are legal and can be simply
 576                  * ignored.
 577                  */
 578                 NextObject = Object->Package.Elements[i];
 579                 if (!NextObject)
 580                 {
 581                     continue;
 582                 }
 583 
 584                 switch (NextObject->Common.Type)
 585                 {
 586                 case ACPI_TYPE_INTEGER:
 587                 case ACPI_TYPE_STRING:
 588                 case ACPI_TYPE_BUFFER:
 589                     /*
 590                      * For these very simple sub-objects, we can just
 591                      * update the reference count here and continue.
 592                      * Greatly increases performance of this operation.
 593                      */
 594                     AcpiUtUpdateRefCount (NextObject, Action);
 595                     break;
 596 
 597                 default:
 598                     /*
 599                      * For complex sub-objects, push them onto the stack
 600                      * for later processing (this eliminates recursion.)
 601                      */
 602                     Status = AcpiUtCreateUpdateStateAndPush (
 603                                  NextObject, Action, &StateList);
 604                     if (ACPI_FAILURE (Status))
 605                     {
 606                         goto ErrorExit;
 607                     }
 608                     break;
 609                 }
 610             }
 611             NextObject = NULL;
 612             break;
 613 
 614         case ACPI_TYPE_BUFFER_FIELD:
 615 
 616             NextObject = Object->BufferField.BufferObj;
 617             break;
 618 
 619         case ACPI_TYPE_LOCAL_REGION_FIELD:
 620 
 621             NextObject = Object->Field.RegionObj;
 622             break;
 623 
 624         case ACPI_TYPE_LOCAL_BANK_FIELD:
 625 
 626             NextObject = Object->BankField.BankObj;
 627             Status = AcpiUtCreateUpdateStateAndPush (
 628                         Object->BankField.RegionObj, Action, &StateList);
 629             if (ACPI_FAILURE (Status))
 630             {
 631                 goto ErrorExit;
 632             }
 633             break;
 634 
 635         case ACPI_TYPE_LOCAL_INDEX_FIELD:
 636 
 637             NextObject = Object->IndexField.IndexObj;
 638             Status = AcpiUtCreateUpdateStateAndPush (
 639                         Object->IndexField.DataObj, Action, &StateList);
 640             if (ACPI_FAILURE (Status))
 641             {
 642                 goto ErrorExit;
 643             }
 644             break;
 645 
 646         case ACPI_TYPE_LOCAL_REFERENCE:
 647             /*
 648              * The target of an Index (a package, string, or buffer) or a named
 649              * reference must track changes to the ref count of the index or
 650              * target object.
 651              */
 652             if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
 653                 (Object->Reference.Class== ACPI_REFCLASS_NAME))
 654             {
 655                 NextObject = Object->Reference.Object;
 656             }
 657             break;
 658 
 659         case ACPI_TYPE_REGION:
 660         default:
 661 
 662             break; /* No subobjects for all other types */
 663         }
 664 
 665         /*
 666          * Now we can update the count in the main object. This can only
 667          * happen after we update the sub-objects in case this causes the
 668          * main object to be deleted.
 669          */
 670         AcpiUtUpdateRefCount (Object, Action);
 671         Object = NULL;
 672 
 673         /* Move on to the next object to be updated */
 674 
 675         if (NextObject)
 676         {
 677             Object = NextObject;
 678             NextObject = NULL;
 679         }
 680         else if (StateList)
 681         {
 682             State = AcpiUtPopGenericState (&StateList);
 683             Object = State->Update.Object;
 684             AcpiUtDeleteGenericState (State);
 685         }
 686     }
 687 
 688     return (AE_OK);
 689 
 690 
 691 ErrorExit:
 692 
 693     ACPI_EXCEPTION ((AE_INFO, Status,
 694         "Could not update object reference count"));
 695 
 696     /* Free any stacked Update State objects */
 697 
 698     while (StateList)
 699     {
 700         State = AcpiUtPopGenericState (&StateList);
 701         AcpiUtDeleteGenericState (State);
 702     }
 703 
 704     return (Status);
 705 }
 706 
 707 
 708 /*******************************************************************************
 709  *
 710  * FUNCTION:    AcpiUtAddReference
 711  *
 712  * PARAMETERS:  Object          - Object whose reference count is to be
 713  *                                incremented
 714  *
 715  * RETURN:      None
 716  *
 717  * DESCRIPTION: Add one reference to an ACPI object
 718  *
 719  ******************************************************************************/
 720 
 721 void
 722 AcpiUtAddReference (
 723     ACPI_OPERAND_OBJECT     *Object)
 724 {
 725 
 726     ACPI_FUNCTION_NAME (UtAddReference);
 727 
 728 
 729     /* Ensure that we have a valid object */
 730 
 731     if (!AcpiUtValidInternalObject (Object))
 732     {
 733         return;
 734     }
 735 
 736     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 737         "Obj %p Current Refs=%X [To Be Incremented]\n",
 738         Object, Object->Common.ReferenceCount));
 739 
 740     /* Increment the reference count */
 741 
 742     (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
 743     return;
 744 }
 745 
 746 
 747 /*******************************************************************************
 748  *
 749  * FUNCTION:    AcpiUtRemoveReference
 750  *
 751  * PARAMETERS:  Object         - Object whose ref count will be decremented
 752  *
 753  * RETURN:      None
 754  *
 755  * DESCRIPTION: Decrement the reference count of an ACPI internal object
 756  *
 757  ******************************************************************************/
 758 
 759 void
 760 AcpiUtRemoveReference (
 761     ACPI_OPERAND_OBJECT     *Object)
 762 {
 763 
 764     ACPI_FUNCTION_NAME (UtRemoveReference);
 765 
 766 
 767     /*
 768      * Allow a NULL pointer to be passed in, just ignore it. This saves
 769      * each caller from having to check. Also, ignore NS nodes.
 770      */
 771     if (!Object ||
 772         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
 773 
 774     {
 775         return;
 776     }
 777 
 778     /* Ensure that we have a valid object */
 779 
 780     if (!AcpiUtValidInternalObject (Object))
 781     {
 782         return;
 783     }
 784 
 785     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 786         "Obj %p Current Refs=%X [To Be Decremented]\n",
 787         Object, Object->Common.ReferenceCount));
 788 
 789     /*
 790      * Decrement the reference count, and only actually delete the object
 791      * if the reference count becomes 0. (Must also decrement the ref count
 792      * of all subobjects!)
 793      */
 794     (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
 795     return;
 796 }