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