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