1 /*******************************************************************************
   2  *
   3  * Module Name: utdelete - object deletion and reference count utilities
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 
 122     case ACPI_TYPE_BUFFER:
 123 
 124         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
 125             Object, Object->Buffer.Pointer));
 126 
 127         /* Free the actual buffer */
 128 
 129         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
 130         {
 131             /* But only if it is NOT a pointer into an ACPI table */
 132 
 133             ObjPointer = Object->Buffer.Pointer;
 134         }
 135         break;
 136 
 137 
 138     case ACPI_TYPE_PACKAGE:
 139 
 140         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
 141             Object->Package.Count));
 142 
 143         /*
 144          * Elements of the package are not handled here, they are deleted
 145          * separately
 146          */
 147 
 148         /* Free the (variable length) element pointer array */
 149 
 150         ObjPointer = Object->Package.Elements;
 151         break;
 152 
 153 
 154     /*
 155      * These objects have a possible list of notify handlers.
 156      * Device object also may have a GPE block.
 157      */
 158     case ACPI_TYPE_DEVICE:
 159 
 160         if (Object->Device.GpeBlock)
 161         {
 162             (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
 163         }
 164 
 165         /*lint -fallthrough */
 166 
 167     case ACPI_TYPE_PROCESSOR:
 168     case ACPI_TYPE_THERMAL:
 169 
 170         /* Walk the notify handler list for this object */
 171 
 172         HandlerDesc = Object->CommonNotify.Handler;
 173         while (HandlerDesc)
 174         {
 175             NextDesc = HandlerDesc->AddressSpace.Next;
 176             AcpiUtRemoveReference (HandlerDesc);
 177             HandlerDesc = NextDesc;
 178         }
 179         break;
 180 
 181 
 182     case ACPI_TYPE_MUTEX:
 183 
 184         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 185             "***** Mutex %p, OS Mutex %p\n",
 186             Object, Object->Mutex.OsMutex));
 187 
 188         if (Object == AcpiGbl_GlobalLockMutex)
 189         {
 190             /* Global Lock has extra semaphore */
 191 
 192             (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
 193             AcpiGbl_GlobalLockSemaphore = NULL;
 194 
 195             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
 196             AcpiGbl_GlobalLockMutex = NULL;
 197         }
 198         else
 199         {
 200             AcpiExUnlinkMutex (Object);
 201             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
 202         }
 203         break;
 204 
 205 
 206     case ACPI_TYPE_EVENT:
 207 
 208         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 209             "***** Event %p, OS Semaphore %p\n",
 210             Object, Object->Event.OsSemaphore));
 211 
 212         (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
 213         Object->Event.OsSemaphore = NULL;
 214         break;
 215 
 216 
 217     case ACPI_TYPE_METHOD:
 218 
 219         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 220             "***** Method %p\n", Object));
 221 
 222         /* Delete the method mutex if it exists */
 223 
 224         if (Object->Method.Mutex)
 225         {
 226             AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
 227             AcpiUtDeleteObjectDesc (Object->Method.Mutex);
 228             Object->Method.Mutex = NULL;
 229         }
 230         break;
 231 
 232 
 233     case ACPI_TYPE_REGION:
 234 
 235         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 236             "***** Region %p\n", Object));
 237 
 238         SecondDesc = AcpiNsGetSecondaryObject (Object);
 239         if (SecondDesc)
 240         {
 241             /*
 242              * Free the RegionContext if and only if the handler is one of the
 243              * default handlers -- and therefore, we created the context object
 244              * locally, it was not created by an external caller.
 245              */
 246             HandlerDesc = Object->Region.Handler;
 247             if (HandlerDesc)
 248             {
 249                 NextDesc = HandlerDesc->AddressSpace.RegionList;
 250                 LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
 251 
 252                 /* Remove the region object from the handler's list */
 253 
 254                 while (NextDesc)
 255                 {
 256                     if (NextDesc == Object)
 257                     {
 258                         *LastObjPtr = NextDesc->Region.Next;
 259                         break;
 260                     }
 261 
 262                     /* Walk the linked list of handler */
 263 
 264                     LastObjPtr = &NextDesc->Region.Next;
 265                     NextDesc = NextDesc->Region.Next;
 266                 }
 267 
 268                 if (HandlerDesc->AddressSpace.HandlerFlags &
 269                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
 270                 {
 271                     /* Deactivate region and free region context */
 272 
 273                     if (HandlerDesc->AddressSpace.Setup)
 274                     {
 275                         (void) HandlerDesc->AddressSpace.Setup (Object,
 276                             ACPI_REGION_DEACTIVATE,
 277                             HandlerDesc->AddressSpace.Context,
 278                             &SecondDesc->Extra.RegionContext);
 279                     }
 280                 }
 281 
 282                 AcpiUtRemoveReference (HandlerDesc);
 283             }
 284 
 285             /* Now we can free the Extra object */
 286 
 287             AcpiUtDeleteObjectDesc (SecondDesc);
 288         }
 289         break;
 290 
 291 
 292     case ACPI_TYPE_BUFFER_FIELD:
 293 
 294         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 295             "***** Buffer Field %p\n", Object));
 296 
 297         SecondDesc = AcpiNsGetSecondaryObject (Object);
 298         if (SecondDesc)
 299         {
 300             AcpiUtDeleteObjectDesc (SecondDesc);
 301         }
 302         break;
 303 
 304 
 305     case ACPI_TYPE_LOCAL_BANK_FIELD:
 306 
 307         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 308             "***** Bank Field %p\n", Object));
 309 
 310         SecondDesc = AcpiNsGetSecondaryObject (Object);
 311         if (SecondDesc)
 312         {
 313             AcpiUtDeleteObjectDesc (SecondDesc);
 314         }
 315         break;
 316 
 317 
 318     default:
 319         break;
 320     }
 321 
 322     /* Free any allocated memory (pointer within the object) found above */
 323 
 324     if (ObjPointer)
 325     {
 326         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
 327             ObjPointer));
 328         ACPI_FREE (ObjPointer);
 329     }
 330 
 331     /* Now the object can be safely deleted */
 332 
 333     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
 334         Object, AcpiUtGetObjectTypeName (Object)));
 335 
 336     AcpiUtDeleteObjectDesc (Object);
 337     return_VOID;
 338 }
 339 
 340 
 341 /*******************************************************************************
 342  *
 343  * FUNCTION:    AcpiUtDeleteInternalObjectList
 344  *
 345  * PARAMETERS:  ObjList         - Pointer to the list to be deleted
 346  *
 347  * RETURN:      None
 348  *
 349  * DESCRIPTION: This function deletes an internal object list, including both
 350  *              simple objects and package objects
 351  *
 352  ******************************************************************************/
 353 
 354 void
 355 AcpiUtDeleteInternalObjectList (
 356     ACPI_OPERAND_OBJECT     **ObjList)
 357 {
 358     ACPI_OPERAND_OBJECT     **InternalObj;
 359 
 360 
 361     ACPI_FUNCTION_TRACE (UtDeleteInternalObjectList);
 362 
 363 
 364     /* Walk the null-terminated internal list */
 365 
 366     for (InternalObj = ObjList; *InternalObj; InternalObj++)
 367     {
 368         AcpiUtRemoveReference (*InternalObj);
 369     }
 370 
 371     /* Free the combined parameter pointer list and object array */
 372 
 373     ACPI_FREE (ObjList);
 374     return_VOID;
 375 }
 376 
 377 
 378 /*******************************************************************************
 379  *
 380  * FUNCTION:    AcpiUtUpdateRefCount
 381  *
 382  * PARAMETERS:  Object          - Object whose ref count is to be updated
 383  *              Action          - What to do
 384  *
 385  * RETURN:      New ref count
 386  *
 387  * DESCRIPTION: Modify the ref count and return it.
 388  *
 389  ******************************************************************************/
 390 
 391 static void
 392 AcpiUtUpdateRefCount (
 393     ACPI_OPERAND_OBJECT     *Object,
 394     UINT32                  Action)
 395 {
 396     UINT16                  Count;
 397     UINT16                  NewCount;
 398 
 399 
 400     ACPI_FUNCTION_NAME (UtUpdateRefCount);
 401 
 402 
 403     if (!Object)
 404     {
 405         return;
 406     }
 407 
 408     Count = Object->Common.ReferenceCount;
 409     NewCount = Count;
 410 
 411     /*
 412      * Perform the reference count action (increment, decrement, force delete)
 413      */
 414     switch (Action)
 415     {
 416     case REF_INCREMENT:
 417 
 418         NewCount++;
 419         Object->Common.ReferenceCount = NewCount;
 420 
 421         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 422             "Obj %p Refs=%X, [Incremented]\n",
 423             Object, NewCount));
 424         break;
 425 
 426     case REF_DECREMENT:
 427 
 428         if (Count < 1)
 429         {
 430             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 431                 "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
 432                 Object, NewCount));
 433 
 434             NewCount = 0;
 435         }
 436         else
 437         {
 438             NewCount--;
 439 
 440             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 441                 "Obj %p Refs=%X, [Decremented]\n",
 442                 Object, NewCount));
 443         }
 444 
 445         if (Object->Common.Type == ACPI_TYPE_METHOD)
 446         {
 447             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 448                 "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount));
 449         }
 450 
 451         Object->Common.ReferenceCount = NewCount;
 452         if (NewCount == 0)
 453         {
 454             AcpiUtDeleteInternalObj (Object);
 455         }
 456         break;
 457 
 458     case REF_FORCE_DELETE:
 459 
 460         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 461             "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count));
 462 
 463         NewCount = 0;
 464         Object->Common.ReferenceCount = NewCount;
 465         AcpiUtDeleteInternalObj (Object);
 466         break;
 467 
 468     default:
 469 
 470         ACPI_ERROR ((AE_INFO, "Unknown action (0x%X)", Action));
 471         break;
 472     }
 473 
 474     /*
 475      * Sanity check the reference count, for debug purposes only.
 476      * (A deleted object will have a huge reference count)
 477      */
 478     if (Count > ACPI_MAX_REFERENCE_COUNT)
 479     {
 480         ACPI_WARNING ((AE_INFO,
 481             "Large Reference Count (0x%X) in object %p", Count, Object));
 482     }
 483 }
 484 
 485 
 486 /*******************************************************************************
 487  *
 488  * FUNCTION:    AcpiUtUpdateObjectReference
 489  *
 490  * PARAMETERS:  Object              - Increment ref count for this object
 491  *                                    and all sub-objects
 492  *              Action              - Either REF_INCREMENT or REF_DECREMENT or
 493  *                                    REF_FORCE_DELETE
 494  *
 495  * RETURN:      Status
 496  *
 497  * DESCRIPTION: Increment the object reference count
 498  *
 499  * Object references are incremented when:
 500  * 1) An object is attached to a Node (namespace object)
 501  * 2) An object is copied (all subobjects must be incremented)
 502  *
 503  * Object references are decremented when:
 504  * 1) An object is detached from an Node
 505  *
 506  ******************************************************************************/
 507 
 508 ACPI_STATUS
 509 AcpiUtUpdateObjectReference (
 510     ACPI_OPERAND_OBJECT     *Object,
 511     UINT16                  Action)
 512 {
 513     ACPI_STATUS             Status = AE_OK;
 514     ACPI_GENERIC_STATE      *StateList = NULL;
 515     ACPI_OPERAND_OBJECT     *NextObject = NULL;
 516     ACPI_GENERIC_STATE      *State;
 517     UINT32                  i;
 518 
 519 
 520     ACPI_FUNCTION_TRACE_PTR (UtUpdateObjectReference, Object);
 521 
 522 
 523     while (Object)
 524     {
 525         /* Make sure that this isn't a namespace handle */
 526 
 527         if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
 528         {
 529             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 530                 "Object %p is NS handle\n", Object));
 531             return_ACPI_STATUS (AE_OK);
 532         }
 533 
 534         /*
 535          * All sub-objects must have their reference count incremented also.
 536          * Different object types have different subobjects.
 537          */
 538         switch (Object->Common.Type)
 539         {
 540         case ACPI_TYPE_DEVICE:
 541         case ACPI_TYPE_PROCESSOR:
 542         case ACPI_TYPE_POWER:
 543         case ACPI_TYPE_THERMAL:
 544 
 545             /* Update the notify objects for these types (if present) */
 546 
 547             AcpiUtUpdateRefCount (Object->CommonNotify.SystemNotify, Action);
 548             AcpiUtUpdateRefCount (Object->CommonNotify.DeviceNotify, Action);
 549             break;
 550 
 551         case ACPI_TYPE_PACKAGE:
 552             /*
 553              * We must update all the sub-objects of the package,
 554              * each of whom may have their own sub-objects.
 555              */
 556             for (i = 0; i < Object->Package.Count; i++)
 557             {
 558                 /*
 559                  * Push each element onto the stack for later processing.
 560                  * Note: There can be null elements within the package,
 561                  * these are simply ignored
 562                  */
 563                 Status = AcpiUtCreateUpdateStateAndPush (
 564                             Object->Package.Elements[i], Action, &StateList);
 565                 if (ACPI_FAILURE (Status))
 566                 {
 567                     goto ErrorExit;
 568                 }
 569             }
 570             break;
 571 
 572         case ACPI_TYPE_BUFFER_FIELD:
 573 
 574             NextObject = Object->BufferField.BufferObj;
 575             break;
 576 
 577         case ACPI_TYPE_LOCAL_REGION_FIELD:
 578 
 579             NextObject = Object->Field.RegionObj;
 580             break;
 581 
 582         case ACPI_TYPE_LOCAL_BANK_FIELD:
 583 
 584             NextObject = Object->BankField.BankObj;
 585             Status = AcpiUtCreateUpdateStateAndPush (
 586                         Object->BankField.RegionObj, Action, &StateList);
 587             if (ACPI_FAILURE (Status))
 588             {
 589                 goto ErrorExit;
 590             }
 591             break;
 592 
 593         case ACPI_TYPE_LOCAL_INDEX_FIELD:
 594 
 595             NextObject = Object->IndexField.IndexObj;
 596             Status = AcpiUtCreateUpdateStateAndPush (
 597                         Object->IndexField.DataObj, Action, &StateList);
 598             if (ACPI_FAILURE (Status))
 599             {
 600                 goto ErrorExit;
 601             }
 602             break;
 603 
 604         case ACPI_TYPE_LOCAL_REFERENCE:
 605             /*
 606              * The target of an Index (a package, string, or buffer) or a named
 607              * reference must track changes to the ref count of the index or
 608              * target object.
 609              */
 610             if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
 611                 (Object->Reference.Class== ACPI_REFCLASS_NAME))
 612             {
 613                 NextObject = Object->Reference.Object;
 614             }
 615             break;
 616 
 617         case ACPI_TYPE_REGION:
 618         default:
 619             break; /* No subobjects for all other types */
 620         }
 621 
 622         /*
 623          * Now we can update the count in the main object. This can only
 624          * happen after we update the sub-objects in case this causes the
 625          * main object to be deleted.
 626          */
 627         AcpiUtUpdateRefCount (Object, Action);
 628         Object = NULL;
 629 
 630         /* Move on to the next object to be updated */
 631 
 632         if (NextObject)
 633         {
 634             Object = NextObject;
 635             NextObject = NULL;
 636         }
 637         else if (StateList)
 638         {
 639             State = AcpiUtPopGenericState (&StateList);
 640             Object = State->Update.Object;
 641             AcpiUtDeleteGenericState (State);
 642         }
 643     }
 644 
 645     return_ACPI_STATUS (AE_OK);
 646 
 647 
 648 ErrorExit:
 649 
 650     ACPI_EXCEPTION ((AE_INFO, Status,
 651         "Could not update object reference count"));
 652 
 653     /* Free any stacked Update State objects */
 654 
 655     while (StateList)
 656     {
 657         State = AcpiUtPopGenericState (&StateList);
 658         AcpiUtDeleteGenericState (State);
 659     }
 660 
 661     return_ACPI_STATUS (Status);
 662 }
 663 
 664 
 665 /*******************************************************************************
 666  *
 667  * FUNCTION:    AcpiUtAddReference
 668  *
 669  * PARAMETERS:  Object          - Object whose reference count is to be
 670  *                                incremented
 671  *
 672  * RETURN:      None
 673  *
 674  * DESCRIPTION: Add one reference to an ACPI object
 675  *
 676  ******************************************************************************/
 677 
 678 void
 679 AcpiUtAddReference (
 680     ACPI_OPERAND_OBJECT     *Object)
 681 {
 682 
 683     ACPI_FUNCTION_TRACE_PTR (UtAddReference, Object);
 684 
 685 
 686     /* Ensure that we have a valid object */
 687 
 688     if (!AcpiUtValidInternalObject (Object))
 689     {
 690         return_VOID;
 691     }
 692 
 693     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 694         "Obj %p Current Refs=%X [To Be Incremented]\n",
 695         Object, Object->Common.ReferenceCount));
 696 
 697     /* Increment the reference count */
 698 
 699     (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
 700     return_VOID;
 701 }
 702 
 703 
 704 /*******************************************************************************
 705  *
 706  * FUNCTION:    AcpiUtRemoveReference
 707  *
 708  * PARAMETERS:  Object         - Object whose ref count will be decremented
 709  *
 710  * RETURN:      None
 711  *
 712  * DESCRIPTION: Decrement the reference count of an ACPI internal object
 713  *
 714  ******************************************************************************/
 715 
 716 void
 717 AcpiUtRemoveReference (
 718     ACPI_OPERAND_OBJECT     *Object)
 719 {
 720 
 721     ACPI_FUNCTION_TRACE_PTR (UtRemoveReference, Object);
 722 
 723 
 724     /*
 725      * Allow a NULL pointer to be passed in, just ignore it. This saves
 726      * each caller from having to check. Also, ignore NS nodes.
 727      *
 728      */
 729     if (!Object ||
 730         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
 731 
 732     {
 733         return_VOID;
 734     }
 735 
 736     /* Ensure that we have a valid object */
 737 
 738     if (!AcpiUtValidInternalObject (Object))
 739     {
 740         return_VOID;
 741     }
 742 
 743     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
 744         "Obj %p Current Refs=%X [To Be Decremented]\n",
 745         Object, Object->Common.ReferenceCount));
 746 
 747     /*
 748      * Decrement the reference count, and only actually delete the object
 749      * if the reference count becomes 0. (Must also decrement the ref count
 750      * of all subobjects!)
 751      */
 752     (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
 753     return_VOID;
 754 }
 755 
 756