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