Revision: 17023
http://sourceforge.net/p/edk2/code/17023
Author: vanjeff
Date: 2015-03-09 06:43:11 +0000 (Mon, 09 Mar 2015)
Log Message:
-----------
UefiCpuPkg/MpService: Put APs to sleep when not busy.
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 <[email protected]>
Reviewed-by: Jeff Fan <[email protected]>
Reviewed-by: Jordan Justen <[email protected]>
Modified Paths:
--------------
trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.c
trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.h
Modified: trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.c
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.c 2015-03-09 06:38:16 UTC (rev
17022)
+++ trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.c 2015-03-09 06:43:11 UTC (rev
17023)
@@ -298,9 +298,15 @@
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]);
}
}
-
SetApState (CpuData, CpuStateIdle);
}
}
@@ -343,7 +349,8 @@
}
CpuState = GetApState (CpuData);
- if (CpuState != CpuStateIdle) {
+ if (CpuState != CpuStateIdle &&
+ CpuState != CpuStateSleeping) {
if (mMpSystemData.FailedList != NULL) {
(*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;
}
@@ -615,6 +622,7 @@
CPU_DATA_BLOCK *CpuData;
UINTN Number;
CPU_STATE APInitialState;
+ CPU_STATE CpuState;
CpuData = NULL;
@@ -655,7 +663,9 @@
continue;
}
- if (GetApState (CpuData) != CpuStateIdle) {
+ CpuState = GetApState (CpuData);
+ if (CpuState != CpuStateIdle &&
+ CpuState != CpuStateSleeping) {
return EFI_NOT_READY;
}
}
@@ -694,13 +704,24 @@
// 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 +868,7 @@
)
{
CPU_DATA_BLOCK *CpuData;
+ CPU_STATE CpuState;
CpuData = NULL;
@@ -877,13 +899,24 @@
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 +1054,7 @@
{
CPU_DATA_BLOCK *CpuData;
BOOLEAN TempStopCheckState;
+ CPU_STATE CpuState;
CpuData = NULL;
TempStopCheckState = FALSE;
@@ -1046,7 +1080,9 @@
return EFI_INVALID_PARAMETER;
}
- if (GetApState (CpuData) != CpuStateIdle) {
+ CpuState = GetApState (CpuData);
+ if (CpuState != CpuStateIdle &&
+ CpuState != CpuStateSleeping) {
return EFI_UNSUPPORTED;
}
@@ -1201,8 +1237,22 @@
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 ();
}
Modified: trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.h
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.h 2015-03-09 06:38:16 UTC (rev
17022)
+++ trunk/edk2/UefiCpuPkg/CpuDxe/CpuMp.h 2015-03-09 06:43:11 UTC (rev
17023)
@@ -80,7 +80,8 @@
CpuStateBlocked,
CpuStateReady,
CpuStateBusy,
- CpuStateFinished
+ CpuStateFinished,
+ CpuStateSleeping
} CPU_STATE;
/**
------------------------------------------------------------------------------
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-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits