MdeModulePkg: CoreValidateHandle Optimization

REF : https://bugzilla.tianocore.org/show_bug.cgi?id=4817

Before entering BIOS setup, CoreValidateHandle function executed
over 600,000 times during BDS phase on latest 8S server platform.
In CoreValidateHandle function, current implementation will go
through the doubly-linked list handle database in each call, and
this will have big impact on boot performance.
The optimization is using Red-black tree to store the EFI handle
address when insert each EFI handle into the handle database, and
remove the handle from Red-black tree if the handle is removed
from the handle database. CoreValidateHandle function changed to
go through the Red-black tree.
After verification on latest 8S server platform, BDS boot time can
save 20s+ after this change.

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Andrew Fish <afish@apple.com>
Tested-by: Xiaoqiang Zhang <xiaoqiang.zhang@intel.com>
This commit is contained in:
Xiaoqiang Zhang 2024-08-07 16:42:44 +08:00 committed by mergify[bot]
parent a63a7dbf85
commit 0596e5fa05
4 changed files with 97 additions and 11 deletions

View File

@ -84,6 +84,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DxeServicesLib.h> #include <Library/DxeServicesLib.h>
#include <Library/DebugAgentLib.h> #include <Library/DebugAgentLib.h>
#include <Library/CpuExceptionHandlerLib.h> #include <Library/CpuExceptionHandlerLib.h>
#include <Library/OrderedCollectionLib.h>
// //
// attributes for reserved memory before it is promoted to system memory // attributes for reserved memory before it is promoted to system memory
@ -2790,4 +2791,15 @@ MergeMemoryMap (
IN UINTN DescriptorSize IN UINTN DescriptorSize
); );
/**
Initializes "handle" support.
@return Status code.
+**/
EFI_STATUS
CoreInitializeHandleServices (
VOID
);
#endif #endif

View File

@ -95,6 +95,7 @@
CpuExceptionHandlerLib CpuExceptionHandlerLib
PcdLib PcdLib
ImagePropertiesRecordLib ImagePropertiesRecordLib
OrderedCollectionLib
[Guids] [Guids]
gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event

View File

@ -276,6 +276,12 @@ DxeMain (
MemoryProfileInit (HobStart); MemoryProfileInit (HobStart);
//
// Start the Handle Services.
//
Status = CoreInitializeHandleServices ();
ASSERT_EFI_ERROR (Status);
// //
// Start the Image Services. // Start the Image Services.
// //

View File

@ -15,10 +15,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase // gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
// gHandleDatabaseKey - The Key to show that the handle has been created/modified // gHandleDatabaseKey - The Key to show that the handle has been created/modified
// //
LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase); LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList); LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
UINT64 gHandleDatabaseKey = 0; UINT64 gHandleDatabaseKey = 0;
ORDERED_COLLECTION *gOrderedHandleList = NULL;
/** /**
Acquire lock on gProtocolDatabaseLock. Acquire lock on gProtocolDatabaseLock.
@ -44,6 +45,60 @@ CoreReleaseProtocolLock (
CoreReleaseLock (&gProtocolDatabaseLock); CoreReleaseLock (&gProtocolDatabaseLock);
} }
/**
Comparator function for two opaque pointers, ordering on (unsigned) pointer
value itself.
Can be used as both Key and UserStruct comparator.
@param[in] Pointer1 First pointer.
@param[in] Pointer2 Second pointer.
@retval <0 If Pointer1 compares less than Pointer2.
@retval 0 If Pointer1 compares equal to Pointer2.
@retval >0 If Pointer1 compares greater than Pointer2.
**/
STATIC
INTN
EFIAPI
PointerCompare (
IN CONST VOID *Pointer1,
IN CONST VOID *Pointer2
)
{
if (Pointer1 == Pointer2) {
return 0;
}
if ((UINTN)Pointer1 < (UINTN)Pointer2) {
return -1;
}
return 1;
}
/**
Initializes "handle" support.
@return Status code.
**/
EFI_STATUS
CoreInitializeHandleServices (
VOID
)
{
gOrderedHandleList = OrderedCollectionInit (PointerCompare, PointerCompare);
if (gOrderedHandleList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/** /**
Check whether a handle is a valid EFI_HANDLE Check whether a handle is a valid EFI_HANDLE
The gProtocolDatabaseLock must be owned The gProtocolDatabaseLock must be owned
@ -59,8 +114,7 @@ CoreValidateHandle (
IN EFI_HANDLE UserHandle IN EFI_HANDLE UserHandle
) )
{ {
IHANDLE *Handle; ORDERED_COLLECTION_ENTRY *Entry;
LIST_ENTRY *Link;
if (UserHandle == NULL) { if (UserHandle == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -68,11 +122,9 @@ CoreValidateHandle (
ASSERT_LOCKED (&gProtocolDatabaseLock); ASSERT_LOCKED (&gProtocolDatabaseLock);
for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) { Entry = OrderedCollectionFind (gOrderedHandleList, UserHandle);
Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); if (Entry != NULL) {
if (Handle == (IHANDLE *)UserHandle) { return EFI_SUCCESS;
return EFI_SUCCESS;
}
} }
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -452,6 +504,16 @@ CoreInstallProtocolInterfaceNotify (
goto Done; goto Done;
} }
//
// Add this handle to the ordered list of all handles
// in the system
//
Status = OrderedCollectionInsert (gOrderedHandleList, NULL, Handle);
if (EFI_ERROR (Status)) {
CoreFreePool (Handle);
goto Done;
}
// //
// Initialize new handler structure // Initialize new handler structure
// //
@ -825,6 +887,11 @@ CoreUninstallProtocolInterface (
// //
if (IsListEmpty (&Handle->Protocols)) { if (IsListEmpty (&Handle->Protocols)) {
Handle->Signature = 0; Handle->Signature = 0;
OrderedCollectionDelete (
gOrderedHandleList,
OrderedCollectionFind (gOrderedHandleList, Handle),
NULL
);
RemoveEntryList (&Handle->AllHandles); RemoveEntryList (&Handle->AllHandles);
CoreFreePool (Handle); CoreFreePool (Handle);
} }