os/kernelhwsrv/kernel/eka/drivers/resourceman/rescontrol_export.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\resourceman\rescontrol_export.cpp
    15 // 
    16 //
    17 
    18 #include <drivers/resourcecontrol.h>
    19 
    20 #ifdef DEBUG_VERSION
    21 #define GET_CRITICAL_SECTION_COUNT(thread)				\
    22 	TInt CsCount = thread.iNThread.iCsCount;
    23 
    24 #define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)			\
    25 	if(thread.iNThread.iCsCount != CsCount)						\
    26 		Kern::Fault("PowerResourceController", __LINE__);		\
    27 	if(pRC->iResourceMutex->iHoldCount != 0)					\
    28 		Kern::Fault("PowerResourceController", __LINE__);	
    29 #else
    30 #define GET_CRITICAL_SECTION_COUNT(thread)
    31 #define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
    32 #endif
    33 
    34 /**
    35 	@publishedPartner
    36 	@prototype 9.5
    37 	Kernel extension or variants can call this API to set the post bool value without registering
    38 	as client with the resource controller. This can be used by the resource controller PSL to set the
    39 	specified static resources to appropriate value before resource controller is fully initialized.
    40 	@param aResId ID of the resource whose level should be set after initialisation
    41 	@param aLevel Resource level to set
    42 	@return KErrNone, if operation is success
    43 			KErrNotFound, if resource ID could not be found in the static resource array.
    44 			KErrNotSupported, if this API is called after resource controller is fully initialized
    45 	*/
    46 EXPORT_C TInt DPowerResourceController::PostBootLevel(TUint aResId, TInt aLevel)
    47 	{
    48 #ifdef DEBUG_VERSION
    49 	DThread& thread = Kern::CurrentThread();
    50 	GET_CRITICAL_SECTION_COUNT(thread)
    51 #endif
    52     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::PostBootLevel, aResId = 0x%x, aLevel = %d", 
    53 	                                                                          aResId, aLevel));
    54     DPowerResourceController* pRC = TInterface::GetPowerResourceController();
    55 	if(!pRC)
    56 		return KErrNotFound;
    57 	pRC->Lock();
    58     CHECK_CONTEXT(thread)
    59 	//Accept the postboot level only if issued before controller is fully initialised.
    60 	if(pRC->iInitialised == EResConStartupCompleted)
    61 		{
    62 		pRC->UnLock();
    63 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
    64 		return KErrNotSupported;
    65 		}	
    66 #ifndef PRM_ENABLE_EXTENDED_VERSION
    67     // coverity[deref_ptr]
    68     // aResId is checked to be more than the array entries before dereferencing pRC->iStaticResourceArray
    69 	if((!aResId) || (aResId > pRC->iStaticResourceArrayEntries) || (!pRC->iStaticResourceArray[aResId-1]))
    70 		{
    71 		pRC->UnLock();
    72 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
    73 		return KErrNotFound;
    74 		}
    75 #else
    76 	if(!aResId || ((aResId & KIdMaskResourceWithDependencies) && ((aResId & ID_INDEX_BIT_MASK) > pRC->iStaticResDependencyCount)) 
    77 				|| (!(aResId & KIdMaskResourceWithDependencies) && ((aResId > pRC->iStaticResourceArrayEntries)
    78 				|| (!pRC->iStaticResourceArray[aResId-1]))))
    79 		{
    80 		pRC->UnLock();
    81 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
    82 		return KErrNotFound;
    83 		}
    84 	if(aResId & KIdMaskResourceWithDependencies)
    85 		{
    86 		aResId &= ID_INDEX_BIT_MASK;
    87 		DStaticPowerResource* pR = pRC->iStaticResDependencyArray[--aResId];
    88 		pR->iPostBootLevel=aLevel;
    89 		pR->iFlags |= SET_VALID_POST_BOOT_LEVEL;
    90 		}
    91 	else
    92 #endif
    93     if(pRC->iStaticResourceArray) 
    94 		{
    95 		DStaticPowerResource* pR=pRC->iStaticResourceArray[--aResId];
    96 		pR->iPostBootLevel=aLevel;
    97 		pR->iFlags |= SET_VALID_POST_BOOT_LEVEL; // To indicate valid post boot level is set.
    98 		}
    99 	pRC->UnLock();
   100 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
   101 	return KErrNone;
   102     }
   103 
   104 /** 
   105 	@publishedPartner
   106 	@prototype 9.5
   107 	Kernel extensions or variants can call this API to register the static resources before resource controller
   108 	is fully initialised.
   109 	@Param aClientId             ID of the client that is requesting resource registration
   110 	@Param aStaticResourceArray  Static resources to register with RC. 
   111 	@Param aResCount             Number of static resources to register with RC. This equals the size of the passed array.
   112 	@return KErrNone, if operation is success
   113 	        KErrAccessDenied if clientId could not be found in the current list of registered clients or if this
   114 			                 client was registered as thread relative and was not called from the same thread.
   115 			KErrNotSupported if called after resource controller is fully initialised or if called from user side proxy
   116 			                 or if the resource is dynamic or dependency resource.
   117 			KErrNoMemory     if there is insufficient memory.
   118 			KErrArgument     if passed array is null or passed number of resources count is 0.
   119 	*/
   120 EXPORT_C TInt DPowerResourceController::RegisterArrayOfStaticResources(TUint aClientId, DStaticPowerResource**& aStaticResourceArray, TUint aResCount)
   121 	{
   122 	DThread& thread = Kern::CurrentThread();
   123 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterStaticResource"));
   124     DPowerResourceController* pRC = TInterface::GetPowerResourceController();
   125 	if(!pRC)
   126 		return KErrNotFound;
   127 
   128 	if(!aStaticResourceArray || (aResCount == 0))
   129 		return KErrArgument;
   130     CHECK_CONTEXT(thread)
   131 	//Accept the registration of static resource only if issued before controller is fully initialised.
   132 	if(pRC->iInitialised == EResConStartupCompleted)
   133 		{
   134 		return KErrNotSupported;
   135 		}
   136 	//User side clients and resource with dependency are not supported.
   137 	if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
   138 		{
   139 		return KErrNotSupported;
   140 		}
   141 #ifdef PRM_ENABLE_EXTENDED_VERSION
   142 	if(aResCount == 1)
   143 		{
   144 		if((((DStaticPowerResource*)aStaticResourceArray)->iResourceId & KIdMaskResourceWithDependencies) ||
   145 										(((DStaticPowerResource*)aStaticResourceArray)->iResourceId & KIdMaskDynamic))
   146 			{
   147 			return KErrNotSupported;
   148 			}
   149 		}
   150 	else
   151 		{
   152 		for(TUint rescount = 0; rescount < aResCount; rescount++)
   153 			{
   154 			if(aStaticResourceArray[rescount] && ((aStaticResourceArray[rescount]->iResourceId & KIdMaskResourceWithDependencies) || 
   155 				                          (aStaticResourceArray[rescount]->iResourceId & KIdMaskDynamic)))
   156 				{
   157 				return KErrNotSupported;
   158 				}
   159 			}
   160 		}
   161 #endif
   162 	SPowerResourceClient* pC = pRC->iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];								
   163 	if(!pC)																										
   164 		{																										
   165 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));											
   166 		return KErrAccessDenied;																		
   167 		}																										
   168 	if(pC->iClientId != aClientId)				
   169 		{																										
   170 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID instance count does not match"));						
   171 		return KErrAccessDenied;																		
   172 		}																										
   173 	if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)															
   174 		{																										
   175 		if(pC->iThreadId != thread.iId)																				
   176 			{																									
   177 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));	
   178 			return KErrAccessDenied;																	
   179 			}																									
   180 		}
   181  
   182     TInt r = Kern::SafeReAlloc((TAny*&)pRC->iStaticResourceArray, pRC->iStaticResourceArrayEntries*sizeof(DStaticPowerResource*), 
   183 		                                         (pRC->iStaticResourceArrayEntries + aResCount)*sizeof(DStaticPowerResource*));
   184     if(r != KErrNone)
   185 		{
   186         return r;
   187 		}
   188 	if(aResCount == 1)
   189 		{
   190 		pRC->iStaticResourceArray[pRC->iStaticResourceArrayEntries++] = (DStaticPowerResource*)aStaticResourceArray;
   191 		if((DStaticPowerResource*)aStaticResourceArray)
   192 			pRC->iStaticResourceCount++;
   193 		}
   194 	else
   195 		{
   196 		for(TUint count = 0; count < aResCount; count++)
   197 			{
   198 			pRC->iStaticResourceArray[pRC->iStaticResourceArrayEntries++] = aStaticResourceArray[count];
   199 			if(aStaticResourceArray[count])
   200 				pRC->iStaticResourceCount++;
   201 			}
   202 		}
   203     return KErrNone;
   204 	}
   205 
   206 /**
   207 	@publishedPartner
   208 	@prototype 9.5
   209 	Kernel extensions or variants can call this API to register the static resources before resource controller
   210 	is fully initialized. 
   211 	@Param aClientId ID of the client that is requesting resource registration
   212 	@Param pR        Static resource to register with RC. 
   213 	@return KErrNone, if operation is success
   214 			KErrAccessDenied if clientId could not be found in the current list of registered clients or if this 
   215 							 client was registered as thread relative and was not called from the same thread. 
   216 			KErrNotSupported if called after resource controller is fully initialized or if called from user side proxy
   217 							 or if the resource is dynamic or dependency resource
   218 			KErrNoMemory if there is insufficient memory.
   219 			KErrArgument if passed array is null
   220 	*/
   221 EXPORT_C TInt DPowerResourceController::RegisterStaticResource(TUint aClientId, DStaticPowerResource* pR)
   222 	{
   223 	return RegisterArrayOfStaticResources(aClientId, (DStaticPowerResource**&)pR, 1);
   224     }
   225 
   226 /**
   227 	@publishedPartner
   228 	@prototype 9.5
   229 	This function initialises the controller. 
   230 	@return KErrNone, if operation is success or one of the system wide errors.
   231 	*/
   232 EXPORT_C TInt DPowerResourceController::InitController()
   233 	{
   234     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitController()"));
   235 	DPowerResourceController* pRC = TInterface::GetPowerResourceController();
   236 	if(!pRC)
   237 		return KErrNotFound;
   238 	if(pRC->iInitialised >= EResConInitialised)
   239 		{
   240 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("InitController already initialised %d\n", pRC->iInitialised));
   241 		return KErrNone;
   242 		}
   243     _LIT(KResMutexName, "RESCTRL");
   244     TInt r=KErrNone;
   245 	//Create the message queue
   246 	pRC->iMsgQ = new TMessageQue(DPowerResourceController::MsgQFunc, pRC, NULL, 2);
   247 	if(!pRC->iMsgQ)
   248 		return KErrNoMemory;
   249 #ifdef PRM_ENABLE_EXTENDED_VERSION
   250 	//Create the message queue for dependency resource processing.
   251 	pRC->iMsgQDependency = new TMessageQue(DPowerResourceController::MsgQDependencyFunc, pRC, NULL, 1);
   252 	if(!pRC->iMsgQDependency)
   253 		return KErrNoMemory;
   254 #endif
   255 	// Call PSL to create all static resources and populate the iStaticResourceArray with pointers to resources and
   256 	// update static resource count
   257     r=pRC->DoRegisterStaticResources(pRC->iStaticResourceArray, pRC->iStaticResourceArrayEntries);
   258     if(r!=KErrNone)
   259 		return r;
   260 	//Get the actual number of static resource registered count
   261 	for(TInt resCnt = 0; resCnt < pRC->iStaticResourceArrayEntries; resCnt++)
   262 		{
   263 		if(pRC->iStaticResourceArray[resCnt])
   264 			pRC->iStaticResourceCount++;
   265 		}
   266 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Actual number of static resource registered = %d\n", pRC->iStaticResourceCount));
   267 #ifdef PRM_INSTRUMENTATION_MACRO
   268 	// Btrace output of resource information of each resource.
   269 	DStaticPowerResource* pR = NULL;
   270 	TPowerResourceInfoBuf01 resInfo;
   271 	TPowerResourceInfoV01 *pResInfo;
   272 	for(TInt resCount = 0; resCount < pRC->iStaticResourceArrayEntries; resCount++)
   273 		{
   274 		pR = pRC->iStaticResourceArray[resCount];
   275 		if(!pR)
   276 			continue;
   277 		pR->GetInfo((TDes8*)resInfo.Ptr());
   278 		pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
   279 		PRM_REGISTER_RESOURCE_TRACE
   280 		}
   281 #endif
   282 
   283 #ifdef PRM_ENABLE_EXTENDED_VERSION
   284 	//Call PSL to register static resources with dependency if any exists
   285 	r = pRC->DoRegisterStaticResourcesDependency(pRC->iStaticResDependencyArray, pRC->iStaticResDependencyCount);
   286 	if(r != KErrNone)
   287 		return r;
   288 	if(pRC->iStaticResDependencyCount)
   289 		{
   290 		DStaticPowerResourceD* pRD = NULL;
   291 		TUint count;
   292 		//Assign resource index in resource id
   293 		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
   294 			{
   295 			pRD = pRC->iStaticResDependencyArray[count];
   296 			if(!pRD)
   297 				Panic(DPowerResourceController::ERegisteringDependentStaticResourceWithHoles);
   298 			pRD->iResourceId |= ((count + 1) & ID_INDEX_BIT_MASK);
   299 			}
   300 		//Check for dependency closed loops
   301 		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
   302 			{
   303 			pRD = pRC->iStaticResDependencyArray[count];
   304 			if(!(pRD->iResourceId & KIdMaskStaticWithDependencies))
   305 				Panic(DPowerResourceController::ERegisteringNonDependentStaticResource);
   306 			//Upgrade latency state change from instantaneous to long latency 
   307 			if(!pRD->LatencySet()) 
   308 				pRD->iFlags |= KLongLatencySet;
   309 			pRC->CheckForDependencyLoop(pRD, pRD->iResourceId, pRD->iResourceId);
   310 			}
   311 #ifdef PRM_INSTRUMENTATION_MACRO
   312 		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
   313 			{
   314 			pR = pRC->iStaticResDependencyArray[count];
   315 			pR->GetInfo((TDes8*)resInfo.Ptr());
   316 			pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
   317 			PRM_REGISTER_STATIC_RESOURCE_WITH_DEPENDENCY_TRACE
   318 			}
   319 #endif
   320 		}
   321 #endif // PRM_ENABLE_EXTENDED_VERSION
   322 	// Create mutex object
   323 	r=Kern::MutexCreate(pRC->iResourceMutex, KResMutexName, KMutexOrdResourceManager);
   324 	if(r==KErrNone) // Call PSL to create DFC queue and creation of pools with the help API's provided by generic layer.
   325 		r=pRC->DoInitController();
   326 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitController()"));
   327 	if(r == KErrNone)
   328 		{
   329 		pRC->iInitialised = EResConInitialised;
   330 	    if(pRC->iDfcQ)
   331 			pRC->iMsgQ->Receive();
   332 #ifdef PRM_ENABLE_EXTENDED_VERSION
   333 	    if(pRC->iDfcQDependency)
   334 			pRC->iMsgQDependency->Receive();
   335 #endif
   336 		}
   337     return r;
   338 	}