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