--- a/kernel/eka/bmarm/ekernsmp.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bmarm/ekernsmp.def Mon Oct 04 12:15:59 2010 +0100
@@ -1058,4 +1058,5 @@
SetKeyOffset__10RArrayBasei @ 1057 NONAME R3UNUSED ; RArrayBase::SetKeyOffset(int)
CpuRetires__5Cache @ 1058 NONAME R3UNUSED ; Cache::CpuRetires(void)
KernelRetires__5Cache @ 1059 NONAME R3UNUSED ; Cache::KernelRetires(void)
+ Register__16DPowerControllerUi @ 1060 NONAME R3UNUSED ; DPowerController::Register(unsigned int)
--- a/kernel/eka/bmarm/ekernu.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bmarm/ekernu.def Mon Oct 04 12:15:59 2010 +0100
@@ -1055,3 +1055,4 @@
SetKeyOffset__10RArrayBasei @ 1054 NONAME R3UNUSED ; RArrayBase::SetKeyOffset(int)
CpuRetires__5Cache @ 1055 NONAME R3UNUSED ; Cache::CpuRetires(void)
KernelRetires__5Cache @ 1056 NONAME R3UNUSED ; Cache::KernelRetires(void)
+ Register__16DPowerControllerUi @ 1057 NONAME R3UNUSED ; DPowerController::Register(unsigned int)
--- a/kernel/eka/bwins/ekernu.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bwins/ekernu.def Mon Oct 04 12:15:59 2010 +0100
@@ -938,4 +938,5 @@
?SetKeyOffset@RArrayBase@@IAEXH@Z @ 937 NONAME ; void RArrayBase::SetKeyOffset(int)
?CpuRetires@Cache@@SAXXZ @ 938 NONAME ; public: static void __cdecl Cache::CpuRetires(void)
?KernelRetires@Cache@@SAXXZ @ 939 NONAME ; public: static void __cdecl Cache::KernelRetires(void)
+ ?Register@DPowerController@@QAEXI@Z @ 940 NONAME ; public: void __thiscall DPowerController::Register(unsigned int)
--- a/kernel/eka/bx86/ekernsmp.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bx86/ekernsmp.def Mon Oct 04 12:15:59 2010 +0100
@@ -1015,4 +1015,5 @@
?SetKeyOffset@RArrayBase@@IAEXH@Z @ 1014 NONAME ; void RArrayBase::SetKeyOffset(int)
?CpuRetires@Cache@@SAXXZ @ 1015 NONAME ; public: static void __cdecl Cache::CpuRetires(void)
?KernelRetires@Cache@@SAXXZ @ 1016 NONAME ; public: static void __cdecl Cache::KernelRetires(void)
+ ?Register@DPowerController@@QAEXI@Z @ 1017 NONAME ; public: void __thiscall DPowerController::Register(unsigned int)
--- a/kernel/eka/bx86/ekernu.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bx86/ekernu.def Mon Oct 04 12:15:59 2010 +0100
@@ -960,4 +960,5 @@
?SetKeyOffset@RArrayBase@@IAEXH@Z @ 959 NONAME ; void RArrayBase::SetKeyOffset(int)
?CpuRetires@Cache@@SAXXZ @ 960 NONAME ; public: static void __cdecl Cache::CpuRetires(void)
?KernelRetires@Cache@@SAXXZ @ 961 NONAME ; public: static void __cdecl Cache::KernelRetires(void)
+ ?Register@DPowerController@@QAEXI@Z @ 962 NONAME ; public: void __thiscall DPowerController::Register(unsigned int)
--- a/kernel/eka/bx86gcc/ekernsmp.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bx86gcc/ekernsmp.def Mon Oct 04 12:15:59 2010 +0100
@@ -1104,7 +1104,5 @@
_ZN5Cache10CpuRetiresEv @ 1103 NONAME
_ZN5Cache13KernelRetiresEv @ 1104 NONAME
_ZN9TRawEvent3SetENS_5TTypeEiiih @ 1105 NONAME
-
-
-
-
+ _ZN16DPowerController8RegisterEj @ 1106 NONAME
+
\ No newline at end of file
--- a/kernel/eka/bx86gcc/ekernu.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/bx86gcc/ekernu.def Mon Oct 04 12:15:59 2010 +0100
@@ -1043,4 +1043,5 @@
_ZN10RArrayBase12SetKeyOffsetEi @ 1042 NONAME
_ZN5Cache10CpuRetiresEv @ 1043 NONAME
_ZN5Cache13KernelRetiresEv @ 1044 NONAME
+ _ZN16DPowerController8RegisterEj @ 1045 NONAME
--- a/kernel/eka/eabi/ekernsmp.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/eabi/ekernsmp.def Mon Oct 04 12:15:59 2010 +0100
@@ -1192,4 +1192,5 @@
_ZN10RArrayBase12SetKeyOffsetEi @ 1191 NONAME
_ZN5Cache10CpuRetiresEv @ 1192 NONAME
_ZN5Cache13KernelRetiresEv @ 1193 NONAME
+ _ZN16DPowerController8RegisterEj @ 1194 NONAME
--- a/kernel/eka/eabi/ekernu.def Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/eabi/ekernu.def Mon Oct 04 12:15:59 2010 +0100
@@ -1184,4 +1184,5 @@
_ZN10RArrayBase12SetKeyOffsetEi @ 1183 NONAME
_ZN5Cache10CpuRetiresEv @ 1184 NONAME
_ZN5Cache13KernelRetiresEv @ 1185 NONAME
+ _ZN16DPowerController8RegisterEj @ 1186 NONAME
--- a/kernel/eka/include/e32ver.h Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/include/e32ver.h Mon Oct 04 12:15:59 2010 +0100
@@ -28,7 +28,7 @@
const TInt KE32MajorVersionNumber=2;
const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=4005;
+const TInt KE32BuildVersionNumber=4006;
const TInt KMachineConfigurationMajorVersionNumber=1;
const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/include/kernel/kpower.h Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/include/kernel/kpower.h Mon Oct 04 12:15:59 2010 +0100
@@ -66,6 +66,7 @@
public:
IMPORT_C DPowerController();
IMPORT_C void Register();
+ IMPORT_C void Register(TUint aShutdownTimeoutMs);
IMPORT_C void WakeupEvent();
#ifndef __X86__
IMPORT_C TInt RegisterResourceController(DBase* aController, TInt aClientId);
--- a/kernel/eka/kernel/power.cpp Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/kernel/power.cpp Mon Oct 04 12:15:59 2010 +0100
@@ -21,8 +21,10 @@
#include "execs.h"
#include "msgqueue.h"
-// #define _DEBUG_POWER
-
+#ifdef _DEBUG
+#include <nkern/nk_trace.h>
+//#define _DEBUG_POWER
+#endif
/******************************************************************************
* Power Manager - a Power Model implementation
@@ -60,9 +62,18 @@
DBatteryMonitor* iBatteryMonitor;
DPowerHal* iPowerHal;
- TInt iTotalCurrent;
+ TUint iPslShutdownTimeoutMs; // default = 0
private:
+#ifndef _DEBUG_POWER
+ enum
+ {
+ ESHUTDOWN_TIMEOUT = 0xFFFFFFFF // -1
+ };
+
+ TInt iPendingShutdownCount;
+#endif
+
DPowerManager();
@@ -90,6 +101,8 @@
void NotifyWakeupEvent(TInt aReason);
+ static void ShutDownTimeoutFn(TAny* aArg);
+
DMutex* iFeatureLock;
DThread* iClient; // protected by the system lock
TClientRequest* iRequest; // protected by the system lock
@@ -142,7 +155,7 @@
return self;
}
-DPowerManager::DPowerManager()
+DPowerManager::DPowerManager()
{
}
@@ -328,7 +341,29 @@
NKern::ThreadLeaveCS();
}
-// Called in CS
+
+void DPowerManager::ShutDownTimeoutFn(TAny* aArg)
+ {
+ __KTRACE_OPT(KPOWER,Kern::Printf(">DPowerManager::ShutDownTimeoutFn"));
+ NFastSemaphore* sem = (NFastSemaphore*)aArg;
+#ifdef _DEBUG_POWER
+ NKern::FSSignal(sem);
+#else
+ TUint SignalCount = __e32_atomic_load_acq32(&(PowerManager->iPendingShutdownCount));
+ DPowerHandler* ph = PowerManager->iHandlers;
+ do
+ {
+ ph->iSem = NULL;
+ ph = ph->iPrev;
+ }while(ph != PowerManager->iHandlers);
+
+ __e32_atomic_store_rel32(&(PowerManager->iPendingShutdownCount), (TUint)ESHUTDOWN_TIMEOUT); // = -1
+ NKern::FSSignalN(sem,SignalCount);
+
+ __KTRACE_OPT(KPOWER,Kern::Printf("<DPowerManager::ShutDownTimeoutFn"));
+#endif
+ }
+
TInt DPowerManager::PowerDown()
{ // called by ExecHandler
__KTRACE_OPT(KPOWER,Kern::Printf(">PowerManger::PowerDown(0x%x) Enter", iPowerController->iTargetState));
@@ -344,7 +379,12 @@
}
__PM_ASSERT(iHandlers);
- NFastSemaphore sem(0);
+ NFastSemaphore shutdownSem(0);
+ NTimer ntimer;
+ TDfc dfc(ShutDownTimeoutFn, &shutdownSem);
+#ifndef _DEBUG_POWER
+ iPendingShutdownCount = 0;
+#endif
DPowerHandler* ph = iHandlers;
//Power down in reverse order of handle registration.
do
@@ -352,25 +392,56 @@
#ifdef _DEBUG_POWER
__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
#endif
- ph->iSem = &sem;
+ ph->iSem = &shutdownSem;
ph->PowerDown(iPowerController->iTargetState);
-#ifdef _DEBUG_POWER
- __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
- NKern::FSWait(&sem); // power down drivers one after another to simplify debug
- __PM_ASSERT(!ph->iSem);
- __PM_ASSERT(ph->iStatus & EDone);
- ph->iStatus &= ~EDone;
-#endif
+#ifndef _DEBUG_POWER
+ iPendingShutdownCount++;
+#else
+ if(iPslShutdownTimeoutMs>0)
+ {
+ // Fire shut down timeout timer
+ ntimer.OneShot(iPslShutdownTimeoutMs, dfc);
+ }
+
+ NKern::FSWait(&shutdownSem); // power down drivers one after another to simplify debug
+ __e32_atomic_and_ord32(&(ph->iStatus), ~DPowerHandler::EDone);
+
+ // timeout condition
+ if(iPslShutdownTimeoutMs>0 && ph->iSem)
+ {
+ __e32_atomic_store_ord_ptr(&ph->iSem, 0);
+ }
+ ntimer.Cancel();
+#endif
ph = ph->iPrev;
}while(ph != iHandlers);
#ifndef _DEBUG_POWER
+ if(iPslShutdownTimeoutMs>0)
+ {
+ // Fire shut down timeout timer
+ ntimer.OneShot(iPslShutdownTimeoutMs, dfc);
+ }
+
ph = iHandlers;
do
{
- NKern::FSWait(&sem);
+ NKern::FSWait(&shutdownSem);
+ if(__e32_atomic_load_acq32(&iPendingShutdownCount)==ESHUTDOWN_TIMEOUT)
+ {
+ iPendingShutdownCount = 0;
+ NKern::Lock();
+ shutdownSem.Reset(); // iPendingShutdownCount could be altered while ShutDownTimeoutFn is running
+ // reset it to make sure shutdownSem is completely clean.
+ NKern::Unlock();
+ break;
+ }
+ __e32_atomic_add_ord32(&iPendingShutdownCount, (TUint)(~0x0)); // iPendingShutDownCount--;
ph = ph->iPrev;
}while(ph != iHandlers);
+
+ ntimer.Cancel();
+
#endif
TTickQ::Wait();
@@ -382,6 +453,8 @@
K::SecondQ->WakeUp();
TTickQ::Signal();
+ NFastSemaphore powerupSem(0);
+
ph = iHandlers->iNext;
//Power up in same order of handle registration.
do
@@ -389,14 +462,13 @@
#ifdef _DEBUG_POWER
__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
#endif
- ph->iSem = &sem;
+ ph->iSem = &powerupSem;
ph->PowerUp();
#ifdef _DEBUG_POWER
- __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
- NKern::FSWait(&sem); // power down drivers one after another to simplify debug
+ NKern::FSWait(&powerupSem); // power down drivers one after another to simplify debug
__PM_ASSERT(!ph->iSem);
- __PM_ASSERT(ph->iStatus & EDone);
- ph->iStatus &= ~EDone;
+ __PM_ASSERT(ph->iStatus & DPowerHandler::EDone);
+ ph->iStatus &= ~DPowerHandler::EDone;
#endif
ph = ph->iNext;
}while(ph != iHandlers->iNext);
@@ -405,7 +477,7 @@
ph = iHandlers->iNext;
do
{
- NKern::FSWait(&sem);
+ NKern::FSWait(&powerupSem);
ph = ph->iNext;
}while(ph != iHandlers->iNext);
#endif
@@ -420,6 +492,7 @@
return KErrNone;
}
+
/******************************************************************************
* Power Handlers
******************************************************************************/
@@ -578,22 +651,13 @@
/** @deprecated, no replacement */
-EXPORT_C void DPowerHandler::DeltaCurrentConsumption(TInt aDelta)
+EXPORT_C void DPowerHandler::DeltaCurrentConsumption(TInt /* aDelta */)
{
- __e32_atomic_add_ord32(&iCurrent, aDelta);
- __PM_ASSERT(iCurrent >= 0);
- __e32_atomic_add_ord32(&PowerManager->iTotalCurrent, aDelta);
- __PM_ASSERT(PowerManager->iTotalCurrent >= 0);
}
/** @deprecated, no replacement */
-EXPORT_C void DPowerHandler::SetCurrentConsumption(TInt aCurrent)
+EXPORT_C void DPowerHandler::SetCurrentConsumption(TInt /* aCurrent */)
{
- __PM_ASSERT(aCurrent >= 0);
- TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrent, aCurrent);
- TInt delta = aCurrent - old;
- __e32_atomic_add_ord32(&PowerManager->iTotalCurrent, delta);
- __PM_ASSERT(PowerManager->iTotalCurrent >= 0);
}
/******************************************************************************
@@ -652,6 +716,25 @@
K::PowerModel = PowerManager;
}
+/**
+Registers this power controller object with the power manager.
+
+The power manager can only use the power controller after registration.
+
+@param aShutdownTimeoutMs The kernel shut down time out value in msec.
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerController::Register(TUint aShutdownTimeoutMs)
+ {
+ PowerManager->iPslShutdownTimeoutMs = aShutdownTimeoutMs;
+ Register();
+ }
+
#ifndef __X86__
/**
Registers resource controller with power controller
--- a/kernel/eka/release.txt Mon Oct 04 12:03:52 2010 +0100
+++ b/kernel/eka/release.txt Mon Oct 04 12:15:59 2010 +0100
@@ -1,3 +1,11 @@
+Version 2.00.4006
+=================
+(Made by vfebvre 27/09/2010)
+
+1. erifung
+ 1. RP540323 REQ:405-4716 kernel side device driver staged shutdown feature
+
+
Version 2.00.4005
=================
(Made by vfebvre 24/09/2010)
--- a/kerneltest/e32test/power/d_lddpowerseqtest.cpp Mon Oct 04 12:03:52 2010 +0100
+++ b/kerneltest/e32test/power/d_lddpowerseqtest.cpp Mon Oct 04 12:15:59 2010 +0100
@@ -60,6 +60,9 @@
DTest2PowerHandler();
void PowerUp();
void PowerDown(TPowerState);
+ void ActDead();
+private:
+ TBool iActDead;
};
class DTestFactory : public DLogicalDevice
@@ -86,6 +89,8 @@
virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2);
DTest1PowerHandler power1;
DTest2PowerHandler power2;
+private:
+ TUint iPslShutdownTimeoutMsBackup;
};
@@ -149,6 +154,7 @@
power2.Remove();
//try to remove a handler twice - should not cause any problems
power2.Remove();
+ ((DTestPowerManager*)(Kern::PowerModel()))->iPslShutdownTimeoutMs = iPslShutdownTimeoutMsBackup;
}
TInt DTest1::Request(TInt aReqNo, TAny* a1, TAny* a2)
@@ -192,10 +198,18 @@
// 'Control' functions...
switch(aReqNo)
{
+
// DoControl
case RLddTest1::ESET_SLEEPTIME:
sleepTime = (TUint)a1;
break;
+ case RLddTest1::EPOWER_ACTDEAD_POWER2:
+ power2.ActDead();
+ break;
+ case RLddTest1::EPOWER_ESETPOWERDOWNTIMEOUT:
+ iPslShutdownTimeoutMsBackup = ((DTestPowerManager*)(Kern::PowerModel()))->iPslShutdownTimeoutMs;
+ ((DTestPowerManager*)(Kern::PowerModel()))->iPslShutdownTimeoutMs = (TUint)a1;
+ break;
}
}
@@ -209,7 +223,7 @@
//
}
-DTest2PowerHandler::DTest2PowerHandler():DPowerHandler(KLitPower2)
+DTest2PowerHandler::DTest2PowerHandler():DPowerHandler(KLitPower2), iActDead(EFalse)
{
//
// Power handler2 constructor
@@ -276,5 +290,14 @@
Kern::RequestComplete(aStatus_down2, KErrNone);
- PowerDownDone();
+ if(!iActDead)
+ {
+ PowerDownDone();
+ }
}
+
+void DTest2PowerHandler::ActDead()
+ {
+ iActDead = ETrue;
+ }
+
--- a/kerneltest/e32test/power/d_lddpowerseqtest.h Mon Oct 04 12:03:52 2010 +0100
+++ b/kerneltest/e32test/power/d_lddpowerseqtest.h Mon Oct 04 12:15:59 2010 +0100
@@ -37,7 +37,9 @@
EPOWERDOWN_POWER1 = 1,
EPOWERDOWN_POWER2 = 2,
EPOWERUP_POWER1 = 3,
- EPOWERUP_POWER2 = 4
+ EPOWERUP_POWER2 = 4,
+ EPOWER_ACTDEAD_POWER2 = 5,
+ EPOWER_ESETPOWERDOWNTIMEOUT = 6
};
public:
@@ -47,9 +49,26 @@
inline void Test_power1up(TRequestStatus &aStatus, TUint &time);
inline void Test_power2up(TRequestStatus &aStatus, TUint &time);
inline TInt Test_setSleepTime(TUint sleepTime);
+ inline void Test_power2ActDead();
+ inline void Test_setPowerDownTimeout(TUint aTimeout);
static inline TInt Unload();
};
+#ifdef __KERNEL_MODE__
+class DTestPowerManager : public DPowerModel
+ {
+public:
+ TAny* iDummy;
+ TAny* iDummy2;
+ TAny* iDummy3;
+
+ // the offset of iPslShutdownTimeoutMs should be exactly same as
+ // of offset in DPowerManager
+ TUint iPslShutdownTimeoutMs; // default = 0
+
+ };
+#endif // __KERNEL_MODE__
+
#include "d_lddpowerseqtest.inl"
#endif //__DLDDPOWERSEQTEST_H__
--- a/kerneltest/e32test/power/d_lddpowerseqtest.inl Mon Oct 04 12:03:52 2010 +0100
+++ b/kerneltest/e32test/power/d_lddpowerseqtest.inl Mon Oct 04 12:15:59 2010 +0100
@@ -28,6 +28,10 @@
{ DoRequest(EPOWERUP_POWER2, aStatus, (TAny *)&time); }
inline TInt RLddTest1::Test_setSleepTime(TUint time)
{ return DoControl(ESET_SLEEPTIME, (TAny *)time); }
+inline void RLddTest1::Test_power2ActDead()
+ { DoControl(EPOWER_ACTDEAD_POWER2); }
+inline void RLddTest1::Test_setPowerDownTimeout(TUint aTimeout)
+ { DoControl(EPOWER_ESETPOWERDOWNTIMEOUT, (TAny *) aTimeout); }
inline TInt RLddTest1::Unload()
{ return User::FreeLogicalDevice(KLddName); }
#endif
--- a/kerneltest/e32test/power/t_lddpowerseqtest.cpp Mon Oct 04 12:03:52 2010 +0100
+++ b/kerneltest/e32test/power/t_lddpowerseqtest.cpp Mon Oct 04 12:15:59 2010 +0100
@@ -78,11 +78,11 @@
User::WaitForRequest(statuspowerdown1);
test(statuspowerdown1.Int() == KErrNone);
- test.Printf(_L("Waiting for power up request completion of handler1\n"));
+ test.Printf(_L("Waiting for power down request completion of handler1\n"));
User::WaitForRequest(statuspowerdown2);
test(statuspowerdown2.Int() == KErrNone);
- test.Printf(_L("Waiting for power down request completion of handler2\n"));
+ test.Printf(_L("Waiting for power up request completion of handler2\n"));
User::WaitForRequest(statuspowerup1);
test(statuspowerup1.Int() == KErrNone);
@@ -94,6 +94,24 @@
User::WaitForRequest(tstatus);
test(tstatus.Int() == KErrNone);
+ test.Printf(_L("Set power manager shut down timeout value\n"));
+ ldd.Test_setPowerDownTimeout(10);
+
+ test.Printf(_L("Instruct power handler 2 to act dead\n"));
+ ldd.Test_power2ActDead();
+
+ test.Printf(_L("Enable wakeup power events to standby\n"));
+ r = Power::EnableWakeupEvents(EPwStandby);
+ test (r == KErrNone);
+
+ wakeup.HomeTime();
+ wakeup += TTimeIntervalMicroSeconds(5000000);
+ timer.At(tstatus, wakeup);
+
+ test.Printf(_L("Powerdown\n"));
+ r = Power::PowerDown();
+ test (r == KErrNone);
+
timer.Close();
test(time_power2down >= time_power1down + timeInterval);