diff options
Diffstat (limited to 'source/components/utilities/utdelete.c')
| -rw-r--r-- | source/components/utilities/utdelete.c | 96 | 
1 files changed, 50 insertions, 46 deletions
| diff --git a/source/components/utilities/utdelete.c b/source/components/utilities/utdelete.c index a1007136a27de..f18d5564f9d99 100644 --- a/source/components/utilities/utdelete.c +++ b/source/components/utilities/utdelete.c @@ -390,11 +390,11 @@ AcpiUtDeleteInternalObjectList (   * FUNCTION:    AcpiUtUpdateRefCount   *   * PARAMETERS:  Object          - Object whose ref count is to be updated - *              Action          - What to do + *              Action          - What to do (REF_INCREMENT or REF_DECREMENT)   * - * RETURN:      New ref count + * RETURN:      None. Sets new reference count within the object   * - * DESCRIPTION: Modify the ref count and return it. + * DESCRIPTION: Modify the reference count for an internal acpi object   *   ******************************************************************************/ @@ -403,8 +403,9 @@ AcpiUtUpdateRefCount (      ACPI_OPERAND_OBJECT     *Object,      UINT32                  Action)  { -    UINT16                  Count; -    UINT16                  NewCount; +    UINT16                  OriginalCount; +    UINT16                  NewCount = 0; +    ACPI_CPU_FLAGS          LockFlags;      ACPI_FUNCTION_NAME (UtUpdateRefCount); @@ -415,80 +416,85 @@ AcpiUtUpdateRefCount (          return;      } -    Count = Object->Common.ReferenceCount; -    NewCount = Count; -      /* -     * Perform the reference count action (increment, decrement, force delete) +     * Always get the reference count lock. Note: Interpreter and/or +     * Namespace is not always locked when this function is called.       */ +    LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock); +    OriginalCount = Object->Common.ReferenceCount; + +    /* Perform the reference count action (increment, decrement) */ +      switch (Action)      {      case REF_INCREMENT: -        NewCount++; +        NewCount = OriginalCount + 1;          Object->Common.ReferenceCount = NewCount; +        AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); + +        /* The current reference count should never be zero here */ + +        if (!OriginalCount) +        { +            ACPI_WARNING ((AE_INFO, +                "Obj %p, Reference Count was zero before increment\n", +                Object)); +        }          ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, -            "Obj %p Refs=%X, [Incremented]\n", -            Object, NewCount)); +            "Obj %p Type %.2X Refs %.2X [Incremented]\n", +            Object, Object->Common.Type, NewCount));          break;      case REF_DECREMENT: -        if (Count < 1) -        { -            ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, -                "Obj %p Refs=%X, can't decrement! (Set to 0)\n", -                Object, NewCount)); +        /* The current reference count must be non-zero */ -            NewCount = 0; -        } -        else +        if (OriginalCount)          { -            NewCount--; - -            ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, -                "Obj %p Refs=%X, [Decremented]\n", -                Object, NewCount)); +            NewCount = OriginalCount - 1; +            Object->Common.ReferenceCount = NewCount;          } -        if (Object->Common.Type == ACPI_TYPE_METHOD) +        AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); + +        if (!OriginalCount)          { -            ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, -                "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount)); +            ACPI_WARNING ((AE_INFO, +                "Obj %p, Reference Count is already zero, cannot decrement\n", +                Object));          } -        Object->Common.ReferenceCount = NewCount; +        ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, +            "Obj %p Type %.2X Refs %.2X [Decremented]\n", +            Object, Object->Common.Type, NewCount)); + +        /* Actually delete the object on a reference count of zero */ +          if (NewCount == 0)          {              AcpiUtDeleteInternalObj (Object);          }          break; -    case REF_FORCE_DELETE: - -        ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, -            "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count)); - -        NewCount = 0; -        Object->Common.ReferenceCount = NewCount; -        AcpiUtDeleteInternalObj (Object); -        break; -      default: -        ACPI_ERROR ((AE_INFO, "Unknown action (0x%X)", Action)); -        break; +        AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); +        ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)", +            Action)); +        return;      }      /*       * Sanity check the reference count, for debug purposes only.       * (A deleted object will have a huge reference count)       */ -    if (Count > ACPI_MAX_REFERENCE_COUNT) +    if (NewCount > ACPI_MAX_REFERENCE_COUNT)      {          ACPI_WARNING ((AE_INFO, -            "Large Reference Count (0x%X) in object %p", Count, Object)); +            "Large Reference Count (0x%X) in object %p, Type=0x%.2X", +            NewCount, Object, Object->Common.Type));      }  } @@ -499,8 +505,7 @@ AcpiUtUpdateRefCount (   *   * PARAMETERS:  Object              - Increment ref count for this object   *                                    and all sub-objects - *              Action              - Either REF_INCREMENT or REF_DECREMENT or - *                                    REF_FORCE_DELETE + *              Action              - Either REF_INCREMENT or REF_DECREMENT   *   * RETURN:      Status   * @@ -771,7 +776,6 @@ AcpiUtRemoveReference (      /*       * Allow a NULL pointer to be passed in, just ignore it. This saves       * each caller from having to check. Also, ignore NS nodes. -     *       */      if (!Object ||          (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)) | 
