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