Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/utilities/utdelete.c
48406 views
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 - 2025, 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
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acinterp.h>
155
#include <contrib/dev/acpica/include/acnamesp.h>
156
#include <contrib/dev/acpica/include/acevents.h>
157
158
159
#define _COMPONENT ACPI_UTILITIES
160
ACPI_MODULE_NAME ("utdelete")
161
162
/* Local prototypes */
163
164
static void
165
AcpiUtDeleteInternalObj (
166
ACPI_OPERAND_OBJECT *Object);
167
168
static void
169
AcpiUtUpdateRefCount (
170
ACPI_OPERAND_OBJECT *Object,
171
UINT32 Action);
172
173
174
/*******************************************************************************
175
*
176
* FUNCTION: AcpiUtDeleteInternalObj
177
*
178
* PARAMETERS: Object - Object to be deleted
179
*
180
* RETURN: None
181
*
182
* DESCRIPTION: Low level object deletion, after reference counts have been
183
* updated (All reference counts, including sub-objects!)
184
*
185
******************************************************************************/
186
187
static void
188
AcpiUtDeleteInternalObj (
189
ACPI_OPERAND_OBJECT *Object)
190
{
191
void *ObjPointer = NULL;
192
ACPI_OPERAND_OBJECT *HandlerDesc;
193
ACPI_OPERAND_OBJECT *SecondDesc;
194
ACPI_OPERAND_OBJECT *NextDesc;
195
ACPI_OPERAND_OBJECT *StartDesc;
196
ACPI_OPERAND_OBJECT **LastObjPtr;
197
198
199
ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
200
201
202
if (!Object)
203
{
204
return_VOID;
205
}
206
207
/*
208
* Must delete or free any pointers within the object that are not
209
* actual ACPI objects (for example, a raw buffer pointer).
210
*/
211
switch (Object->Common.Type)
212
{
213
case ACPI_TYPE_STRING:
214
215
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
216
Object, Object->String.Pointer));
217
218
/* Free the actual string buffer */
219
220
if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
221
{
222
/* But only if it is NOT a pointer into an ACPI table */
223
224
ObjPointer = Object->String.Pointer;
225
}
226
break;
227
228
case ACPI_TYPE_BUFFER:
229
230
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
231
Object, Object->Buffer.Pointer));
232
233
/* Free the actual buffer */
234
235
if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
236
{
237
/* But only if it is NOT a pointer into an ACPI table */
238
239
ObjPointer = Object->Buffer.Pointer;
240
}
241
break;
242
243
case ACPI_TYPE_PACKAGE:
244
245
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
246
Object->Package.Count));
247
248
/*
249
* Elements of the package are not handled here, they are deleted
250
* separately
251
*/
252
253
/* Free the (variable length) element pointer array */
254
255
ObjPointer = Object->Package.Elements;
256
break;
257
258
/*
259
* These objects have a possible list of notify handlers.
260
* Device object also may have a GPE block.
261
*/
262
case ACPI_TYPE_DEVICE:
263
264
if (Object->Device.GpeBlock)
265
{
266
(void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
267
}
268
269
ACPI_FALLTHROUGH;
270
271
case ACPI_TYPE_PROCESSOR:
272
case ACPI_TYPE_THERMAL:
273
274
/* Walk the address handler list for this object */
275
276
HandlerDesc = Object->CommonNotify.Handler;
277
while (HandlerDesc)
278
{
279
NextDesc = HandlerDesc->AddressSpace.Next;
280
AcpiUtRemoveReference (HandlerDesc);
281
HandlerDesc = NextDesc;
282
}
283
break;
284
285
case ACPI_TYPE_MUTEX:
286
287
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
288
"***** Mutex %p, OS Mutex %p\n",
289
Object, Object->Mutex.OsMutex));
290
291
if (Object == AcpiGbl_GlobalLockMutex)
292
{
293
/* Global Lock has extra semaphore */
294
295
(void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
296
AcpiGbl_GlobalLockSemaphore = ACPI_SEMAPHORE_NULL;
297
298
AcpiOsDeleteMutex (Object->Mutex.OsMutex);
299
AcpiGbl_GlobalLockMutex = NULL;
300
}
301
else
302
{
303
AcpiExUnlinkMutex (Object);
304
AcpiOsDeleteMutex (Object->Mutex.OsMutex);
305
}
306
break;
307
308
case ACPI_TYPE_EVENT:
309
310
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
311
"***** Event %p, OS Semaphore %p\n",
312
Object, Object->Event.OsSemaphore));
313
314
(void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
315
Object->Event.OsSemaphore = ACPI_SEMAPHORE_NULL;
316
break;
317
318
case ACPI_TYPE_METHOD:
319
320
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
321
"***** Method %p\n", Object));
322
323
/* Delete the method mutex if it exists */
324
325
if (Object->Method.Mutex)
326
{
327
AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
328
AcpiUtDeleteObjectDesc (Object->Method.Mutex);
329
Object->Method.Mutex = NULL;
330
}
331
332
if (Object->Method.Node)
333
{
334
Object->Method.Node = NULL;
335
}
336
break;
337
338
case ACPI_TYPE_REGION:
339
340
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
341
"***** Region %p\n", Object));
342
343
/*
344
* Update AddressRange list. However, only permanent regions
345
* are installed in this list. (Not created within a method)
346
*/
347
if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
348
{
349
AcpiUtRemoveAddressRange (Object->Region.SpaceId,
350
Object->Region.Node);
351
}
352
353
SecondDesc = AcpiNsGetSecondaryObject (Object);
354
if (SecondDesc)
355
{
356
/*
357
* Free the RegionContext if and only if the handler is one of the
358
* default handlers -- and therefore, we created the context object
359
* locally, it was not created by an external caller.
360
*/
361
HandlerDesc = Object->Region.Handler;
362
if (HandlerDesc)
363
{
364
NextDesc = HandlerDesc->AddressSpace.RegionList;
365
StartDesc = NextDesc;
366
LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
367
368
/* Remove the region object from the handler list */
369
370
while (NextDesc)
371
{
372
if (NextDesc == Object)
373
{
374
*LastObjPtr = NextDesc->Region.Next;
375
break;
376
}
377
378
/* Walk the linked list of handlers */
379
380
LastObjPtr = &NextDesc->Region.Next;
381
NextDesc = NextDesc->Region.Next;
382
383
/* Prevent infinite loop if list is corrupted */
384
385
if (NextDesc == StartDesc)
386
{
387
ACPI_ERROR ((AE_INFO,
388
"Circular region list in address handler object %p",
389
HandlerDesc));
390
return_VOID;
391
}
392
}
393
394
if (HandlerDesc->AddressSpace.HandlerFlags &
395
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
396
{
397
/* Deactivate region and free region context */
398
399
if (HandlerDesc->AddressSpace.Setup)
400
{
401
(void) HandlerDesc->AddressSpace.Setup (Object,
402
ACPI_REGION_DEACTIVATE,
403
HandlerDesc->AddressSpace.Context,
404
&SecondDesc->Extra.RegionContext);
405
}
406
}
407
408
AcpiUtRemoveReference (HandlerDesc);
409
}
410
411
/* Now we can free the Extra object */
412
413
AcpiUtDeleteObjectDesc (SecondDesc);
414
}
415
if (Object->Field.InternalPccBuffer)
416
{
417
ACPI_FREE(Object->Field.InternalPccBuffer);
418
}
419
420
break;
421
422
case ACPI_TYPE_BUFFER_FIELD:
423
424
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
425
"***** Buffer Field %p\n", Object));
426
427
SecondDesc = AcpiNsGetSecondaryObject (Object);
428
if (SecondDesc)
429
{
430
AcpiUtDeleteObjectDesc (SecondDesc);
431
}
432
break;
433
434
case ACPI_TYPE_LOCAL_BANK_FIELD:
435
436
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
437
"***** Bank Field %p\n", Object));
438
439
SecondDesc = AcpiNsGetSecondaryObject (Object);
440
if (SecondDesc)
441
{
442
AcpiUtDeleteObjectDesc (SecondDesc);
443
}
444
break;
445
446
case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
447
448
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
449
"***** Address handler %p\n", Object));
450
451
AcpiOsDeleteMutex (Object->AddressSpace.ContextMutex);
452
break;
453
454
default:
455
456
break;
457
}
458
459
/* Free any allocated memory (pointer within the object) found above */
460
461
if (ObjPointer)
462
{
463
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
464
ObjPointer));
465
ACPI_FREE (ObjPointer);
466
}
467
468
/* Now the object can be safely deleted */
469
470
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS, "%s: Deleting Object %p [%s]\n",
471
ACPI_GET_FUNCTION_NAME, Object, AcpiUtGetObjectTypeName (Object)));
472
473
AcpiUtDeleteObjectDesc (Object);
474
return_VOID;
475
}
476
477
478
/*******************************************************************************
479
*
480
* FUNCTION: AcpiUtDeleteInternalObjectList
481
*
482
* PARAMETERS: ObjList - Pointer to the list to be deleted
483
*
484
* RETURN: None
485
*
486
* DESCRIPTION: This function deletes an internal object list, including both
487
* simple objects and package objects
488
*
489
******************************************************************************/
490
491
void
492
AcpiUtDeleteInternalObjectList (
493
ACPI_OPERAND_OBJECT **ObjList)
494
{
495
ACPI_OPERAND_OBJECT **InternalObj;
496
497
498
ACPI_FUNCTION_ENTRY ();
499
500
501
/* Walk the null-terminated internal list */
502
503
for (InternalObj = ObjList; *InternalObj; InternalObj++)
504
{
505
AcpiUtRemoveReference (*InternalObj);
506
}
507
508
/* Free the combined parameter pointer list and object array */
509
510
ACPI_FREE (ObjList);
511
return;
512
}
513
514
515
/*******************************************************************************
516
*
517
* FUNCTION: AcpiUtUpdateRefCount
518
*
519
* PARAMETERS: Object - Object whose ref count is to be updated
520
* Action - What to do (REF_INCREMENT or REF_DECREMENT)
521
*
522
* RETURN: None. Sets new reference count within the object
523
*
524
* DESCRIPTION: Modify the reference count for an internal acpi object
525
*
526
******************************************************************************/
527
528
static void
529
AcpiUtUpdateRefCount (
530
ACPI_OPERAND_OBJECT *Object,
531
UINT32 Action)
532
{
533
UINT16 OriginalCount;
534
UINT16 NewCount = 0;
535
ACPI_CPU_FLAGS LockFlags;
536
char *Message;
537
538
539
ACPI_FUNCTION_NAME (UtUpdateRefCount);
540
541
542
if (!Object)
543
{
544
return;
545
}
546
547
/*
548
* Always get the reference count lock. Note: Interpreter and/or
549
* Namespace is not always locked when this function is called.
550
*/
551
LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
552
OriginalCount = Object->Common.ReferenceCount;
553
554
/* Perform the reference count action (increment, decrement) */
555
556
switch (Action)
557
{
558
case REF_INCREMENT:
559
560
NewCount = OriginalCount + 1;
561
Object->Common.ReferenceCount = NewCount;
562
AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
563
564
/* The current reference count should never be zero here */
565
566
if (!OriginalCount)
567
{
568
ACPI_WARNING ((AE_INFO,
569
"Obj %p, Reference Count was zero before increment\n",
570
Object));
571
}
572
573
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
574
"Obj %p Type %.2X [%s] Refs %.2X [Incremented]\n",
575
Object, Object->Common.Type,
576
AcpiUtGetObjectTypeName (Object), NewCount));
577
Message = "Increment";
578
break;
579
580
case REF_DECREMENT:
581
582
/* The current reference count must be non-zero */
583
584
if (OriginalCount)
585
{
586
NewCount = OriginalCount - 1;
587
Object->Common.ReferenceCount = NewCount;
588
}
589
590
AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
591
592
if (!OriginalCount)
593
{
594
ACPI_WARNING ((AE_INFO,
595
"Obj %p, Reference Count is already zero, cannot decrement\n",
596
Object));
597
return;
598
}
599
600
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS,
601
"%s: Obj %p Type %.2X Refs %.2X [Decremented]\n",
602
ACPI_GET_FUNCTION_NAME, Object, Object->Common.Type, NewCount));
603
604
/* Actually delete the object on a reference count of zero */
605
606
if (NewCount == 0)
607
{
608
AcpiUtDeleteInternalObj (Object);
609
}
610
Message = "Decrement";
611
break;
612
613
default:
614
615
AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
616
ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
617
Action));
618
return;
619
}
620
621
/*
622
* Sanity check the reference count, for debug purposes only.
623
* (A deleted object will have a huge reference count)
624
*/
625
if (NewCount > ACPI_MAX_REFERENCE_COUNT)
626
{
627
ACPI_WARNING ((AE_INFO,
628
"Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s",
629
NewCount, Object, Object->Common.Type, Message));
630
}
631
}
632
633
634
/*******************************************************************************
635
*
636
* FUNCTION: AcpiUtUpdateObjectReference
637
*
638
* PARAMETERS: Object - Increment or decrement the ref count for
639
* this object and all sub-objects
640
* Action - Either REF_INCREMENT or REF_DECREMENT
641
*
642
* RETURN: Status
643
*
644
* DESCRIPTION: Increment or decrement the object reference count
645
*
646
* Object references are incremented when:
647
* 1) An object is attached to a Node (namespace object)
648
* 2) An object is copied (all subobjects must be incremented)
649
*
650
* Object references are decremented when:
651
* 1) An object is detached from an Node
652
*
653
******************************************************************************/
654
655
ACPI_STATUS
656
AcpiUtUpdateObjectReference (
657
ACPI_OPERAND_OBJECT *Object,
658
UINT16 Action)
659
{
660
ACPI_STATUS Status = AE_OK;
661
ACPI_GENERIC_STATE *StateList = NULL;
662
ACPI_OPERAND_OBJECT *NextObject = NULL;
663
ACPI_OPERAND_OBJECT *PrevObject;
664
ACPI_GENERIC_STATE *State;
665
UINT32 i;
666
667
668
ACPI_FUNCTION_NAME (UtUpdateObjectReference);
669
670
671
while (Object)
672
{
673
/* Make sure that this isn't a namespace handle */
674
675
if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
676
{
677
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
678
"Object %p is NS handle\n", Object));
679
return (AE_OK);
680
}
681
682
/*
683
* All sub-objects must have their reference count updated
684
* also. Different object types have different subobjects.
685
*/
686
switch (Object->Common.Type)
687
{
688
case ACPI_TYPE_DEVICE:
689
case ACPI_TYPE_PROCESSOR:
690
case ACPI_TYPE_POWER:
691
case ACPI_TYPE_THERMAL:
692
/*
693
* Update the notify objects for these types (if present)
694
* Two lists, system and device notify handlers.
695
*/
696
for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
697
{
698
PrevObject = Object->CommonNotify.NotifyList[i];
699
while (PrevObject)
700
{
701
NextObject = PrevObject->Notify.Next[i];
702
AcpiUtUpdateRefCount (PrevObject, Action);
703
PrevObject = NextObject;
704
}
705
}
706
break;
707
708
case ACPI_TYPE_PACKAGE:
709
/*
710
* We must update all the sub-objects of the package,
711
* each of whom may have their own sub-objects.
712
*/
713
for (i = 0; i < Object->Package.Count; i++)
714
{
715
/*
716
* Null package elements are legal and can be simply
717
* ignored.
718
*/
719
NextObject = Object->Package.Elements[i];
720
if (!NextObject)
721
{
722
continue;
723
}
724
725
switch (NextObject->Common.Type)
726
{
727
case ACPI_TYPE_INTEGER:
728
case ACPI_TYPE_STRING:
729
case ACPI_TYPE_BUFFER:
730
/*
731
* For these very simple sub-objects, we can just
732
* update the reference count here and continue.
733
* Greatly increases performance of this operation.
734
*/
735
AcpiUtUpdateRefCount (NextObject, Action);
736
break;
737
738
default:
739
/*
740
* For complex sub-objects, push them onto the stack
741
* for later processing (this eliminates recursion.)
742
*/
743
Status = AcpiUtCreateUpdateStateAndPush (
744
NextObject, Action, &StateList);
745
if (ACPI_FAILURE (Status))
746
{
747
goto ErrorExit;
748
}
749
break;
750
}
751
}
752
753
NextObject = NULL;
754
break;
755
756
case ACPI_TYPE_BUFFER_FIELD:
757
758
NextObject = Object->BufferField.BufferObj;
759
break;
760
761
case ACPI_TYPE_LOCAL_BANK_FIELD:
762
763
NextObject = Object->BankField.BankObj;
764
Status = AcpiUtCreateUpdateStateAndPush (
765
Object->BankField.RegionObj, Action, &StateList);
766
if (ACPI_FAILURE (Status))
767
{
768
goto ErrorExit;
769
}
770
break;
771
772
case ACPI_TYPE_LOCAL_INDEX_FIELD:
773
774
NextObject = Object->IndexField.IndexObj;
775
Status = AcpiUtCreateUpdateStateAndPush (
776
Object->IndexField.DataObj, Action, &StateList);
777
if (ACPI_FAILURE (Status))
778
{
779
goto ErrorExit;
780
}
781
break;
782
783
case ACPI_TYPE_LOCAL_REFERENCE:
784
/*
785
* The target of an Index (a package, string, or buffer) or a named
786
* reference must track changes to the ref count of the index or
787
* target object.
788
*/
789
if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
790
(Object->Reference.Class== ACPI_REFCLASS_NAME))
791
{
792
NextObject = Object->Reference.Object;
793
}
794
break;
795
796
case ACPI_TYPE_LOCAL_REGION_FIELD:
797
case ACPI_TYPE_REGION:
798
default:
799
800
break; /* No subobjects for all other types */
801
}
802
803
/*
804
* Now we can update the count in the main object. This can only
805
* happen after we update the sub-objects in case this causes the
806
* main object to be deleted.
807
*/
808
AcpiUtUpdateRefCount (Object, Action);
809
Object = NULL;
810
811
/* Move on to the next object to be updated */
812
813
if (NextObject)
814
{
815
Object = NextObject;
816
NextObject = NULL;
817
}
818
else if (StateList)
819
{
820
State = AcpiUtPopGenericState (&StateList);
821
Object = State->Update.Object;
822
AcpiUtDeleteGenericState (State);
823
}
824
}
825
826
return (AE_OK);
827
828
829
ErrorExit:
830
831
ACPI_EXCEPTION ((AE_INFO, Status,
832
"Could not update object reference count"));
833
834
/* Free any stacked Update State objects */
835
836
while (StateList)
837
{
838
State = AcpiUtPopGenericState (&StateList);
839
AcpiUtDeleteGenericState (State);
840
}
841
842
return (Status);
843
}
844
845
846
/*******************************************************************************
847
*
848
* FUNCTION: AcpiUtAddReference
849
*
850
* PARAMETERS: Object - Object whose reference count is to be
851
* incremented
852
*
853
* RETURN: None
854
*
855
* DESCRIPTION: Add one reference to an ACPI object
856
*
857
******************************************************************************/
858
859
void
860
AcpiUtAddReference (
861
ACPI_OPERAND_OBJECT *Object)
862
{
863
864
ACPI_FUNCTION_NAME (UtAddReference);
865
866
867
/* Ensure that we have a valid object */
868
869
if (!AcpiUtValidInternalObject (Object))
870
{
871
return;
872
}
873
874
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
875
"Obj %p Current Refs=%X [To Be Incremented]\n",
876
Object, Object->Common.ReferenceCount));
877
878
/* Increment the reference count */
879
880
(void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
881
return;
882
}
883
884
885
/*******************************************************************************
886
*
887
* FUNCTION: AcpiUtRemoveReference
888
*
889
* PARAMETERS: Object - Object whose ref count will be decremented
890
*
891
* RETURN: None
892
*
893
* DESCRIPTION: Decrement the reference count of an ACPI internal object
894
*
895
******************************************************************************/
896
897
void
898
AcpiUtRemoveReference (
899
ACPI_OPERAND_OBJECT *Object)
900
{
901
902
ACPI_FUNCTION_NAME (UtRemoveReference);
903
904
905
/*
906
* Allow a NULL pointer to be passed in, just ignore it. This saves
907
* each caller from having to check. Also, ignore NS nodes.
908
*/
909
if (!Object ||
910
(ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
911
912
{
913
return;
914
}
915
916
/* Ensure that we have a valid object */
917
918
if (!AcpiUtValidInternalObject (Object))
919
{
920
return;
921
}
922
923
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS,
924
"%s: Obj %p Current Refs=%X [To Be Decremented]\n",
925
ACPI_GET_FUNCTION_NAME, Object, Object->Common.ReferenceCount));
926
927
/*
928
* Decrement the reference count, and only actually delete the object
929
* if the reference count becomes 0. (Must also decrement the ref count
930
* of all subobjects!)
931
*/
932
(void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
933
return;
934
}
935
936