\r
\r
if (FailedCpuList != NULL) {\r
- FailledList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
- SetMemN (FailledList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);\r
- FailedListIndex = 0;\r
- *FailedCpuList = FailledList;\r
+ gMPSystem.FailedList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
+ if (gMPSystem.FailedList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ SetMemN (gMPSystem.FailedList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);\r
+ gMPSystem.FailedListIndex = 0;\r
+ *FailedCpuList = gMPSystem.FailedList;\r
}\r
\r
Timeout = TimeoutInMicroseconds;\r
\r
ListIndex = 0;\r
- ProcessorData = NULL;\r
+ ProcessorData = NULL;\r
\r
- gMPSystem.FinishCount = 0;\r
- gMPSystem.StartCount = 0;\r
- APInitialState = CPU_STATE_READY;\r
+ gMPSystem.FinishCount = 0;\r
+ gMPSystem.StartCount = 0;\r
+ gMPSystem.SingleThread = SingleThread;\r
+ APInitialState = CPU_STATE_READY;\r
\r
for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {\r
ProcessorData = &gMPSystem.ProcessorData[Number];\r
continue;\r
}\r
\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Number;\r
+ continue;\r
+ }\r
+\r
//\r
// Get APs prepared, and put failing APs into FailedCpuList\r
// if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready\r
if (SingleThread) {\r
APInitialState = CPU_STATE_BLOCKED;\r
}\r
-\r
- } else if (FailedCpuList != NULL) {\r
- FailledList[FailedListIndex++] = Number;\r
- ListIndex++;\r
+ } else {\r
+ return EFI_NOT_READY;\r
}\r
}\r
\r
- if (FailedCpuList != NULL) {\r
- if (FailedListIndex == 0) {\r
- FreePool (*FailedCpuList);\r
- *FailedCpuList = NULL;\r
+ if (WaitEvent != NULL) {\r
+ for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {\r
+ ProcessorData = &gMPSystem.ProcessorData[Number]; \r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+ // Skip BSP\r
+ continue;\r
+ }\r
+\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ continue;\r
+ }\r
+ \r
+ SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
}\r
+\r
+ //\r
+ // Save data into private data structure, and create timer to poll AP state before exiting\r
+ //\r
+ gMPSystem.Procedure = Procedure;\r
+ gMPSystem.ProcedureArgument = ProcedureArgument;\r
+ gMPSystem.WaitEvent = WaitEvent;\r
+ gMPSystem.Timeout = TimeoutInMicroseconds;\r
+ gMPSystem.TimeoutActive = (BOOLEAN)(TimeoutInMicroseconds != 0);\r
+ Status = gBS->SetTimer (\r
+ gMPSystem.CheckAllAPsEvent,\r
+ TimerPeriodic,\r
+ gPollInterval\r
+ );\r
+ return Status;\r
+\r
}\r
\r
while (TRUE) {\r
continue;\r
}\r
\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ continue;\r
+ }\r
+\r
gThread->MutexLock (ProcessorData->StateLock);\r
ProcessorState = ProcessorData->State;\r
gThread->MutexUnlock (ProcessorData->StateLock);\r
}\r
\r
if (gMPSystem.FinishCount == gMPSystem.StartCount) {\r
- return EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
}\r
\r
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
- //\r
- // Save data into private data structure, and create timer to poll AP state before exiting\r
- //\r
- gMPSystem.Procedure = Procedure;\r
- gMPSystem.ProcedureArgument = ProcedureArgument;\r
- gMPSystem.WaitEvent = WaitEvent;\r
-\r
- Status = gBS->SetTimer (\r
- gMPSystem.CheckAllAPsEvent,\r
- TimerPeriodic,\r
- gPollInterval\r
- );\r
- return EFI_TIMEOUT;\r
+ Status = EFI_TIMEOUT;\r
+ goto Done;\r
}\r
\r
gBS->Stall (gPollInterval);\r
Timeout -= gPollInterval;\r
}\r
\r
+Done:\r
+ if (FailedCpuList != NULL) {\r
+ if (gMPSystem.FailedListIndex == 0) {\r
+ FreePool (*FailedCpuList);\r
+ *FailedCpuList = NULL;\r
+ }\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
\r
SetApProcedure (&gMPSystem.ProcessorData[ProcessorNumber], Procedure, ProcedureArgument);\r
\r
+ if (WaitEvent != NULL) {\r
+ // Non Blocking\r
+ gMPSystem.WaitEvent = WaitEvent;\r
+ Status = gBS->SetTimer (\r
+ gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,\r
+ TimerPeriodic,\r
+ gPollInterval\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ // Blocking\r
while (TRUE) {\r
gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {\r
gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
\r
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
- gMPSystem.WaitEvent = WaitEvent;\r
- Status = gBS->SetTimer (\r
- gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,\r
- TimerPeriodic,\r
- gPollInterval\r
- );\r
return EFI_TIMEOUT;\r
}\r
\r
PROCESSOR_DATA_BLOCK *NextData;\r
EFI_STATUS Status;\r
PROCESSOR_STATE ProcessorState;\r
+ UINTN Cpu;\r
+ BOOLEAN Found;\r
\r
+ if (gMPSystem.TimeoutActive) {\r
+ gMPSystem.Timeout -= gPollInterval;\r
+ }\r
+ \r
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
\r
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
continue;\r
}\r
\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ continue;\r
+ }\r
+\r
// This is an Interrupt Service routine.\r
// This can grab a lock that is held in a non-interrupt\r
// context. Meaning deadlock. Which is a bad thing.\r
break;\r
}\r
}\r
+ \r
+ if (gMPSystem.TimeoutActive && gMPSystem.Timeout < 0) {\r
+ //\r
+ // Timeout\r
+ //\r
+ if (gMPSystem.FailedList != NULL) {\r
+ for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
+ if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+ // Skip BSP\r
+ continue;\r
+ }\r
+\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ continue;\r
+ }\r
+ \r
+ // Mark the \r
+ Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ if (EFI_ERROR(Status)) {\r
+ return;\r
+ }\r
+ ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ \r
+ if (ProcessorState != CPU_STATE_IDLE) {\r
+ // If we are retrying make sure we don't double count\r
+ for (Cpu = 0, Found = FALSE; Cpu < gMPSystem.NumberOfProcessors; Cpu++) {\r
+ if (gMPSystem.FailedList[Cpu] == END_OF_CPU_LIST) {\r
+ break;\r
+ }\r
+ if (gMPSystem.FailedList[ProcessorNumber] == Cpu) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ if (!Found) {\r
+ gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Cpu;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // Force terminal exit\r
+ gMPSystem.FinishCount = gMPSystem.StartCount;\r
+ }\r
\r
- if (gMPSystem.FinishCount == gMPSystem.StartCount) {\r
- gBS->SetTimer (\r
- gMPSystem.CheckAllAPsEvent,\r
- TimerCancel,\r
- 0\r
- );\r
- Status = gBS->SignalEvent (gMPSystem.WaitEvent);\r
+ if (gMPSystem.FinishCount != gMPSystem.StartCount) {\r
+ return;\r
}\r
+ \r
+ gBS->SetTimer (\r
+ gMPSystem.CheckAllAPsEvent,\r
+ TimerCancel,\r
+ 0\r
+ );\r
+\r
+ if (gMPSystem.FailedListIndex == 0) {\r
+ if (gMPSystem.FailedList != NULL) {\r
+ FreePool (gMPSystem.FailedList);\r
+ gMPSystem.FailedList = NULL;\r
+ }\r
+ }\r
+\r
+ Status = gBS->SignalEvent (gMPSystem.WaitEvent);\r
\r
return ;\r
}\r
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
\r
//\r
- // rdar://6260979 - This is an Interrupt Service routine.\r
- // this can grab a lock that is held in a non-interrupt\r
+ // This is an Interrupt Service routine.\r
+ // that can grab a lock that is held in a non-interrupt\r
// context. Meaning deadlock. Which is a badddd thing.\r
// So, try lock it. If we can get it, cool, do our thing.\r
// otherwise, just dump out & try again on the next iteration.\r