Skip to content

Commit

Permalink
Tables: Tune table mutex to be a leaf lock
Browse files Browse the repository at this point in the history
This patch tunes MTX_TABLES into a leaf lock by always ensuring it is
released before holding other locks.

This patch also collects all table loading related functions into
AcpiTbLoadTable() (invoked by LoadTable opcode) and
AcpiTbInstallAndLoadTable() (invoked by Load opcode and AcpiLoadTable()) so
that we can have lock tuning code collected at the boundary of these 2
functions. Lv Zheng.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
  • Loading branch information
Lv Zheng committed Aug 26, 2016
1 parent fd305ed commit f564d57
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 135 deletions.
7 changes: 7 additions & 0 deletions source/compiler/aslstubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,13 @@ AcpiEvDeleteGpeBlock (
return (AE_OK);
}

void
AcpiEvUpdateGpes (
ACPI_OWNER_ID TableOwnerId)
{
return;
}

ACPI_STATUS
AcpiEvAcquireGlobalLock (
UINT16 Timeout)
Expand Down
102 changes: 18 additions & 84 deletions source/components/executer/exconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@
static ACPI_STATUS
AcpiExAddTable (
UINT32 TableIndex,
ACPI_NAMESPACE_NODE *ParentNode,
ACPI_OPERAND_OBJECT **DdbHandle);

