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