Add a new sleeping state for APs, when no procedure execution, put AP to sleep. when need to execute procedure, only need to wake up this AP by sent SIPI.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com> --- UefiCpuPkg/CpuDxe/CpuMp.c | 61 +++++++++++++++++++++++++++++++++++++++++++---- UefiCpuPkg/CpuDxe/CpuMp.h | 3 ++- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index 25c9091..0d6c4ec 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -298,6 +298,13 @@ CheckAndUpdateAllAPsToIdleState ( SetApProcedure (&mMpSystemData.CpuDatas[NextNumber], mMpSystemData.Procedure, mMpSystemData.ProcedureArgument); + // + // If this AP previous state is blocked, we should + // wake up this AP by sent a SIPI. and avoid + // re-involve the sleeping state. we must call + // SetApProcedure() first. + // + ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]); } } @@ -343,7 +350,8 @@ ResetAllFailedAPs ( } CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle) { + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { if (mMpSystemData.FailedList != NULL) { (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number; } @@ -615,6 +623,7 @@ StartupAllAPs ( CPU_DATA_BLOCK *CpuData; UINTN Number; CPU_STATE APInitialState; + CPU_STATE CpuState; CpuData = NULL; @@ -655,7 +664,9 @@ StartupAllAPs ( continue; } - if (GetApState (CpuData) != CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { return EFI_NOT_READY; } } @@ -694,13 +705,24 @@ StartupAllAPs ( // state 1 by 1, until the previous 1 finished its task // if not "SingleThread", all APs are put to ready state from the beginning // - if (GetApState (CpuData) == CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState == CpuStateIdle || + CpuState == CpuStateSleeping) { mMpSystemData.StartCount++; SetApState (CpuData, APInitialState); if (APInitialState == CpuStateReady) { SetApProcedure (CpuData, Procedure, ProcedureArgument); + // + // If this AP previous state is Sleeping, we should + // wake up this AP by sent a SIPI. and avoid + // re-involve the sleeping state. we must call + // SetApProcedure() first. + // + if (CpuState == CpuStateSleeping) { + ResetProcessorToIdleState (CpuData); + } } if (SingleThread) { @@ -847,6 +869,7 @@ StartupThisAP ( ) { CPU_DATA_BLOCK *CpuData; + CPU_STATE CpuState; CpuData = NULL; @@ -877,13 +900,24 @@ StartupThisAP ( return EFI_INVALID_PARAMETER; } - if (GetApState (CpuData) != CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { return EFI_NOT_READY; } SetApState (CpuData, CpuStateReady); SetApProcedure (CpuData, Procedure, ProcedureArgument); + // + // If this AP previous state is Sleeping, we should + // wake up this AP by sent a SIPI. and avoid + // re-involve the sleeping state. we must call + // SetApProcedure() first. + // + if (CpuState == CpuStateSleeping) { + ResetProcessorToIdleState (CpuData); + } CpuData->Timeout = TimeoutInMicroseconds; CpuData->WaitEvent = WaitEvent; @@ -1021,6 +1055,7 @@ EnableDisableAP ( { CPU_DATA_BLOCK *CpuData; BOOLEAN TempStopCheckState; + CPU_STATE CpuState; CpuData = NULL; TempStopCheckState = FALSE; @@ -1046,7 +1081,9 @@ EnableDisableAP ( return EFI_INVALID_PARAMETER; } - if (GetApState (CpuData) != CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { return EFI_UNSUPPORTED; } @@ -1201,6 +1238,20 @@ ProcessorToIdleState ( CpuData->Procedure = NULL; CpuData->State = CpuStateFinished; ReleaseMpSpinLock (CpuData); + } else { + // + // if no procedure to execution, we simply put AP + // into sleeping state, and waiting BSP sent SIPI. + // + GetMpSpinLock (CpuData); + if (CpuData->State == CpuStateIdle) { + CpuData->State = CpuStateSleeping; + } + ReleaseMpSpinLock (CpuData); + } + + if (GetApState (CpuData) == CpuStateSleeping) { + CpuSleep (); } CpuPause (); diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h index a6478c0..cb3460f 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.h +++ b/UefiCpuPkg/CpuDxe/CpuMp.h @@ -80,7 +80,8 @@ typedef enum { CpuStateBlocked, CpuStateReady, CpuStateBusy, - CpuStateFinished + CpuStateFinished, + CpuStateSleeping } CPU_STATE; /** -- 1.9.3 ------------------------------------------------------------------------------ Dive into the World of Parallel Programming The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel