kernel/eka/kernel/power.cpp
changeset 280 2bfb1feef9de
parent 244 a77889bee936
child 286 48e57fb1237e
equal deleted inserted replaced
279:957c583b417b 280:2bfb1feef9de
    19 #include <kernel/kpower.h>
    19 #include <kernel/kpower.h>
    20 #include <kernel/kern_priv.h>
    20 #include <kernel/kern_priv.h>
    21 #include "execs.h"
    21 #include "execs.h"
    22 #include "msgqueue.h"
    22 #include "msgqueue.h"
    23 
    23 
    24 // #define _DEBUG_POWER
    24 #ifdef _DEBUG
    25 
    25 #include <nkern/nk_trace.h>
       
    26 //#define _DEBUG_POWER
       
    27 #endif
    26 
    28 
    27 /******************************************************************************
    29 /******************************************************************************
    28  * Power Manager - a Power Model implementation
    30  * Power Manager - a Power Model implementation
    29  ******************************************************************************/
    31  ******************************************************************************/
    30 #ifndef __X86__
    32 #ifndef __X86__
    58 
    60 
    59 	DPowerController*	iPowerController;
    61 	DPowerController*	iPowerController;
    60 	DBatteryMonitor*	iBatteryMonitor;
    62 	DBatteryMonitor*	iBatteryMonitor;
    61 	DPowerHal*			iPowerHal;
    63 	DPowerHal*			iPowerHal;
    62 
    64 
    63 	TInt				iTotalCurrent;
    65 	TUint iPslShutdownTimeoutMs; // default = 0
    64 
    66 
    65 private:
    67 private:
       
    68 #ifndef _DEBUG_POWER	
       
    69 	enum 
       
    70 		{
       
    71 		ESHUTDOWN_TIMEOUT = 0xFFFFFFFF // -1
       
    72 		};
       
    73 
       
    74 	TInt iPendingShutdownCount;
       
    75 #endif	
       
    76 
    66 
    77 
    67 	DPowerManager();
    78 	DPowerManager();
    68 
    79 
    69 	// Acquire the feature lock
    80 	// Acquire the feature lock
    70 	// Called in CS
    81 	// Called in CS
    87 		// used in assertions only
    98 		// used in assertions only
    88 //		{ return iFeatureLock->iCleanup.iThread == TheCurrentThread; }
    99 //		{ return iFeatureLock->iCleanup.iThread == TheCurrentThread; }
    89 // #endif
   100 // #endif
    90 	
   101 	
    91 	void NotifyWakeupEvent(TInt aReason);
   102 	void NotifyWakeupEvent(TInt aReason);
       
   103 
       
   104 	static void ShutDownTimeoutFn(TAny* aArg);
    92 
   105 
    93 	DMutex*			iFeatureLock;
   106 	DMutex*			iFeatureLock;
    94 	DThread*		iClient;				// protected by the system lock
   107 	DThread*		iClient;				// protected by the system lock
    95 	TClientRequest*	iRequest;				// protected by the system lock
   108 	TClientRequest*	iRequest;				// protected by the system lock
    96 	DPowerHandler*	iHandlers;				// protected by the feature lock
   109 	DPowerHandler*	iHandlers;				// protected by the feature lock
   140 	if (r != KErrNone)
   153 	if (r != KErrNone)
   141 		return NULL; // Do not cleanup since kernel will panic eventually
   154 		return NULL; // Do not cleanup since kernel will panic eventually
   142 	return self;
   155 	return self;
   143 	}
   156 	}
   144 
   157 
   145 DPowerManager::DPowerManager() 
   158 DPowerManager::DPowerManager()							
   146 	{
   159 	{
   147 	}
   160 	}
   148 
   161 
   149 void DPowerManager::CpuIdle()
   162 void DPowerManager::CpuIdle()
   150 	{ // from DPowerModel
   163 	{ // from DPowerModel
   326 	NKern::ThreadEnterCS();
   339 	NKern::ThreadEnterCS();
   327 	NotifyWakeupEvent(KErrCancel);
   340 	NotifyWakeupEvent(KErrCancel);
   328 	NKern::ThreadLeaveCS();
   341 	NKern::ThreadLeaveCS();
   329 	}
   342 	}
   330 
   343 
   331 // Called in CS
   344 
       
   345 void DPowerManager::ShutDownTimeoutFn(TAny* aArg)
       
   346 	{
       
   347 	__KTRACE_OPT(KPOWER,Kern::Printf(">DPowerManager::ShutDownTimeoutFn"));
       
   348 	NFastSemaphore* sem = (NFastSemaphore*)aArg;
       
   349 #ifdef _DEBUG_POWER
       
   350 	NKern::FSSignal(sem);
       
   351 #else
       
   352 	TUint SignalCount = __e32_atomic_load_acq32(&(PowerManager->iPendingShutdownCount));
       
   353 	DPowerHandler* ph = PowerManager->iHandlers;
       
   354 	do
       
   355 		{
       
   356 		ph->iSem = NULL; 
       
   357 		ph = ph->iPrev;
       
   358 		}while(ph != PowerManager->iHandlers);
       
   359 
       
   360 	__e32_atomic_store_rel32(&(PowerManager->iPendingShutdownCount), (TUint)ESHUTDOWN_TIMEOUT); // = -1
       
   361 	NKern::FSSignalN(sem,SignalCount);
       
   362 
       
   363 	__KTRACE_OPT(KPOWER,Kern::Printf("<DPowerManager::ShutDownTimeoutFn"));
       
   364 #endif
       
   365 	}
       
   366 
   332 TInt DPowerManager::PowerDown()
   367 TInt DPowerManager::PowerDown()
   333 	{ // called by ExecHandler 
   368 	{ // called by ExecHandler 
   334 	__KTRACE_OPT(KPOWER,Kern::Printf(">PowerManger::PowerDown(0x%x) Enter", iPowerController->iTargetState));
   369 	__KTRACE_OPT(KPOWER,Kern::Printf(">PowerManger::PowerDown(0x%x) Enter", iPowerController->iTargetState));
   335 	__ASSERT_CRITICAL;
   370 	__ASSERT_CRITICAL;
   336 
   371 
   342 		Unlock();
   377 		Unlock();
   343 		return KErrNotReady;
   378 		return KErrNotReady;
   344 		}
   379 		}
   345 
   380 
   346     __PM_ASSERT(iHandlers);
   381     __PM_ASSERT(iHandlers);
   347 	NFastSemaphore sem(0);
   382 	NFastSemaphore shutdownSem(0);
       
   383 	NTimer ntimer;
       
   384 	TDfc dfc(ShutDownTimeoutFn, &shutdownSem);
       
   385 #ifndef _DEBUG_POWER	
       
   386 	iPendingShutdownCount = 0;
       
   387 #endif	
   348 	DPowerHandler* ph = iHandlers;
   388 	DPowerHandler* ph = iHandlers;
   349 	//Power down in reverse order of handle registration.
   389 	//Power down in reverse order of handle registration.
   350 	do
   390 	do
   351 		{
   391 		{
   352 #ifdef _DEBUG_POWER
   392 #ifdef _DEBUG_POWER
   353 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   393 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   354 #endif
   394 #endif
   355 		ph->iSem = &sem;
   395 		ph->iSem = &shutdownSem; 
   356 		ph->PowerDown(iPowerController->iTargetState);
   396 		ph->PowerDown(iPowerController->iTargetState);
   357 #ifdef _DEBUG_POWER
   397 #ifndef _DEBUG_POWER		
   358 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   398 		iPendingShutdownCount++; 
   359 		NKern::FSWait(&sem);	// power down drivers one after another to simplify debug
   399 #else
   360 		__PM_ASSERT(!ph->iSem);
   400 		if(iPslShutdownTimeoutMs>0)
   361 		__PM_ASSERT(ph->iStatus & EDone);
   401 			{
   362 		ph->iStatus &= ~EDone;
   402 		    // Fire shut down timeout timer			
   363 #endif
   403 			ntimer.OneShot(iPslShutdownTimeoutMs, dfc);
       
   404 			}
       
   405 
       
   406 		NKern::FSWait(&shutdownSem);	// power down drivers one after another to simplify debug
       
   407 		__e32_atomic_and_ord32(&(ph->iStatus), ~DPowerHandler::EDone);
       
   408 
       
   409 		// timeout condition
       
   410 		if(iPslShutdownTimeoutMs>0 && ph->iSem)
       
   411 			{
       
   412 			__e32_atomic_store_ord_ptr(&ph->iSem, 0);
       
   413 			}
       
   414 		ntimer.Cancel();
       
   415 #endif		
   364 		ph = ph->iPrev;
   416 		ph = ph->iPrev;
   365 		}while(ph != iHandlers);
   417 		}while(ph != iHandlers);
   366 
   418 
   367 #ifndef _DEBUG_POWER
   419 #ifndef _DEBUG_POWER
       
   420 	if(iPslShutdownTimeoutMs>0)
       
   421 		{
       
   422 		// Fire shut down timeout timer
       
   423 		ntimer.OneShot(iPslShutdownTimeoutMs, dfc);
       
   424 		}
       
   425 
   368 	ph = iHandlers;
   426 	ph = iHandlers;
   369 	do
   427 	do
   370 		{
   428 		{
   371 		NKern::FSWait(&sem);
   429 		NKern::FSWait(&shutdownSem);
       
   430 		if(__e32_atomic_load_acq32(&iPendingShutdownCount)==ESHUTDOWN_TIMEOUT)
       
   431 			{
       
   432 			iPendingShutdownCount = 0;
       
   433 			NKern::Lock();
       
   434 			shutdownSem.Reset(); // iPendingShutdownCount could be altered while ShutDownTimeoutFn is running
       
   435 		       			     // reset it to make sure shutdownSem is completely clean.	
       
   436 			NKern::Unlock();
       
   437 			break;
       
   438 			}
       
   439 		__e32_atomic_add_ord32(&iPendingShutdownCount, (TUint)(~0x0)); // iPendingShutDownCount--;
   372 		ph = ph->iPrev;
   440 		ph = ph->iPrev;
   373 		}while(ph != iHandlers);
   441 		}while(ph != iHandlers);
       
   442 
       
   443 	ntimer.Cancel();
       
   444 	
   374 #endif
   445 #endif
   375 
   446 
   376 	TTickQ::Wait();
   447 	TTickQ::Wait();
   377 
   448 
   378 	iPowerController->PowerDown(K::SecondQ->WakeupTime());
   449 	iPowerController->PowerDown(K::SecondQ->WakeupTime());
   380 	iPowerController->iTargetState = EPwActive;
   451 	iPowerController->iTargetState = EPwActive;
   381 
   452 
   382 	K::SecondQ->WakeUp();
   453 	K::SecondQ->WakeUp();
   383 	TTickQ::Signal();
   454 	TTickQ::Signal();
   384 
   455 
       
   456 	NFastSemaphore powerupSem(0);
       
   457 
   385 	ph = iHandlers->iNext;
   458 	ph = iHandlers->iNext;
   386 	//Power up in same order of handle registration.
   459 	//Power up in same order of handle registration.
   387 	do
   460 	do
   388 		{
   461 		{
   389 #ifdef _DEBUG_POWER
   462 #ifdef _DEBUG_POWER
   390 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   463 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   391 #endif
   464 #endif
   392 		ph->iSem = &sem;
   465 		ph->iSem = &powerupSem;
   393 		ph->PowerUp();
   466 		ph->PowerUp();
   394 #ifdef _DEBUG_POWER
   467 #ifdef _DEBUG_POWER
   395 		__PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
   468 		NKern::FSWait(&powerupSem);	// power down drivers one after another to simplify debug
   396 		NKern::FSWait(&sem);	// power down drivers one after another to simplify debug
       
   397 		__PM_ASSERT(!ph->iSem);
   469 		__PM_ASSERT(!ph->iSem);
   398 		__PM_ASSERT(ph->iStatus & EDone);
   470 		__PM_ASSERT(ph->iStatus & DPowerHandler::EDone);
   399 		ph->iStatus &= ~EDone;
   471 		ph->iStatus &= ~DPowerHandler::EDone;
   400 #endif
   472 #endif
   401 		ph = ph->iNext;
   473 		ph = ph->iNext;
   402 		}while(ph != iHandlers->iNext);
   474 		}while(ph != iHandlers->iNext);
   403 
   475 
   404 #ifndef _DEBUG_POWER
   476 #ifndef _DEBUG_POWER
   405 	ph = iHandlers->iNext;
   477 	ph = iHandlers->iNext;
   406 	do
   478 	do
   407 		{
   479 		{
   408 		NKern::FSWait(&sem);
   480 		NKern::FSWait(&powerupSem);
   409 		ph = ph->iNext;
   481 		ph = ph->iNext;
   410 		}while(ph != iHandlers->iNext);
   482 		}while(ph != iHandlers->iNext);
   411 #endif
   483 #endif
   412 
   484 
   413 	// complete wakeup notification request if any
   485 	// complete wakeup notification request if any
   417 
   489 
   418 	__KTRACE_OPT(KPOWER,Kern::Printf("<PowerManger::PowerDown() Leave"));
   490 	__KTRACE_OPT(KPOWER,Kern::Printf("<PowerManger::PowerDown() Leave"));
   419 
   491 
   420 	return KErrNone;
   492 	return KErrNone;
   421 	}	
   493 	}	
       
   494 
   422 
   495 
   423 /******************************************************************************
   496 /******************************************************************************
   424  * Power Handlers
   497  * Power Handlers
   425  ******************************************************************************/
   498  ******************************************************************************/
   426 
   499 
   576 	}
   649 	}
   577 
   650 
   578 
   651 
   579 
   652 
   580 /**	@deprecated, no replacement	*/
   653 /**	@deprecated, no replacement	*/
   581 EXPORT_C void DPowerHandler::DeltaCurrentConsumption(TInt aDelta)
   654 EXPORT_C void DPowerHandler::DeltaCurrentConsumption(TInt /* aDelta */)
   582 	{
   655 	{
   583 	__e32_atomic_add_ord32(&iCurrent, aDelta);
       
   584 	__PM_ASSERT(iCurrent >= 0);
       
   585 	__e32_atomic_add_ord32(&PowerManager->iTotalCurrent, aDelta);
       
   586 	__PM_ASSERT(PowerManager->iTotalCurrent >= 0);
       
   587 	}
   656 	}
   588 
   657 
   589 /**	@deprecated, no replacement	*/
   658 /**	@deprecated, no replacement	*/
   590 EXPORT_C void DPowerHandler::SetCurrentConsumption(TInt aCurrent)
   659 EXPORT_C void DPowerHandler::SetCurrentConsumption(TInt /* aCurrent */)
   591 	{
   660 	{
   592 	__PM_ASSERT(aCurrent >= 0);
       
   593 	TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrent, aCurrent);
       
   594 	TInt delta = aCurrent - old;
       
   595 	__e32_atomic_add_ord32(&PowerManager->iTotalCurrent, delta);
       
   596 	__PM_ASSERT(PowerManager->iTotalCurrent >= 0);
       
   597 	}
   661 	}
   598 
   662 
   599 /******************************************************************************
   663 /******************************************************************************
   600  * Power Controller
   664  * Power Controller
   601  ******************************************************************************/
   665  ******************************************************************************/
   648 	PowerManager->iPowerController = this;
   712 	PowerManager->iPowerController = this;
   649 #ifndef __X86__
   713 #ifndef __X86__
   650 	TPowerController::ThePowerController = this;
   714 	TPowerController::ThePowerController = this;
   651 #endif
   715 #endif
   652 	K::PowerModel = PowerManager;
   716 	K::PowerModel = PowerManager;
       
   717 	}
       
   718 
       
   719 /**
       
   720 Registers this power controller object with the power manager.
       
   721 
       
   722 The power manager can only use the power controller after registration.
       
   723 
       
   724 @param aShutdownTimeoutMs The kernel shut down time out value in msec.
       
   725 
       
   726 @pre Calling thread must be in a critical section.
       
   727 @pre No fast mutex can be held.
       
   728 @pre Call in a thread context.
       
   729 @pre Kernel must be unlocked
       
   730 @pre interrupts enabled
       
   731 */
       
   732 EXPORT_C void DPowerController::Register(TUint aShutdownTimeoutMs)
       
   733 	{
       
   734 	PowerManager->iPslShutdownTimeoutMs = aShutdownTimeoutMs;
       
   735 	Register();
   653 	}
   736 	}
   654 
   737 
   655 #ifndef __X86__
   738 #ifndef __X86__
   656 /**
   739 /**
   657 Registers resource controller with power controller
   740 Registers resource controller with power controller