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