Beispiel #1
0
// :FIXME: improve API
TInt DKdaChannel::GetCodeSegs(RMinKda::TCodeSnapshotParams* aParams)
	{
	RMinKda::TCodeSnapshotParams params;
	umemget32(&params, aParams, sizeof(params));

	TInt maxcount;
	umemget32(&maxcount, params.iCountPtr, sizeof(maxcount));

	__KTRACE_OPT(KDEBUGGER, Kern::Printf(">DKdaChannel::GetCodeSegs pid=%d maxcount=%d", params.iPid, maxcount));
	
	__ASSERT_DEBUG(! iTempObj, Kern::Fault(KFault, __LINE__));
	TInt r = OpenTempObject(params.iPid, EProcess);
	if (r != KErrNone)
		{
		__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DKdaChannel::GetCodeSegs process not found"));
		return r;
		}
		
	DProcess* pP = (DProcess*)iTempObj;

	Kern::AccessCode();

	SDblQue q;
	TInt actcount = pP->TraverseCodeSegs(&q, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);

	CloseTempObject();

	TInt n = Min(actcount, maxcount);
	SDblQueLink* pL = q.iA.iNext;
	r = KErrNone;
	for (TInt i=0; i<n; ++i, pL = pL->iNext)
		{
		DCodeSeg* pS = _LOFF(pL, DCodeSeg, iTempLink);
		XTRAP(r, XT_DEFAULT, umemput32(params.iHandles + i, &pS, sizeof(TAny*)));
		if (r != KErrNone)
			break;
		}

	DCodeSeg::EmptyQueue(q, DCodeSeg::EMarkDebug);

	Kern::EndAccessCode();

	if (r == KErrBadDescriptor)
		Kern::PanicCurrentThread(KLitKernExec, ECausedException);
	umemput32(params.iCountPtr, &actcount, sizeof(actcount));

	__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DKdaChannel::GetCodeSegs actcount=%d", actcount));
	return r;
	}
Beispiel #2
0
TInt DKdaChannel::GetThreadInfo(TUint aTid, TAny* aInfo)
	{
	TInt r = OpenTempObject(aTid, EThread);
	if (r == KErrNone)
		{
		DThread* pT = (DThread*)iTempObj;
		TDbgThreadInfo info;
		pT->FullName(info.iFullName);
		info.iPid = pT->iOwningProcess->iId;
		info.iStackBase = pT->iUserStackRunAddress;
		info.iStackSize = pT->iUserStackSize;
		info.iExitCategory = pT->iExitCategory;
		info.iExitReason = pT->iExitReason;
		GetThreadCpuInfo(pT, info.iCpu);
		umemput32(aInfo, &info, sizeof(info));
		CloseTempObject();
		}
	return r;
	}
Beispiel #3
0
// :FIXME: improve API
TInt DKdaChannel::GetCodeSegInfo(RMinKda::TCodeInfoParams* aParams)
	{
	RMinKda::TCodeInfoParams params;
	umemget32(&params, aParams, sizeof(params));

	// :FIXME: Currently code segments are always loaded at the same
	// location in every address space.  Consequently we can ignore
	// the PID provided by the client.
	DProcess* pP = NULL;

	TInt r = KErrNotFound;
	TFileName	nameBuffer;
	nameBuffer.Zero();
	Kern::AccessCode();
	DCodeSeg* pS = DCodeSeg::VerifyHandle(params.iHandle);
	if (pS)
		{
		TModuleMemoryInfo mmi;
		r = pS->GetMemoryInfo(mmi, pP);
		if (r == KErrNone)
			{
			params.iCodeBase = mmi.iCodeBase;
			params.iCodeSize = mmi.iCodeSize;
			XTRAP(r, XT_DEFAULT, nameBuffer.Append(*(pS->iFileName)));
			}
		}
	Kern::EndAccessCode();
	Kern::KUDesPut(*(params.iPathPtr), nameBuffer);
	if (r == KErrBadDescriptor)
		Kern::PanicCurrentThread(KLitKernExec, ECausedException);

	if (r == KErrNone)
		umemput32(aParams, &params, sizeof(params));

	return r;
	}
