diff options
author | niruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-08-15 01:55:41 +0000 |
---|---|---|
committer | niruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-08-15 01:55:41 +0000 |
commit | 569224f9de1d19e323c685839a0653136fcb0dea (patch) | |
tree | bbdf4ce791723e4da36e26af3f48cad8e891019b /MdePkg/Library | |
parent | 5672b88f6c6326325235b4b2f9b666d75452596f (diff) | |
download | edk2-569224f9de1d19e323c685839a0653136fcb0dea.zip edk2-569224f9de1d19e323c685839a0653136fcb0dea.tar.gz edk2-569224f9de1d19e323c685839a0653136fcb0dea.tar.bz2 |
Use linked list to replace the current array solution to store the periodic SMI handlers to support more than 8 periodic SMI handlers.
Signed-off-by: niruiyu
Reviewed-by: xdu2
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12127 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdePkg/Library')
-rw-r--r-- | MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c | 296 |
1 files changed, 173 insertions, 123 deletions
diff --git a/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c b/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c index af456e9..1a96596 100644 --- a/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c +++ b/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c @@ -27,10 +27,8 @@ #include <Library/SmmPeriodicSmiLib.h>
///
-/// Define the number of periodic SMI handler entries that should be allocated in
-/// the constructor for gPeriodicSmiLibraryHandlers and also use this value as the
-/// number of entries to add to gPeriodicSmiLibraryHandlers when gPeriodicSmiLibraryHandlers
-/// is full.
+/// Define the number of periodic SMI handler entries that should be allocated to the list
+/// of free periodic SMI handlers when the list of free periodic SMI handlers is empty.
///
#define PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE 0x08
@@ -48,6 +46,10 @@ typedef struct { ///
UINT32 Signature;
///
+ /// The link entry to be inserted to the list of periodic SMI handlers.
+ ///
+ LIST_ENTRY Link;
+ ///
/// The dispatch function to called to invoke an enabled periodic SMI handler.
///
PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction;
@@ -155,6 +157,19 @@ typedef struct { PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE \
)
+/**
+ Macro that returns a pointer to a PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT
+ structure based on a pointer to a Link field.
+
+**/
+#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK(a) \
+ CR ( \
+ a, \
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT, \
+ Link, \
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE \
+ )
+
///
/// Pointer to the SMM Periodic Timer Disatch Protocol that was located in the constuctor.
///
@@ -170,21 +185,22 @@ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *gSmmPeriodicTimerDispatch2 UINT64 *gSmiTickPeriodTable = NULL;
///
-/// The number entries in gPeriodicSmiLibraryHandlers
+/// Linked list of free periodic SMI handlers that this library can use.
///
-UINTN gNumberOfPeriodicSmiLibraryHandlers = 0;
+LIST_ENTRY gFreePeriodicSmiLibraryHandlers =
+ INITIALIZE_LIST_HEAD_VARIABLE (gFreePeriodicSmiLibraryHandlers);
///
-/// Table of periodic SMI handlers that this library is currently managing. This
-/// table is allocated using AllocatePool()
+/// Linked list of periodic SMI handlers that this library is currently managing.
///
-PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *gPeriodicSmiLibraryHandlers = NULL;
+LIST_ENTRY gPeriodicSmiLibraryHandlers =
+ INITIALIZE_LIST_HEAD_VARIABLE (gPeriodicSmiLibraryHandlers);
///
-/// The index of gPeriodicSmiLibraryHandlers that is currently being executed.
-/// Is set to -1 if no periodic SMI handler is currently being executed.
+/// Pointer to the periodic SMI handler that is currently being executed.
+/// Is set to NULL if no periodic SMI handler is currently being executed.
///
-INTN gActivePeriodicSmiLibraryHandlerIndex = -1;
+PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *gActivePeriodicSmiLibraryHandler = NULL;
/**
Internal worker function that returns a pointer to the
@@ -202,18 +218,7 @@ GetActivePeriodicSmiLibraryHandler ( VOID
)
{
- if (gActivePeriodicSmiLibraryHandlerIndex < 0) {
- //
- // Return NULL if index is negative, which means that there is no active
- // periodic SMI handler.
- //
- return NULL;
- }
-
- //
- // Return a pointer to the active periodic SMI handler context
- //
- return &gPeriodicSmiLibraryHandlers[gActivePeriodicSmiLibraryHandlerIndex];
+ return gActivePeriodicSmiLibraryHandler;
}
/**
@@ -240,24 +245,30 @@ GetActivePeriodicSmiLibraryHandler ( **/
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *
LookupPeriodicSmiLibraryHandler (
- IN EFI_HANDLE DispatchHandle OPTIONAL
+ IN EFI_HANDLE DispatchHandle OPTIONAL
)
{
- UINTN Index;
+ LIST_ENTRY *Link;
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
//
// If DispatchHandle is NULL, then return the active periodic SMI handler
- //
+ //
if (DispatchHandle == NULL) {
return GetActivePeriodicSmiLibraryHandler ();
}
//
// Search the periodic SMI handler entries for a a matching DispatchHandle
- //
- for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {
- if (gPeriodicSmiLibraryHandlers[Index].DispatchHandle == DispatchHandle) {
- return &gPeriodicSmiLibraryHandlers[Index];
+ //
+ for ( Link = GetFirstNode (&gPeriodicSmiLibraryHandlers)
+ ; !IsNull (&gPeriodicSmiLibraryHandlers, Link)
+ ; Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link)
+ ) {
+ PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
+
+ if (PeriodicSmiLibraryHandler->DispatchHandle == DispatchHandle) {
+ return PeriodicSmiLibraryHandler;
}
}
@@ -285,15 +296,88 @@ SetActivePeriodicSmiLibraryHandler ( IN CONST VOID *Context OPTIONAL
)
{
- PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
-
if (Context == NULL) {
- gActivePeriodicSmiLibraryHandlerIndex = -1;
- return NULL;
+ gActivePeriodicSmiLibraryHandler = NULL;
+ } else {
+ gActivePeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_REGISTER_CONTEXT (Context);
}
- PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_REGISTER_CONTEXT (Context);
- gActivePeriodicSmiLibraryHandlerIndex = PeriodicSmiLibraryHandler - gPeriodicSmiLibraryHandlers;
- return PeriodicSmiLibraryHandler;
+ return gActivePeriodicSmiLibraryHandler;
+}
+
+/**
+ Internal worker function that moves the specified periodic SMI handler from the
+ list of managed periodic SMI handlers to the list of free periodic SMI handlers.
+
+ @param[in] PeriodicSmiLibraryHandler Pointer to the periodic SMI handler to be reclaimed.
+**/
+VOID
+ReclaimPeriodicSmiLibraryHandler (
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler
+ )
+{
+ LIST_ENTRY *Link;
+
+ ASSERT (PeriodicSmiLibraryHandler->DispatchHandle == NULL);
+ if (PeriodicSmiLibraryHandler->Stack != NULL) {
+ FreePages (
+ PeriodicSmiLibraryHandler->Stack,
+ EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)
+ );
+ PeriodicSmiLibraryHandler->Stack = NULL;
+ }
+ RemoveEntryList (&PeriodicSmiLibraryHandler->Link);
+ //
+ // Insert to gFreePeriodicSmiLibraryHandlers in the reverse order of the address of PeriodicSmiLibraryHandler
+ //
+ for ( Link = GetFirstNode (&gFreePeriodicSmiLibraryHandlers)
+ ; !IsNull (&gFreePeriodicSmiLibraryHandlers, Link)
+ ; Link = GetNextNode (&gFreePeriodicSmiLibraryHandlers, Link)
+ ) {
+ if (Link < &PeriodicSmiLibraryHandler->Link) {
+ break;
+ }
+ }
+ InsertTailList (Link, &PeriodicSmiLibraryHandler->Link);
+}
+
+/**
+ Add the additional entries to the list of free periodic SMI handlers.
+ The function is assumed to be called only when the list of free periodic SMI
+ handlers is empty.
+
+ @retval TRUE The additional entries were added.
+ @retval FALSE There was no available resource for the additional entries.
+**/
+BOOLEAN
+EnlargeFreePeriodicSmiLibraryHandlerList (
+ VOID
+ )
+{
+ UINTN Index;
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandlers;
+
+ //
+ // The function is assumed to be called only when the list of free periodic SMI library
+ // handlers is empty.
+ //
+ ASSERT (IsListEmpty (&gFreePeriodicSmiLibraryHandlers));
+
+ PeriodicSmiLibraryHandlers = AllocatePool (
+ PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE * sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT)
+ );
+ if (PeriodicSmiLibraryHandlers == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Add the entries to the list in the reverse order of the their memory address
+ //
+ for (Index = 0; Index < PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE; Index++) {
+ PeriodicSmiLibraryHandlers[Index].Signature = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE;
+ InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandlers[Index].Link);
+ }
+
+ return TRUE;
}
/**
@@ -310,40 +394,24 @@ FindFreePeriodicSmiLibraryHandler ( VOID
)
{
- UINTN Index;
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
- //
- // Search for a free entry in gPeriodicSmiLibraryHandlers
- // A free entry must have a NULL DispatchHandle and a NULL Stack.
- //
- for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {
- if (gPeriodicSmiLibraryHandlers[Index].DispatchHandle != NULL) {
- continue;
- }
- if (gPeriodicSmiLibraryHandlers[Index].Stack != NULL) {
- continue;
+ if (IsListEmpty (&gFreePeriodicSmiLibraryHandlers)) {
+ if (!EnlargeFreePeriodicSmiLibraryHandlerList ()) {
+ return NULL;
}
- return &gPeriodicSmiLibraryHandlers[Index];
}
//
- // If no free entries were found, then grow the table of periodic SMI handler entries
+ // Get one from the list of free periodic SMI handlers.
//
- if (Index == gNumberOfPeriodicSmiLibraryHandlers) {
- PeriodicSmiLibraryHandler = ReallocatePool (
- gNumberOfPeriodicSmiLibraryHandlers * sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT),
- (gNumberOfPeriodicSmiLibraryHandlers + PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE) * sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT),
- gPeriodicSmiLibraryHandlers
- );
- if (PeriodicSmiLibraryHandler == NULL) {
- return NULL;
- }
- gPeriodicSmiLibraryHandlers = PeriodicSmiLibraryHandler;
- gNumberOfPeriodicSmiLibraryHandlers += PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE;
- }
+ PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (
+ GetFirstNode (&gFreePeriodicSmiLibraryHandlers)
+ );
+ RemoveEntryList (&PeriodicSmiLibraryHandler->Link);
+ InsertTailList (&gPeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);
- return &gPeriodicSmiLibraryHandlers[Index];
+ return PeriodicSmiLibraryHandler;
}
/**
@@ -807,27 +875,12 @@ PeriodicSmiDispatchFunction ( //
ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
}
-
+
//
- // Retrieve the active periodic SMI handler in case the entries were reallocated
- // when the active periodic SMI handler was dispatched.
+ // Reclaim the active periodic SMI handler if it was disabled during the current dispatch.
//
- PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler ();
- if (PeriodicSmiLibraryHandler != NULL) {
- //
- // If the active periodic SMI handler was disabled during the current dispatch
- // and the periodic SMI handler was allocated a stack when it was enabled, then
- // free that stack here.
- //
- if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) {
- if (PeriodicSmiLibraryHandler->Stack != NULL) {
- FreePages (
- PeriodicSmiLibraryHandler->Stack,
- EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)
- );
- PeriodicSmiLibraryHandler->Stack = NULL;
- }
- }
+ if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) {
+ ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
}
//
@@ -923,8 +976,7 @@ PeriodicSmiEnable ( //
// Initialize a new periodic SMI handler entry
- //
- PeriodicSmiLibraryHandler->Signature = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE;
+ //
PeriodicSmiLibraryHandler->YieldFlag = FALSE;
PeriodicSmiLibraryHandler->DispatchHandle = NULL;
PeriodicSmiLibraryHandler->DispatchFunction = DispatchFunction;
@@ -937,6 +989,8 @@ PeriodicSmiEnable ( return EFI_OUT_OF_RESOURCES;
}
ZeroMem (PeriodicSmiLibraryHandler->Stack, PeriodicSmiLibraryHandler->StackSize);
+ } else {
+ PeriodicSmiLibraryHandler->Stack = NULL;
}
InitializeSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
PeriodicSmiLibraryHandler->PerfomanceCounterRate = GetPerformanceCounterProperties (
@@ -951,18 +1005,9 @@ PeriodicSmiEnable ( &PeriodicSmiLibraryHandler->RegisterContext,
&PeriodicSmiLibraryHandler->DispatchHandle
);
- if (EFI_ERROR (Status) || PeriodicSmiLibraryHandler->DispatchHandle == NULL) {
- //
- // If the registration failed or the handle is invalid, free the stack if one was allocated
- //
- if (PeriodicSmiLibraryHandler->Stack != NULL) {
- FreePages (
- PeriodicSmiLibraryHandler->Stack,
- EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)
- );
- PeriodicSmiLibraryHandler->Stack = NULL;
- }
+ if (EFI_ERROR (Status)) {
PeriodicSmiLibraryHandler->DispatchHandle = NULL;
+ ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
return EFI_OUT_OF_RESOURCES;
}
@@ -1021,25 +1066,15 @@ PeriodicSmiDisable ( }
//
- // If active periodic SMI handler is not the periodic SMI handler being
- // disabled, and the periodic SMI handler being disabled was allocated a
- // stack when it was enabled, then free the stack.
+ // Mark the entry for the disabled periodic SMI handler as free, and
+ // call ReclaimPeriodicSmiLibraryHandler to move it to the list of free
+ // periodic SMI handlers.
//
+ PeriodicSmiLibraryHandler->DispatchHandle = NULL;
if (PeriodicSmiLibraryHandler != GetActivePeriodicSmiLibraryHandler ()) {
- if (PeriodicSmiLibraryHandler->Stack != NULL) {
- FreePages (
- PeriodicSmiLibraryHandler->Stack,
- EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)
- );
- PeriodicSmiLibraryHandler->Stack = NULL;
- }
+ ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
}
-
- //
- // Mark the entry for the disabled periodic SMI handler as free
- //
- PeriodicSmiLibraryHandler->DispatchHandle = NULL;
-
+
return TRUE;
}
@@ -1111,12 +1146,12 @@ SmmPeriodicSmiLibConstructor ( gSmiTickPeriodTable[Count] = *SmiTickInterval;
}
Count++;
- } while (SmiTickInterval != NULL);
+ } while (SmiTickInterval != NULL);
//
// Allocate buffer for initial set of periodic SMI handlers
//
- FindFreePeriodicSmiLibraryHandler ();
+ EnlargeFreePeriodicSmiLibraryHandlerList ();
return EFI_SUCCESS;
}
@@ -1138,28 +1173,43 @@ SmmPeriodicSmiLibDestructor ( IN EFI_SYSTEM_TABLE *SystemTable
)
{
- UINTN Index;
+ LIST_ENTRY *Link;
+ PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
+ UINTN Index;
//
// Free the table of supported periodic SMI tick rates
- //
+ //
if (gSmiTickPeriodTable != NULL) {
FreePool (gSmiTickPeriodTable);
}
//
// Disable all periodic SMI handlers
- //
- for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {
- PeriodicSmiDisable (gPeriodicSmiLibraryHandlers[Index].DispatchHandle);
+ //
+ for (Link = GetFirstNode (&gPeriodicSmiLibraryHandlers); !IsNull (&gPeriodicSmiLibraryHandlers, Link);) {
+ PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
+ Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link);
+ PeriodicSmiDisable (PeriodicSmiLibraryHandler->DispatchHandle);
}
-
+
//
// Free all the periodic SMI handler entries
//
- if (gPeriodicSmiLibraryHandlers != NULL) {
- FreePool (gPeriodicSmiLibraryHandlers);
+ Index = 0;
+ for (Link = GetFirstNode (&gFreePeriodicSmiLibraryHandlers); !IsNull (&gFreePeriodicSmiLibraryHandlers, Link);) {
+ PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
+ Link = RemoveEntryList (Link);
+ Index++;
+ //
+ // Because the entries in the list are in the reverse order of the address of PeriodicSmiLibraryHandler and
+ // every PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE entries are in the same pool returned by AllocatePool(),
+ // every PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE'th entry is the header of allocated pool.
+ //
+ if ((Index % PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE) == 0) {
+ FreePool (PeriodicSmiLibraryHandler);
+ }
}
-
+
return EFI_SUCCESS;
}
|