[ACPICA]
[reactos.git] / reactos / drivers / bus / acpi / acpica / utilities / utdelete.c
1 /*******************************************************************************
2 *
3 * Module Name: utdelete - object deletion and reference count utilities
4 *
5 ******************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2015, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "acinterp.h"
119 #include "acnamesp.h"
120 #include "acevents.h"
121
122
123 #define _COMPONENT ACPI_UTILITIES
124 ACPI_MODULE_NAME ("utdelete")
125
126 /* Local prototypes */
127
128 static void
129 AcpiUtDeleteInternalObj (
130 ACPI_OPERAND_OBJECT *Object);
131
132 static void
133 AcpiUtUpdateRefCount (
134 ACPI_OPERAND_OBJECT *Object,
135 UINT32 Action);
136
137
138 /*******************************************************************************
139 *
140 * FUNCTION: AcpiUtDeleteInternalObj
141 *
142 * PARAMETERS: Object - Object to be deleted
143 *
144 * RETURN: None
145 *
146 * DESCRIPTION: Low level object deletion, after reference counts have been
147 * updated (All reference counts, including sub-objects!)
148 *
149 ******************************************************************************/
150
151 static void
152 AcpiUtDeleteInternalObj (
153 ACPI_OPERAND_OBJECT *Object)
154 {
155 void *ObjPointer = NULL;
156 ACPI_OPERAND_OBJECT *HandlerDesc;
157 ACPI_OPERAND_OBJECT *SecondDesc;
158 ACPI_OPERAND_OBJECT *NextDesc;
159 ACPI_OPERAND_OBJECT *StartDesc;
160 ACPI_OPERAND_OBJECT **LastObjPtr;
161
162
163 ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
164
165
166 if (!Object)
167 {
168 return_VOID;
169 }
170
171 /*
172 * Must delete or free any pointers within the object that are not
173 * actual ACPI objects (for example, a raw buffer pointer).
174 */
175 switch (Object->Common.Type)
176 {
177 case ACPI_TYPE_STRING:
178
179 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
180 Object, Object->String.Pointer));
181
182 /* Free the actual string buffer */
183
184 if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
185 {
186 /* But only if it is NOT a pointer into an ACPI table */
187
188 ObjPointer = Object->String.Pointer;
189 }
190 break;
191
192 case ACPI_TYPE_BUFFER:
193
194 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
195 Object, Object->Buffer.Pointer));
196
197 /* Free the actual buffer */
198
199 if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
200 {
201 /* But only if it is NOT a pointer into an ACPI table */
202
203 ObjPointer = Object->Buffer.Pointer;
204 }
205 break;
206
207 case ACPI_TYPE_PACKAGE:
208
209 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
210 Object->Package.Count));
211
212 /*
213 * Elements of the package are not handled here, they are deleted
214 * separately
215 */
216
217 /* Free the (variable length) element pointer array */
218
219 ObjPointer = Object->Package.Elements;
220 break;
221
222 /*
223 * These objects have a possible list of notify handlers.
224 * Device object also may have a GPE block.
225 */
226 case ACPI_TYPE_DEVICE:
227
228 if (Object->Device.GpeBlock)
229 {
230 (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
231 }
232
233 /*lint -fallthrough */
234
235 case ACPI_TYPE_PROCESSOR:
236 case ACPI_TYPE_THERMAL:
237
238 /* Walk the address handler list for this object */
239
240 HandlerDesc = Object->CommonNotify.Handler;
241 while (HandlerDesc)
242 {
243 NextDesc = HandlerDesc->AddressSpace.Next;
244 AcpiUtRemoveReference (HandlerDesc);
245 HandlerDesc = NextDesc;
246 }
247 break;
248
249 case ACPI_TYPE_MUTEX:
250
251 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
252 "***** Mutex %p, OS Mutex %p\n",
253 Object, Object->Mutex.OsMutex));
254
255 if (Object == AcpiGbl_GlobalLockMutex)
256 {
257 /* Global Lock has extra semaphore */
258
259 (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
260 AcpiGbl_GlobalLockSemaphore = NULL;
261
262 AcpiOsDeleteMutex (Object->Mutex.OsMutex);
263 AcpiGbl_GlobalLockMutex = NULL;
264 }
265 else
266 {
267 AcpiExUnlinkMutex (Object);
268 AcpiOsDeleteMutex (Object->Mutex.OsMutex);
269 }
270 break;
271
272 case ACPI_TYPE_EVENT:
273
274 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
275 "***** Event %p, OS Semaphore %p\n",
276 Object, Object->Event.OsSemaphore));
277
278 (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
279 Object->Event.OsSemaphore = NULL;
280 break;
281
282 case ACPI_TYPE_METHOD:
283
284 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
285 "***** Method %p\n", Object));
286
287 /* Delete the method mutex if it exists */
288
289 if (Object->Method.Mutex)
290 {
291 AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
292 AcpiUtDeleteObjectDesc (Object->Method.Mutex);
293 Object->Method.Mutex = NULL;
294 }
295 break;
296
297 case ACPI_TYPE_REGION:
298
299 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
300 "***** Region %p\n", Object));
301
302 /*
303 * Update AddressRange list. However, only permanent regions
304 * are installed in this list. (Not created within a method)
305 */
306 if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
307 {
308 AcpiUtRemoveAddressRange (Object->Region.SpaceId,
309 Object->Region.Node);
310 }
311
312 SecondDesc = AcpiNsGetSecondaryObject (Object);
313 if (SecondDesc)
314 {
315 /*
316 * Free the RegionContext if and only if the handler is one of the
317 * default handlers -- and therefore, we created the context object
318 * locally, it was not created by an external caller.
319 */
320 HandlerDesc = Object->Region.Handler;
321 if (HandlerDesc)
322 {
323 NextDesc = HandlerDesc->AddressSpace.RegionList;
324 StartDesc = NextDesc;
325 LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
326
327 /* Remove the region object from the handler list */
328
329 while (NextDesc)
330 {
331 if (NextDesc == Object)
332 {
333 *LastObjPtr = NextDesc->Region.Next;
334 break;
335 }
336
337 /* Walk the linked list of handlers */
338
339 LastObjPtr = &NextDesc->Region.Next;
340 NextDesc = NextDesc->Region.Next;
341
342 /* Prevent infinite loop if list is corrupted */
343
344 if (NextDesc == StartDesc)
345 {
346 ACPI_ERROR ((AE_INFO,
347 "Circular region list in address handler object %p",
348 HandlerDesc));
349 return_VOID;
350 }
351 }
352
353 if (HandlerDesc->AddressSpace.HandlerFlags &
354 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
355 {
356 /* Deactivate region and free region context */
357
358 if (HandlerDesc->AddressSpace.Setup)
359 {
360 (void) HandlerDesc->AddressSpace.Setup (Object,
361 ACPI_REGION_DEACTIVATE,
362 HandlerDesc->AddressSpace.Context,
363 &SecondDesc->Extra.RegionContext);
364 }
365 }
366
367 AcpiUtRemoveReference (HandlerDesc);
368 }
369
370 /* Now we can free the Extra object */
371
372 AcpiUtDeleteObjectDesc (SecondDesc);
373 }
374 break;
375
376 case ACPI_TYPE_BUFFER_FIELD:
377
378 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
379 "***** Buffer Field %p\n", Object));
380
381 SecondDesc = AcpiNsGetSecondaryObject (Object);
382 if (SecondDesc)
383 {
384 AcpiUtDeleteObjectDesc (SecondDesc);
385 }
386 break;
387
388 case ACPI_TYPE_LOCAL_BANK_FIELD:
389
390 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
391 "***** Bank Field %p\n", Object));
392
393 SecondDesc = AcpiNsGetSecondaryObject (Object);
394 if (SecondDesc)
395 {
396 AcpiUtDeleteObjectDesc (SecondDesc);
397 }
398 break;
399
400 default:
401
402 break;
403 }
404
405 /* Free any allocated memory (pointer within the object) found above */
406
407 if (ObjPointer)
408 {
409 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
410 ObjPointer));
411 ACPI_FREE (ObjPointer);
412 }
413
414 /* Now the object can be safely deleted */
415
416 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
417 Object, AcpiUtGetObjectTypeName (Object)));
418
419 AcpiUtDeleteObjectDesc (Object);
420 return_VOID;
421 }
422
423
424 /*******************************************************************************
425 *
426 * FUNCTION: AcpiUtDeleteInternalObjectList
427 *
428 * PARAMETERS: ObjList - Pointer to the list to be deleted
429 *
430 * RETURN: None
431 *
432 * DESCRIPTION: This function deletes an internal object list, including both
433 * simple objects and package objects
434 *
435 ******************************************************************************/
436
437 void
438 AcpiUtDeleteInternalObjectList (
439 ACPI_OPERAND_OBJECT **ObjList)
440 {
441 ACPI_OPERAND_OBJECT **InternalObj;
442
443
444 ACPI_FUNCTION_ENTRY ();
445
446
447 /* Walk the null-terminated internal list */
448
449 for (InternalObj = ObjList; *InternalObj; InternalObj++)
450 {
451 AcpiUtRemoveReference (*InternalObj);
452 }
453
454 /* Free the combined parameter pointer list and object array */
455
456 ACPI_FREE (ObjList);
457 return;
458 }
459
460
461 /*******************************************************************************
462 *
463 * FUNCTION: AcpiUtUpdateRefCount
464 *
465 * PARAMETERS: Object - Object whose ref count is to be updated
466 * Action - What to do (REF_INCREMENT or REF_DECREMENT)
467 *
468 * RETURN: None. Sets new reference count within the object
469 *
470 * DESCRIPTION: Modify the reference count for an internal acpi object
471 *
472 ******************************************************************************/
473
474 static void
475 AcpiUtUpdateRefCount (
476 ACPI_OPERAND_OBJECT *Object,
477 UINT32 Action)
478 {
479 UINT16 OriginalCount;
480 UINT16 NewCount = 0;
481 ACPI_CPU_FLAGS LockFlags;
482
483
484 ACPI_FUNCTION_NAME (UtUpdateRefCount);
485
486
487 if (!Object)
488 {
489 return;
490 }
491
492 /*
493 * Always get the reference count lock. Note: Interpreter and/or
494 * Namespace is not always locked when this function is called.
495 */
496 LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
497 OriginalCount = Object->Common.ReferenceCount;
498
499 /* Perform the reference count action (increment, decrement) */
500
501 switch (Action)
502 {
503 case REF_INCREMENT:
504
505 NewCount = OriginalCount + 1;
506 Object->Common.ReferenceCount = NewCount;
507 AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
508
509 /* The current reference count should never be zero here */
510
511 if (!OriginalCount)
512 {
513 ACPI_WARNING ((AE_INFO,
514 "Obj %p, Reference Count was zero before increment\n",
515 Object));
516 }
517
518 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
519 "Obj %p Type %.2X Refs %.2X [Incremented]\n",
520 Object, Object->Common.Type, NewCount));
521 break;
522
523 case REF_DECREMENT:
524
525 /* The current reference count must be non-zero */
526
527 if (OriginalCount)
528 {
529 NewCount = OriginalCount - 1;
530 Object->Common.ReferenceCount = NewCount;
531 }
532
533 AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
534
535 if (!OriginalCount)
536 {
537 ACPI_WARNING ((AE_INFO,
538 "Obj %p, Reference Count is already zero, cannot decrement\n",
539 Object));
540 }
541
542 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
543 "Obj %p Type %.2X Refs %.2X [Decremented]\n",
544 Object, Object->Common.Type, NewCount));
545
546 /* Actually delete the object on a reference count of zero */
547
548 if (NewCount == 0)
549 {
550 AcpiUtDeleteInternalObj (Object);
551 }
552 break;
553
554 default:
555
556 AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
557 ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
558 Action));
559 return;
560 }
561
562 /*
563 * Sanity check the reference count, for debug purposes only.
564 * (A deleted object will have a huge reference count)
565 */
566 if (NewCount > ACPI_MAX_REFERENCE_COUNT)
567 {
568 ACPI_WARNING ((AE_INFO,
569 "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
570 NewCount, Object, Object->Common.Type));
571 }
572 }
573
574
575 /*******************************************************************************
576 *
577 * FUNCTION: AcpiUtUpdateObjectReference
578 *
579 * PARAMETERS: Object - Increment ref count for this object
580 * and all sub-objects
581 * Action - Either REF_INCREMENT or REF_DECREMENT
582 *
583 * RETURN: Status
584 *
585 * DESCRIPTION: Increment the object reference count
586 *
587 * Object references are incremented when:
588 * 1) An object is attached to a Node (namespace object)
589 * 2) An object is copied (all subobjects must be incremented)
590 *
591 * Object references are decremented when:
592 * 1) An object is detached from an Node
593 *
594 ******************************************************************************/
595
596 ACPI_STATUS
597 AcpiUtUpdateObjectReference (
598 ACPI_OPERAND_OBJECT *Object,
599 UINT16 Action)
600 {
601 ACPI_STATUS Status = AE_OK;
602 ACPI_GENERIC_STATE *StateList = NULL;
603 ACPI_OPERAND_OBJECT *NextObject = NULL;
604 ACPI_OPERAND_OBJECT *PrevObject;
605 ACPI_GENERIC_STATE *State;
606 UINT32 i;
607
608
609 ACPI_FUNCTION_NAME (UtUpdateObjectReference);
610
611
612 while (Object)
613 {
614 /* Make sure that this isn't a namespace handle */
615
616 if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
617 {
618 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
619 "Object %p is NS handle\n", Object));
620 return (AE_OK);
621 }
622
623 /*
624 * All sub-objects must have their reference count incremented also.
625 * Different object types have different subobjects.
626 */
627 switch (Object->Common.Type)
628 {
629 case ACPI_TYPE_DEVICE:
630 case ACPI_TYPE_PROCESSOR:
631 case ACPI_TYPE_POWER:
632 case ACPI_TYPE_THERMAL:
633 /*
634 * Update the notify objects for these types (if present)
635 * Two lists, system and device notify handlers.
636 */
637 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
638 {
639 PrevObject = Object->CommonNotify.NotifyList[i];
640 while (PrevObject)
641 {
642 NextObject = PrevObject->Notify.Next[i];
643 AcpiUtUpdateRefCount (PrevObject, Action);
644 PrevObject = NextObject;
645 }
646 }
647 break;
648
649 case ACPI_TYPE_PACKAGE:
650 /*
651 * We must update all the sub-objects of the package,
652 * each of whom may have their own sub-objects.
653 */
654 for (i = 0; i < Object->Package.Count; i++)
655 {
656 /*
657 * Null package elements are legal and can be simply
658 * ignored.
659 */
660 NextObject = Object->Package.Elements[i];
661 if (!NextObject)
662 {
663 continue;
664 }
665
666 switch (NextObject->Common.Type)
667 {
668 case ACPI_TYPE_INTEGER:
669 case ACPI_TYPE_STRING:
670 case ACPI_TYPE_BUFFER:
671 /*
672 * For these very simple sub-objects, we can just
673 * update the reference count here and continue.
674 * Greatly increases performance of this operation.
675 */
676 AcpiUtUpdateRefCount (NextObject, Action);
677 break;
678
679 default:
680 /*
681 * For complex sub-objects, push them onto the stack
682 * for later processing (this eliminates recursion.)
683 */
684 Status = AcpiUtCreateUpdateStateAndPush (
685 NextObject, Action, &StateList);
686 if (ACPI_FAILURE (Status))
687 {
688 goto ErrorExit;
689 }
690 break;
691 }
692 }
693 NextObject = NULL;
694 break;
695
696 case ACPI_TYPE_BUFFER_FIELD:
697
698 NextObject = Object->BufferField.BufferObj;
699 break;
700
701 case ACPI_TYPE_LOCAL_REGION_FIELD:
702
703 NextObject = Object->Field.RegionObj;
704 break;
705
706 case ACPI_TYPE_LOCAL_BANK_FIELD:
707
708 NextObject = Object->BankField.BankObj;
709 Status = AcpiUtCreateUpdateStateAndPush (
710 Object->BankField.RegionObj, Action, &StateList);
711 if (ACPI_FAILURE (Status))
712 {
713 goto ErrorExit;
714 }
715 break;
716
717 case ACPI_TYPE_LOCAL_INDEX_FIELD:
718
719 NextObject = Object->IndexField.IndexObj;
720 Status = AcpiUtCreateUpdateStateAndPush (
721 Object->IndexField.DataObj, Action, &StateList);
722 if (ACPI_FAILURE (Status))
723 {
724 goto ErrorExit;
725 }
726 break;
727
728 case ACPI_TYPE_LOCAL_REFERENCE:
729 /*
730 * The target of an Index (a package, string, or buffer) or a named
731 * reference must track changes to the ref count of the index or
732 * target object.
733 */
734 if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
735 (Object->Reference.Class== ACPI_REFCLASS_NAME))
736 {
737 NextObject = Object->Reference.Object;
738 }
739 break;
740
741 case ACPI_TYPE_REGION:
742 default:
743
744 break; /* No subobjects for all other types */
745 }
746
747 /*
748 * Now we can update the count in the main object. This can only
749 * happen after we update the sub-objects in case this causes the
750 * main object to be deleted.
751 */
752 AcpiUtUpdateRefCount (Object, Action);
753 Object = NULL;
754
755 /* Move on to the next object to be updated */
756
757 if (NextObject)
758 {
759 Object = NextObject;
760 NextObject = NULL;
761 }
762 else if (StateList)
763 {
764 State = AcpiUtPopGenericState (&StateList);
765 Object = State->Update.Object;
766 AcpiUtDeleteGenericState (State);
767 }
768 }
769
770 return (AE_OK);
771
772
773 ErrorExit:
774
775 ACPI_EXCEPTION ((AE_INFO, Status,
776 "Could not update object reference count"));
777
778 /* Free any stacked Update State objects */
779
780 while (StateList)
781 {
782 State = AcpiUtPopGenericState (&StateList);
783 AcpiUtDeleteGenericState (State);
784 }
785
786 return (Status);
787 }
788
789
790 /*******************************************************************************
791 *
792 * FUNCTION: AcpiUtAddReference
793 *
794 * PARAMETERS: Object - Object whose reference count is to be
795 * incremented
796 *
797 * RETURN: None
798 *
799 * DESCRIPTION: Add one reference to an ACPI object
800 *
801 ******************************************************************************/
802
803 void
804 AcpiUtAddReference (
805 ACPI_OPERAND_OBJECT *Object)
806 {
807
808 ACPI_FUNCTION_NAME (UtAddReference);
809
810
811 /* Ensure that we have a valid object */
812
813 if (!AcpiUtValidInternalObject (Object))
814 {
815 return;
816 }
817
818 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
819 "Obj %p Current Refs=%X [To Be Incremented]\n",
820 Object, Object->Common.ReferenceCount));
821
822 /* Increment the reference count */
823
824 (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
825 return;
826 }
827
828
829 /*******************************************************************************
830 *
831 * FUNCTION: AcpiUtRemoveReference
832 *
833 * PARAMETERS: Object - Object whose ref count will be decremented
834 *
835 * RETURN: None
836 *
837 * DESCRIPTION: Decrement the reference count of an ACPI internal object
838 *
839 ******************************************************************************/
840
841 void
842 AcpiUtRemoveReference (
843 ACPI_OPERAND_OBJECT *Object)
844 {
845
846 ACPI_FUNCTION_NAME (UtRemoveReference);
847
848
849 /*
850 * Allow a NULL pointer to be passed in, just ignore it. This saves
851 * each caller from having to check. Also, ignore NS nodes.
852 */
853 if (!Object ||
854 (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
855
856 {
857 return;
858 }
859
860 /* Ensure that we have a valid object */
861
862 if (!AcpiUtValidInternalObject (Object))
863 {
864 return;
865 }
866
867 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
868 "Obj %p Current Refs=%X [To Be Decremented]\n",
869 Object, Object->Common.ReferenceCount));
870
871 /*
872 * Decrement the reference count, and only actually delete the object
873 * if the reference count becomes 0. (Must also decrement the ref count
874 * of all subobjects!)
875 */
876 (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
877 return;
878 }