Beispiel #4
0
TInt DDisplayLdd::SendControl(TMessageBase* aMsg)
	{	
	TThreadMessage& m	= *(TThreadMessage*)aMsg;
    TInt aReqNumber 	= m.iValue;
	

	//Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
		
	RDisplayChannel::TPostCount  			kernelPostCount;
	RDisplayChannel::TDisplayRotation 		kernelRotation;
	
	TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);

	TInt  kernelpack[2];	
	TInt  kernelBufferId;
	TBool kernelRotChanged;
	TInt  kernelIndex;
	
	TAny* userConfigData0 = m.Ptr0();
	TAny* userConfigData1 = m.Ptr1();
		
			
	switch (aReqNumber)
		{
		//iDisplayInfo doesn't change after the driver initialisation so copy in client thread context
		case RDisplayChannel::ECtrlGetDisplayInfo:
			umemput32(userConfigData0, &pckgInfo, sizeof(TPckgBuf<RDisplayChannel::TDisplayInfo>) );	
			return KErrNone;

		case RDisplayChannel::ECtrlPostCompositionBuffer:  		//Client should read data updated in the DFC thread.
			m.iArg[1] = &kernelPostCount;
			break;
		
		case RDisplayChannel::ECtrlPostLegacyBuffer:			//Client should read data updated in the DFC thread.
			m.iArg[1] = &kernelPostCount;			
			break;	
		
		case RDisplayChannel::ECtrlRegisterUserBuffer:			//Both the client and DFC thread need to read data.
			umemget32(&kernelpack, userConfigData0, (sizeof(TInt)*2) );
			m.iArg[0] = &kernelpack;			
			m.iArg[1] = &kernelBufferId;	
			break;
		
		case RDisplayChannel::ECtrlDeregisterUserBuffer:		//Client data should be passed to the DFC thread.	
			umemget32(&kernelBufferId, userConfigData0, sizeof(TInt) );
			m.iArg[0] = &kernelBufferId;				
			break;	
				
	 	case RDisplayChannel::ECtrlSetRotation:					//Both the client and DFC thread need to read data.
			umemget32(&kernelRotation, userConfigData0, sizeof(RDisplayChannel::TDisplayRotation) );
			m.iArg[0] = &kernelRotation;
			m.iArg[1] = &kernelRotChanged;
			break;
			
		case RDisplayChannel::ECtrlCurrentRotation:				//Client should read data updated in the DFC thread.
			m.iArg[0] = &kernelRotation;
			break;
			
		case RDisplayChannel::ECtrlGetCompositionBufferInfo:	//Both the client and DFC thread need to read data.		
			umemget32(&kernelIndex, userConfigData0, sizeof(TInt) );
			m.iArg[0] = &kernelIndex;
			m.iArg[1] = &kernelpack;		
			break;

#ifdef _DEBUG
		case RDisplayChannel::ECtrlCreateUserBuffer:
		    m.iArg[0] = userConfigData0;
            m.iArg[1] = userConfigData1;
            break;
#endif // _DEBUG

		default:
			return KErrNotSupported; 
				
		}
	
	TInt r = DLogicalChannel::SendMsg(aMsg);	
	if (r != KErrNone)
		{
		return r;
		}

	 //Copy config data from local copies to client, in context of client thread
    switch (aReqNumber)
		{					
	    case RDisplayChannel::ECtrlPostCompositionBuffer:  				
			__DEBUG_PRINT2("ECtrlPostCompositionBuffer =%d", kernelPostCount );
			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );	
			break;
		
		case RDisplayChannel::ECtrlPostLegacyBuffer:
			__DEBUG_PRINT2("ECtrlPostLegacyBuffer=%d", kernelPostCount );	
			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );			
			break;	
		
		case RDisplayChannel::ECtrlRegisterUserBuffer:
			__DEBUG_PRINT2("ECtrlRegisterUserBuffer kernelBufferId=%d", kernelBufferId );	
			umemput32(userConfigData1, &kernelBufferId, sizeof(TInt) );
			break;
		
		case RDisplayChannel::ECtrlSetRotation:
			__DEBUG_PRINT2("ECtrlSetRotation  kernelRotChanged=%d", kernelRotChanged );
			umemput32(userConfigData1, &kernelRotChanged, sizeof(TBool) );
			break;	
		
		case RDisplayChannel::ECtrlCurrentRotation:
			__DEBUG_PRINT2("ECtrlCurrentRotation kernelRotation=%d",  kernelRotation );
			umemput32(userConfigData0, &kernelRotation, sizeof(RDisplayChannel::TDisplayRotation) );
			break;
		
		case RDisplayChannel::ECtrlGetCompositionBufferInfo:				
			__DEBUG_PRINT3("ECtrlGetCompositionBufferInfo kernelpack[0] =%d and kernelpack[1] =%d",  kernelpack[0], kernelpack[1]);
			umemput32(userConfigData1, &kernelpack, (sizeof(TInt)*2) );
			break;					
		}			
	return r;
	}
Beispiel #5
0
/**
Validate, pre-process, send and post-process data for an asynchronous client request, so that data can be safely
accessed from kernel threads without the possibility of taking page faults. 

This function is called in the context of the client thread.
 
@param aMsg  The message to process.
             The iValue member of this distinguishes the message type:
			 iValue==ECloseMsg, channel close message
			 iValue==KMaxTInt, a 'DoCancel' message
			 iValue>=0, a 'DoControl' message with function number equal to iValue
			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
 
 @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
        codes.
 */ 
