]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
MdeModulePkg/DxeCorePerformanceLib: add lock protection
[mirror_edk2.git] / MdeModulePkg / Library / DxeCorePerformanceLib / DxeCorePerformanceLib.c
index 51f488af6c14d91f4372049655e05dcfc6d5ec61..7c0e2078fbe9a20689087655de372f86b4140815 100644 (file)
@@ -63,6 +63,11 @@ PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
 \r
 PERFORMANCE_PROPERTY  mPerformanceProperty;\r
 \r
+//\r
+//  Gauge record lock to avoid data corruption or even memory overflow\r
+//\r
+STATIC EFI_LOCK mPerfRecordLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
+\r
 /**\r
   Searches in the gauge array with keyword Handle, Token, Module and Identifier.\r
 \r
@@ -162,6 +167,12 @@ StartGaugeEx (
   UINTN                     OldGaugeDataSize;\r
   GAUGE_DATA_HEADER         *OldGaugeData;\r
   UINT32                    Index;\r
+  EFI_STATUS                Status;\r
+\r
+  Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   Index = mGaugeData->NumberOfEntries;\r
   if (Index >= mMaxGaugeRecords) {\r
@@ -175,6 +186,7 @@ StartGaugeEx (
 \r
     NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
     if (NewGaugeData == NULL) {\r
+      EfiReleaseLock (&mPerfRecordLock);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
@@ -209,6 +221,8 @@ StartGaugeEx (
 \r
   mGaugeData->NumberOfEntries++;\r
 \r
+  EfiReleaseLock (&mPerfRecordLock);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -250,6 +264,12 @@ EndGaugeEx (
 {\r
   GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
   UINT32              Index;\r
+  EFI_STATUS          Status;\r
+\r
+  Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   if (TimeStamp == 0) {\r
     TimeStamp = GetPerformanceCounter ();\r
@@ -257,11 +277,13 @@ EndGaugeEx (
 \r
   Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
   if (Index >= mGaugeData->NumberOfEntries) {\r
+    EfiReleaseLock (&mPerfRecordLock);\r
     return EFI_NOT_FOUND;\r
   }\r
   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
   GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
 \r
+  EfiReleaseLock (&mPerfRecordLock);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -274,6 +296,8 @@ EndGaugeEx (
   If it stands for a valid entry, then EFI_SUCCESS is returned and\r
   GaugeDataEntryEx stores the pointer to that entry.\r
 \r
+  This internal function is added to avoid releasing lock before each return statement.\r
+\r
   @param  LogEntryKey             The key for the previous performance measurement log entry.\r
                                   If 0, then the first performance measurement log entry is retrieved.\r
   @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
@@ -287,7 +311,7 @@ EndGaugeEx (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-GetGaugeEx (\r
+InternalGetGaugeEx (\r
   IN  UINTN                 LogEntryKey,\r
   OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx\r
   )\r
@@ -313,6 +337,47 @@ GetGaugeEx (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Retrieves a previously logged performance measurement.\r
+  It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
+  and then assign the Identifier with 0.\r
+\r
+  Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
+  If it stands for a valid entry, then EFI_SUCCESS is returned and\r
+  GaugeDataEntryEx stores the pointer to that entry.\r
+\r
+  @param  LogEntryKey             The key for the previous performance measurement log entry.\r
+                                  If 0, then the first performance measurement log entry is retrieved.\r
+  @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
+                                  if the retrieval is successful.\r
+\r
+  @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.\r
+  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).\r
+  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).\r
+  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetGaugeEx (\r
+  IN  UINTN                 LogEntryKey,\r
+  OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = InternalGetGaugeEx (LogEntryKey, GaugeDataEntryEx);\r
+\r
+  EfiReleaseLock (&mPerfRecordLock);\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Adds a record at the end of the performance measurement log\r
   that records the start time of a performance measurement.\r