\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
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
\r
NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
if (NewGaugeData == NULL) {\r
+ EfiReleaseLock (&mPerfRecordLock);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
\r
mGaugeData->NumberOfEntries++;\r
\r
+ EfiReleaseLock (&mPerfRecordLock);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
{\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
\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
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
**/\r
EFI_STATUS\r
EFIAPI\r
-GetGaugeEx (\r
+InternalGetGaugeEx (\r
IN UINTN LogEntryKey,\r
OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
)\r
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