TInt DDisplayLdd::SendRequest(TMessageBase* aMsg)
	{
	TThreadMessage& m	=*(TThreadMessage*)aMsg;
    TInt aReqNumber 	= ~m.iValue;
	TRequestStatus* pS	=(TRequestStatus*)m.Ptr0();
	
	#ifdef _GCE_DISPLAY_DEBUG
	DThread* client 	= m.Client();
	#endif		
			
	TInt r 				= KErrNotSupported;
	TInt pendingIndex;

	/*Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
	Using thread local copies is possible even for asynchronous requests, since the values to be returned are known 
	when processing the request( inside DoRequest ) and not at a later stage.*/
	
	TInt kernelCompBuffIdx;
	TInt kernelpack[2];	
	RDisplayChannel::TPostCount  kernelCount;
	
	
	//In asynchronous requests m.Ptr0 is used for the TRequestStatus object.
	TAny* userConfigData1 = m.Ptr1();
	TAny* userConfigData2 = m.Ptr2();
	
	/*
	If the client request needs to pass some data to the DFC thread then we copy these to a thread local
	copy(created in the thread supervisor stack) and then update the message to point to that local copy. 
	If the client will have to read a value updated in the DFC thread, then the message should just be 
	updated and point to the local copy. After the request has completed the updated data will be copied
	from the local copy to the client, in the context of the client thread. 
	*/
    
    switch (aReqNumber)
		{
	    case RDisplayChannel::EReqGetCompositionBuffer:	//Client should read data updated in the DFC thread.
				m.iArg[1] = &kernelCompBuffIdx;				
				break;

        case RDisplayChannel::EReqPostUserBuffer:    	//Both the client and DFC thread need to read data.
				umemget32(&kernelpack, userConfigData1, (sizeof(TInt)*2) );
				m.iArg[1] = &kernelpack;
				m.iArg[2] = &kernelCount;
				break;		
		
		case RDisplayChannel::EReqWaitForPost:			//Client data should be passed to the DFC thread.	
				umemget32(&kernelCount, userConfigData1, sizeof(RDisplayChannel::TPostCount) );
				m.iArg[1] = &kernelCount;							
				break;
		default:
				return KErrNotSupported; 
		
		}
		
	/* 		
	The TClientRequest objects associated with each asynchronous request need to be accessed by both the client and DFC
	threads. To resolve the potential synchronization problem we maintain two seperate pointers(iClientRequest and 
	iPendingReq.iClientReq )to the same TClientRequest object. iClientRequestMutex is used to synchronise access to 
	iClientRequest from different client threads. The first client thread that acquires the mutex will set the status
	of an available TClientRequest object and send the message(call SendMsg). Consequently method DoRequest is queued for 
	execution by the DFC thread. DoRequest initialy saves iClientRequest to iPendingReq.iClientReq and queues the request. 
	Only then, the mutex is signaled. Another client thread trying to access iClientRequest will block in the mutex until
	DoRequest has updated iPendingReq.iClientReq. Even more the DFC thread only accesses iClientRequest in DoRequest and 
	then iPendingReq.iClientReq is only used, so synchronizing access to iPendingReq.iClientReq is handled by the DFC queue.
	*/
	
	// Need to be in critical section whilst holding a DMutex
	NKern::ThreadEnterCS();
	
	Kern::MutexWait(*iClientRequestMutex);	
	//Save the TRequestStatus in any available TClientRequest object for that asynchronous request.
	
	for( TInt k=0; k< KMaxQueuedRequests; k++) 
		{
		//setStatus will return KErrInUse if a previous client request hasn't completed yet.
		r = iClientRequest[aReqNumber][k]->SetStatus(pS);
		if( r == KErrNone)
			{
			pendingIndex = k;
			//The current available index for this pending request will be passed as 
			//another message argument to the DFC thread.
			m.iArg[3] =  (TAny*) pendingIndex; 
			break;
			}		 			
		}
					 						
	if (r == KErrNone)
		{
		r = DLogicalChannel::SendMsg(aMsg);
		}
	else
		{
		__DEBUG_PRINT3("Client %08x trying to issue asynchronous request %d", client, aReqNumber);
		//Fail if there aren't any available TClientRequest object
		__ASSERT_DEBUG(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));				
		}
	
	Kern::MutexSignal(*iClientRequestMutex);

    NKern::ThreadLeaveCS();
    
    //Copy config data from local copies to client, in context of client thread
    switch (aReqNumber)
		{
	    case RDisplayChannel::EReqGetCompositionBuffer:
	    		__DEBUG_PRINT2("EReqGetCompositionBuffer: kernelCompBuffIdx returned =%d",kernelCompBuffIdx);						
				umemput32(userConfigData1, &kernelCompBuffIdx, sizeof(TInt) );
				break;
				
        case RDisplayChannel::EReqPostUserBuffer:
        		__DEBUG_PRINT2("EReqPostUserBuffer: kernelCount returned = %d",kernelCount);
				umemput32(userConfigData2, &kernelCount, sizeof(RDisplayChannel::TPostCount) );	
				break;							
		}		 	
	return r;
	}