kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp
changeset 31 56f325a607ea
parent 0 a41df078684a
child 244 a77889bee936
--- a/kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp	Mon Dec 21 16:14:42 2009 +0000
+++ b/kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp	Wed Dec 23 11:43:31 2009 +0000
@@ -44,7 +44,7 @@
 			LIST_PUSH(iResourceLevelPool, &pCL[count], iNextInList);
 		iResourceLevelPoolCount= (TUint16)(iResourceLevelPoolCount + (iStaticResDependencyCount / 2));
 #ifdef PRM_INSTRUMENTATION_MACRO
-		TUint size = allocCount * 4;
+		TUint size = allocCount * sizeof(SPowerResourceClientLevel);
 		PRM_MEMORY_USAGE_TRACE
 #endif
 		}
@@ -300,7 +300,7 @@
 		aClientPtr->iDynamicResCount++;
 		}
 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterDynamicResource, resource ID = 0x%x", 
-		                                                                                  aDynamicResourceId));
+		                                                                                  *aDynamicResourceId));
 #ifdef PRM_INSTRUMENTATION_MACRO
 	PRM_REGISTER_DYNAMIC_RESOURCE_TRACE
 #endif
@@ -501,8 +501,7 @@
 TInt DPowerResourceController::DoRegisterStaticResourcesDependency(DStaticPowerResourceD**& aStaticResourceDArray, 
 																    TUint16& aStaticResourceDCount)
 	{
-	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default \
-		                                                               implementation"));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default implementation"));
 	aStaticResourceDArray = NULL;
 	aStaticResourceDCount = 0;
 	return KErrNone;