static ACPI_STATUS
Expand Down Expand Up @@ -160,12 +159,9 @@ AcpiExRegionRead (
static ACPI_STATUS
AcpiExAddTable (
UINT32 TableIndex,
ACPI_NAMESPACE_NODE *ParentNode,
ACPI_OPERAND_OBJECT **DdbHandle)
{
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_STATUS Status;
ACPI_OWNER_ID OwnerId;


ACPI_FUNCTION_TRACE (ExAddTable);
Expand All @@ -183,42 +179,8 @@ AcpiExAddTable (

ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE;
*DdbHandle = ObjDesc;

/* Install the new table into the local data structures */

ObjDesc->Reference.Value = TableIndex;

/* Add the table to the namespace */

Status = AcpiNsLoadTable (TableIndex, ParentNode);
if (ACPI_FAILURE (Status))
{
AcpiUtRemoveReference (ObjDesc);
*DdbHandle = NULL;
return_ACPI_STATUS (Status);
}

/* Execute any module-level code that was found in the table */

AcpiExExitInterpreter ();
if (!AcpiGbl_ParseTableAsTermList && AcpiGbl_GroupModuleLevelCode)
{
AcpiNsExecModuleCodeList ();
}
AcpiExEnterInterpreter ();

/*
* Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
* responsible for discovering any new wake GPEs by running _PRW methods
* that may have been loaded by this table.
*/
Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
if (ACPI_SUCCESS (Status))
{
AcpiEvUpdateGpes (OwnerId);
}

*DdbHandle = ObjDesc;
return_ACPI_STATUS (AE_OK);
}

Expand Down Expand Up @@ -247,7 +209,6 @@ AcpiExLoadTableOp (
ACPI_NAMESPACE_NODE *StartNode;
ACPI_NAMESPACE_NODE *ParameterNode = NULL;
ACPI_OPERAND_OBJECT *DdbHandle;
ACPI_TABLE_HEADER *Table;
UINT32 TableIndex;


Expand All @@ -256,10 +217,12 @@ AcpiExLoadTableOp (

/* Find the ACPI table in the RSDT/XSDT */

AcpiExExitInterpreter ();
Status = AcpiTbFindTable (
Operand[0]->String.Pointer,
Operand[1]->String.Pointer,
Operand[2]->String.Pointer, &TableIndex);
AcpiExEnterInterpreter ();
if (ACPI_FAILURE (Status))
{
if (Status != AE_NOT_FOUND)
Expand Down Expand Up @@ -328,7 +291,16 @@ AcpiExLoadTableOp (

/* Load the table into the namespace */

Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle);
ACPI_INFO (("Dynamic OEM Table Load:"));
AcpiExExitInterpreter ();
Status = AcpiTbLoadTable (TableIndex, ParentNode);
AcpiExEnterInterpreter ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}

Status = AcpiExAddTable (TableIndex, &DdbHandle);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
Expand All @@ -351,21 +323,6 @@ AcpiExLoadTableOp (
}
}

Status = AcpiGetTableByIndex (TableIndex, &Table);
if (ACPI_SUCCESS (Status))
{
ACPI_INFO (("Dynamic OEM Table Load:"));
AcpiTbPrintTableHeader (0, Table);
}

/* Invoke table handler if present */

if (AcpiGbl_TableHandler)
{
(void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
AcpiGbl_TableHandlerContext);
}

*ReturnDesc = DdbHandle;
return_ACPI_STATUS (Status);
}
Expand Down Expand Up @@ -595,13 +552,10 @@ AcpiExLoadOp (
/* Install the new table into the local data structures */

ACPI_INFO (("Dynamic OEM Table Load:"));
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);

Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, TRUE,
&TableIndex);

(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
AcpiExExitInterpreter ();
Status = AcpiTbInstallAndLoadTable (Table, ACPI_PTR_TO_PHYSADDR (Table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, &TableIndex);
AcpiExEnterInterpreter ();
if (ACPI_FAILURE (Status))
{
/* Delete allocated table buffer */
Expand All @@ -610,25 +564,14 @@ AcpiExLoadOp (
return_ACPI_STATUS (Status);
}

/*
* Note: Now table is "INSTALLED", it must be validated before
* loading.
*/
Status = AcpiTbValidateTable (
&AcpiGbl_RootTableList.Tables[TableIndex]);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}

/*
* Add the table to the namespace.
*
* Note: Load the table objects relative to the root of the namespace.
* This appears to go against the ACPI specification, but we do it for
* compatibility with other ACPI implementations.
*/
Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle);
Status = AcpiExAddTable (TableIndex, &DdbHandle);
if (ACPI_FAILURE (Status))
{
/* On error, TablePtr was deallocated above */
Expand All @@ -652,15 +595,6 @@ AcpiExLoadOp (
/* Remove the reference by added by AcpiExStore above */

AcpiUtRemoveReference (DdbHandle);

/* Invoke table handler if present */

if (AcpiGbl_TableHandler)
{
(void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
AcpiGbl_TableHandlerContext);
}

return_ACPI_STATUS (Status);
}

Expand Down
158 changes: 158 additions & 0 deletions source/components/tables/tbdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
#include "accommon.h"
#include "acnamesp.h"
#include "actables.h"
#include "acevents.h"

#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME ("tbdata")
Expand Down Expand Up @@ -939,3 +940,160 @@ AcpiTbSetTableLoadedFlag (

(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
}


/*******************************************************************************
*
* FUNCTION: AcpiTbLoadTable
*
* PARAMETERS: TableIndex - Table index
* ParentNode - Where table index is returned
*
* RETURN: Status
*
* DESCRIPTION: Load an ACPI table
*
******************************************************************************/

ACPI_STATUS
AcpiTbLoadTable (
UINT32 TableIndex,
ACPI_NAMESPACE_NODE *ParentNode)
{
ACPI_TABLE_HEADER *Table;
ACPI_STATUS Status;
ACPI_OWNER_ID OwnerId;


ACPI_FUNCTION_TRACE (TbLoadTable);


/*
* Note: Now table is "INSTALLED", it must be validated before
* using.
*/
Status = AcpiGetTableByIndex (TableIndex, &Table);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}

Status = AcpiNsLoadTable (TableIndex, ParentNode);

/* Execute any module-level code that was found in the table */

if (!AcpiGbl_ParseTableAsTermList && AcpiGbl_GroupModuleLevelCode)
{
AcpiNsExecModuleCodeList ();
}

/*
* Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
* responsible for discovering any new wake GPEs by running _PRW methods
* that may have been loaded by this table.
*/
Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
if (ACPI_SUCCESS (Status))
{
AcpiEvUpdateGpes (OwnerId);
}

/* Invoke table handler if present */

if (AcpiGbl_TableHandler)
{
(void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
AcpiGbl_TableHandlerContext);
}

return_ACPI_STATUS (Status);
}


/*******************************************************************************
*
* FUNCTION: AcpiTbInstallAndLoadTable
*
* PARAMETERS: Table - Pointer to the table
* Address - Physical address of the table
* Flags - Allocation flags of the table
* TableIndex - Where table index is returned
*
* RETURN: Status
*
* DESCRIPTION: Install and load an ACPI table
*
******************************************************************************/

ACPI_STATUS
AcpiTbInstallAndLoadTable (
ACPI_TABLE_HEADER *Table,
ACPI_PHYSICAL_ADDRESS Address,
UINT8 Flags,
BOOLEAN Override,
UINT32 *TableIndex)
{
ACPI_STATUS Status;
UINT32 i;
ACPI_OWNER_ID OwnerId;


ACPI_FUNCTION_TRACE (AcpiLoadTable);


(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);

/* Install the table and load it into the namespace */

Status = AcpiTbInstallStandardTable (Address, Flags, TRUE,
Override, &i);
if (ACPI_FAILURE (Status))
{
goto UnlockAndExit;
}

/*
* Note: Now table is "INSTALLED", it must be validated before
* using.
*/
Status = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[i]);
if (ACPI_FAILURE (Status))
{
goto UnlockAndExit;
}

(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
Status = AcpiNsLoadTable (i, AcpiGbl_RootNode);

/* Execute any module-level code that was found in the table */

if (!AcpiGbl_ParseTableAsTermList && AcpiGbl_GroupModuleLevelCode)
{
AcpiNsExecModuleCodeList ();
}

/*
* Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
* responsible for discovering any new wake GPEs by running _PRW methods
* that may have been loaded by this table.
*/
Status = AcpiTbGetOwnerId (i, &OwnerId);
if (ACPI_SUCCESS (Status))
{
AcpiEvUpdateGpes (OwnerId);
}

/* Invoke table handler if present */

if (AcpiGbl_TableHandler)
{
(void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
AcpiGbl_TableHandlerContext);
}
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);

UnlockAndExit:
*TableIndex = i;
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
return_ACPI_STATUS (Status);
}
Loading

0 comments on commit f564d57

Please sign in to comment.