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