@@ -923,21 +922,267 @@
 */
 TInt DStaticPowerResourceD::HandleChangePropagation(TPowerRequest aRequest, TPropagation aProp, TUint aOriginatorId, const TDesC8& aOriginatorName)
 	{
+	TInt result = KErrNone;
+	result = PowerResourceController->HandleResourceChange(aRequest, aProp, aOriginatorId, aOriginatorName, this);
+	return result;
+	}
+//Function to change the resource state of dependency resource. 
+TInt DPowerResourceController::HandleResourceChange(TPowerRequest &aRequest, TPropagation aProp, TUint aOriginatorId, 
+													const TDesC8& aOriginatorName, DStaticPowerResourceD* aResource)
+	{
 	static TUint16 clientLevelCount = 0;
 	DStaticPowerResourceD* pDR = (DStaticPowerResourceD*)aRequest.Resource();
+	DStaticPowerResourceD* pDepRes = NULL;
+	SNode* dependencyList = NULL;
+	TPowerRequest depRequest;
 	TInt result = KErrNone;
 	TInt resState;
-	TPowerRequest depRequest;
 	depRequest.ReqType() = TPowerRequest::EChange;
 	depRequest.ResourceCb() = NULL;
 	depRequest.ReturnCode() = KErrNone;
 	depRequest.RequiresChange() = EFalse;
-	DStaticPowerResourceD* pDepRes = NULL;
-	TBool traceEnabled = EFalse;
+
+	if(pDR->iResourceId & KIdMaskDynamic)
+		dependencyList = ((DDynamicPowerResourceD*)pDR)->iDependencyList;
+	else
+		dependencyList = pDR->iDependencyList;
+	switch(aProp)																									
+		{																											
+		case EChangeStart:																							
+			{
+			if(!dependencyList) /*No dependents so change state of the resource*/
+				{																									
+				aRequest.ReturnCode() = pDR->DoRequest(aRequest);													
+				if(aRequest.ReturnCode() == KErrNone)																
+					{																								
+					aResource->iCachedLevel = aRequest.Level();																
+					aResource->iLevelOwnerId = aRequest.ClientId();															
+					if(aResource->iIdleListEntry)																				
+						{																							
+						aResource->iIdleListEntry->iCurrentLevel = aRequest.Level();											
+						aResource->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();										
+						}			
+					CompleteNotifications(aRequest.ClientId(), pDR,									
+							aRequest.Level(), aRequest.ReturnCode(), aRequest.ClientId());							
+					}																								
+					break;																		
+				}					
+			depRequest.ResourceId() = aRequest.ResourceId();														
+			depRequest.ClientId() = aRequest.ResourceId();															
+			depRequest.Level() = aRequest.Level();																	
+			depRequest.Resource() = pDR;
+			result = pDR->HandleChangePropagation(depRequest, ECheckChangeAllowed, aOriginatorId, aOriginatorName);	
+			if(result != KErrNone)																					
+				return result;																						
+			/*Adjust resource client level*/																		
+			if(clientLevelCount)																					
+				{					
+				result = ReserveClientLevelPoolCount(clientLevelCount);								
+				if(result != KErrNone)																				
+					return result;																					
+				}																									
+			/*Resource change of dependents */																		
+			pDR->HandleChangePropagation(aRequest, ERequestStateChange, aOriginatorId, aOriginatorName);				
+			/*Notification to dependents */																			
+			pDR->HandleChangePropagation(aRequest, EIssueNotifications, aOriginatorId, aOriginatorName);				
+			break;																									
+			}																										
+		case ECheckChangeAllowed:																					
+			{																										
+			TChangePropagationStatus status;																		
+			for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)					
+				{																									
+				pDepRes = depNode->iResource;													
+				if((aRequest.ClientId() & KIdMaskResourceWithDependencies) &&										
+						(pDepRes->iResourceId == (TUint)aRequest.ClientId()))										
+					continue;	
+				/*Resource need not change if it is already in that state, so continue with							
+						another dependent state.*/																	
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					status = ((DDynamicPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),		
+																				aRequest.Level(), resState);		
+				else																								
+					status = ((DStaticPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),		
+																					aRequest.Level(), resState);	
+				if((status == ENoChange) || (pDepRes->iCachedLevel == resState))									
+					{																								
+					depNode->iRequiresChange = EFalse;																
+					continue;																						
+					}																								
+				if(status == EChangeNotAccepted)																	
+					return KErrPermissionDenied;	
+				depRequest.ResourceId() = pDepRes->iResourceId;														
+				depRequest.ClientId() = aRequest.ResourceId(); /*ID of the dependent resource */					
+				depRequest.Level() = resState;																		
+				depRequest.Resource() = pDepRes;		
+				/*Check resource client list and resource list to see whether change is allowed.*/					
+				if(pDepRes->Sense() == DStaticPowerResource::ECustom)												
+					{																								
+					/*Call custom function to check whether change is allowed.*/									
+					if(pDepRes->iResourceId & KIdMaskDynamic)														
+						depRequest.RequiresChange() = ((DDynamicPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),	
+							aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,		
+									(TAny*)&((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, NULL);				
+					else																							
+						depRequest.RequiresChange() = ((DStaticPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),		
+							aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,		
+									(TAny*)&((DStaticPowerResourceD*)pDepRes)->iResourceClientList, NULL);				
+					if(!depRequest.RequiresChange())																
+						return KErrPermissionDenied;																
+					}						
+				SPowerResourceClientLevel*pN=NULL;																	
+				for(SDblQueLink* pNL=pDepRes->iClientList.First();pNL!=&pDepRes->iClientList.iA; pNL=pNL->iNext)	
+					{																								
+					pN = (SPowerResourceClientLevel*)pNL;															
+					if(pDepRes->Sense() == DStaticPowerResource::EPositive)											
+						{																							
+						if(pN->iLevel > depRequest.Level())															
+							return KErrPermissionDenied;															
+						}																							
+					else if(pDepRes->Sense() == DStaticPowerResource::ENegative)									
+						{																							
+						if(pN->iLevel < depRequest.Level())															
+							return KErrPermissionDenied;															
+						}																							
+					}																								
+				/*check through the resource client level */														
+				SPowerResourceClientLevel*pCL = NULL;																
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;									
+				else																								
+					pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;									
+				for(; pCL != NULL; pCL = pCL->iNextInList)															
+					{																								
+					if(pCL->iClientId == pDR->iResourceId)															
+						break;																						
+					}																								
+				if(!pCL)																							
+					clientLevelCount++;																				
+				/*check dependent resource client list & resource list to see whether change is allowed */			
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					result = ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,				
+																ECheckChangeAllowed, aOriginatorId, aOriginatorName);	
+				else																								
+					result = ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,					
+											ECheckChangeAllowed, aOriginatorId, aOriginatorName);						
+				if(result != KErrNone)																				
+					return result;																					
+				depNode->iPropagatedLevel = resState;																
+				depNode->iRequiresChange = ETrue;																	
+				}																									
+			break;																									
+			}																										
+		case ERequestStateChange:																					
+			{																										
+			SPowerResourceClientLevel* pCL = NULL;																	
+			for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)					
+				{																									
+				pDepRes = depNode->iResource;													
+				if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))				
+					continue;																						
+				depRequest.ResourceId() = pDepRes->iResourceId;														
+				depRequest.ClientId() = aRequest.ResourceId();														
+				depRequest.Level() = depNode->iPropagatedLevel;														
+				depRequest.Resource() = pDepRes;									
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,	
+																					aOriginatorId, aOriginatorName);	
+				else																								
+					((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,		
+																					aOriginatorId, aOriginatorName);	
+				/*Update level if resource client level is already present for this resource.*/						
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;									
+				else																								
+					pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;									
+				for(; pCL != NULL; pCL = pCL->iNextInList)															
+					{																								
+					if(pCL->iClientId == pDR->iResourceId)															
+						{																							
+						pCL->iLevel = depNode->iPropagatedLevel;													
+						break;																						
+						}																							
+					}																								
+				if(!pCL) /*Create a new resource client level*/														
+					{																								
+					RemoveClientLevelFromPool(pCL);													
+					pCL->iClientId = pDR->iResourceId;																
+					pCL->iResourceId = pDepRes->iResourceId;														
+					pCL->iLevel = depNode->iPropagatedLevel;														
+					if(pDepRes->iResourceId & KIdMaskDynamic)														
+						{																							
+						LIST_PUSH(((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);		
+						}																							
+					else																							
+						{																							
+						LIST_PUSH(((DStaticPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);		
+						}																							
+					clientLevelCount--;																				
+					}																								
+				}	
+#ifdef PRM_INSTRUMENTATION_MACRO			
+			if(aRequest.ClientId() & KIdMaskResourceWithDependencies)								
+				{																									
+				SPowerResourceClient res;																			
+				SPowerResourceClient* pC = &res;																	
+				pC->iClientId = aRequest.ClientId();																
+				pC->iName = &KParentResource;																		
+				DStaticPowerResource*pR = (DStaticPowerResource*)pDR;												
+				TUint aResourceId = pDR->iResourceId;																
+				TInt aNewState = aRequest.Level();																	
+				PRM_CLIENT_CHANGE_STATE_START_TRACE																	
+				}																									
+#endif
+				aResource->DoRequest(aRequest);																				
 #ifdef PRM_INSTRUMENTATION_MACRO
-	traceEnabled = ETrue;
-#endif
-	HANDLE_CHANGE_PROPAGATION(PowerResourceController, DStaticPowerResourceD*, traceEnabled, aOriginatorId, aOriginatorName)
+			if(aRequest.ClientId() & KIdMaskResourceWithDependencies)								
+				{																									
+				SPowerResourceClient res;																			
+				SPowerResourceClient* pC = &res;																	
+				pC->iClientId = aRequest.ClientId();																
+				pC->iName = &KParentResource;																		
+				DStaticPowerResource*pR = (DStaticPowerResource*)pDR;												
+				TUint aResourceId = pDR->iResourceId;																
+				TInt aNewState = aRequest.Level();																	
+				TInt r = KErrNone;																					
+				PRM_CLIENT_CHANGE_STATE_END_TRACE																	
+				}													
+#endif												
+			pDR->iCachedLevel = aRequest.Level();																	
+			pDR->iLevelOwnerId = aRequest.ClientId();																
+			if(pDR->iIdleListEntry)																					
+				{																									
+				pDR->iIdleListEntry->iCurrentLevel = aRequest.Level();												
+				pDR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();											
+				}									
+			break;																									
+			}																										
+		case EIssueNotifications:																					
+			{																										
+			for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)					
+				{																									
+				pDepRes = depNode->iResource;													
+				if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))				
+					continue;																						
+				depRequest.ResourceId() = pDepRes->iResourceId;														
+				depRequest.ClientId() = pDepRes->iLevelOwnerId;														
+				depRequest.Level() = pDepRes->iCachedLevel;															
+				depRequest.Resource() = pDepRes;																	
+				if(pDepRes->iResourceId & KIdMaskDynamic)															
+					((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,	
+																					aOriginatorId, aOriginatorName);	
+				else																								
+					((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,		
+																					aOriginatorId, aOriginatorName);	
+				}							
+			CompleteNotifications(aRequest.ClientId(), pDR, aRequest.Level(), KErrNone,				
+																					aRequest.ClientId());			
+			break;																									
+			}																										
+		default:																									
+			return KErrNotSupported;																				
+		}																											
+	return result;
 	}