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