diff -r a179b74831c9 -r c1f20ce4abcf kerneltest/e32test/resourceman/d_rescontrolclisync.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/resourceman/d_rescontrolclisync.cpp Tue Aug 31 16:34:26 2010 +0300 @@ -0,0 +1,419 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\resourceman\d_rescontrolclisync.cpp +// +// + +#include +#include +#include +#include "d_rescontrolclisync.h" + +#include "resourceman_psl/rescontrol_psl.h" + +_LIT(KTestPowerRCName, "D_RESCONTROLCLISYNC.LDD"); + + +const TInt KTestResManLddThreadPriority = 0x5; +const TUint KResourceId = 16; // DMLSHLGLSPResource +const TInt KResourceMax = 65; +const TInt KResourceMin = 10; + +_LIT(KTestResManLddThread, "TestResManLddThread"); +_LIT(KTestResManLddHelperThread, "TestResManLddHelperThread"); +_LIT(KTestResManLddCallbackThread, "TestResManLddCallbackThread"); +_LIT(KResClientName1, "ResTestClient1"); +_LIT(KResClientName2, "ResTestClient2"); + +class DTestResManLdd; +/** +The logical device (factory class) for the resource manager client side test. +*/ +class DTestResManLddFactory : public DLogicalDevice + { +public: + enum { + ESignallerCallback, + EWaiterCallback + }; + DTestResManLddFactory(); + ~DTestResManLddFactory(); + virtual TInt Install(); + virtual void GetCaps(TDes8 &aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); + + NFastSemaphore iSemaphore1; // fast semaphore for helper queue + NFastSemaphore iSemaphore2; // fast semaphore for call back thread + + TInt iResourceClientRegisterCount; + TDynamicDfcQue* iLddQue; // dfc que for logical channel (also running the primary ChangeResourceState + TDynamicDfcQue* iLddHelperQue; // helper dfc que to execute the secondary ChangeResourceState + TDynamicDfcQue* iCallbackQue; // dfc que for call back + + DTestResManLdd* iChannel1; + DTestResManLdd* iChannel2; + TInt iCallbackState; + TPowerResourceCb* iAsyncResourceCallback; + }; + +/** Logical channel class for Resource manager test LDD */ +class DTestResManLdd : public DLogicalChannel + { +public: + DTestResManLdd(); + virtual ~DTestResManLdd(); + // Inherited from DLogicalChannel + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual void HandleMsg(TMessageBase* aMsg); + + DThread* iClientThreadPtr; + TRequestStatus* iStatus; + TUint iResClientId; + TDfc* iWaitAndChangeResourceDfc; + +private: + TInt DoControl(TInt aFunction, TAny* a1, TAny* a2); + TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2); + TInt DoCancel(TUint aMask); + }; + +void AsyncResourceCallbackFn(TUint /*aClientId*/, TUint /*aResourceId*/, TInt /*aLevel*/, TInt /*aLevelOwnerId*/, TInt aResult, TAny* aParam) + { + // call back function, always run on call back dfc queue + Kern::Printf(">AsyncResourceCallbackFn 0x%x", &(Kern::CurrentThread().iNThread)); + DTestResManLddFactory* pLddFactory = (DTestResManLddFactory*)aParam; + DTestResManLdd* pLdd = NULL; + + if(pLddFactory->iCallbackState == DTestResManLddFactory::ESignallerCallback) + { + pLdd = pLddFactory->iChannel1; + Kern::Printf("AsyncResourceCallbackFn cond 1 signal [#3.1]"); + NKern::FSSignal(&(pLddFactory->iSemaphore1)); + + Kern::Printf("AsyncResourceCallbackFn cond 1 wait [#3.2]"); + NKern::FSWait(&(pLddFactory->iSemaphore2)); + + Kern::Printf("AsyncResourceCallbackFn cond 1 wake up [#3.3]"); + } + else if(pLddFactory->iCallbackState == DTestResManLddFactory::EWaiterCallback) + { + pLdd = pLddFactory->iChannel2; + // aResult should be equal to KErrNone (not KErrCompletion) + Kern::Printf("AsyncResourceCallbackFn cond 2 r = %d [#2.5]", aResult); + } + else + { + Kern::Fault("AsyncResourceCallbackFn", __LINE__); + } + + Kern::RequestComplete(pLdd->iClientThreadPtr, pLdd->iStatus, aResult); + pLdd->iStatus = NULL; + Kern::Printf("WaitAndChangeResourceDfcFn 0x%x [#2.1]", &(Kern::CurrentThread().iNThread)); + DTestResManLdd* pLdd = (DTestResManLdd*)aLdd; + DTestResManLddFactory* pLddFactory = (DTestResManLddFactory*)(pLdd->iDevice); + + Kern::Printf(" WaitAndChangeResourceDfcFn - Wait for Semaphore [#2.2]"); + NKern::FSWait(&(pLddFactory->iSemaphore1)); + + Kern::Printf(" WaitAndChangeResourceDfcFn - ChangeResourceState [#2.3]"); + pLddFactory->iCallbackState = DTestResManLddFactory::EWaiterCallback; + PowerResourceManager::ChangeResourceState(pLdd->iResClientId, KResourceId, KResourceMax, pLddFactory->iAsyncResourceCallback); + + Kern::Printf(" WaitAndChangeResourceDfcFn - signal [#2.4]"); + NKern::FSSignal(&(pLddFactory->iSemaphore2)); + + delete pLdd->iWaitAndChangeResourceDfc; + Kern::Printf("Destroy(); + if(iLddHelperQue) + iLddHelperQue->Destroy(); + if(iCallbackQue) + iCallbackQue->Destroy(); + + if(iAsyncResourceCallback) + delete iAsyncResourceCallback; + } + +/** Entry point for this driver */ +DECLARE_STANDARD_LDD() + { + DTestResManLddFactory* p = new DTestResManLddFactory; + if(!p) + return NULL; + + TInt r = KErrNone; + + r = Kern::DynamicDfcQCreate(p->iLddQue, KTestResManLddThreadPriority, KTestResManLddThread); + if(r != KErrNone) + { + return NULL; + } + Kern::Printf("iLddQue 0x%x", p->iLddQue->iThread); + + r = Kern::DynamicDfcQCreate(p->iLddHelperQue, KTestResManLddThreadPriority, KTestResManLddHelperThread); + if(r != KErrNone) + { + p->iLddQue->Destroy(); + return NULL; + } + p->iSemaphore1.iOwningThread = (NThreadBase*)(p->iLddHelperQue->iThread); + Kern::Printf("iSemaphore1 owning thread 0x%x", p->iSemaphore1.iOwningThread); + + r = Kern::DynamicDfcQCreate(p->iCallbackQue, KTestResManLddThreadPriority, KTestResManLddCallbackThread); + if(r != KErrNone) + { + p->iLddQue->Destroy(); + p->iLddHelperQue->Destroy(); + return NULL; + } + p->iSemaphore2.iOwningThread = (NThreadBase*)(p->iCallbackQue->iThread); + Kern::Printf("iSemaphore2 owning thread 0x%x", p->iSemaphore2.iOwningThread); + + p->iAsyncResourceCallback = new TPowerResourceCb(AsyncResourceCallbackFn, p, + p->iCallbackQue, 5); + +#ifdef __SMP__ + NKern::ThreadSetCpuAffinity((NThread*)(p->iLddQue->iThread), 0); + NKern::ThreadSetCpuAffinity((NThread*)(p->iLddHelperQue->iThread), 0); + NKern::ThreadSetCpuAffinity((NThread*)(p->iCallbackQue->iThread), 1); +#endif + + r = DSimulatedPowerResourceController::CompleteResourceControllerInitialisation(); + if(r != KErrNone) + Kern::Fault("PRM INIT FAILED", __LINE__); + return p; + } + +/** Second stage constuctor */ +TInt DTestResManLddFactory::Install() + { + return(SetName(&KTestPowerRCName)); + } + +/** Device capabilities */ +void DTestResManLddFactory::GetCaps(TDes8& aDes)const + { + // Create a capabilities object + RTestResMan::TCaps caps; + caps.iVersion = iVersion; + // Write it back to user memory + Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps)); + } + + +TInt DTestResManLddFactory::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DTestResManLdd(); + if(!aChannel) + return KErrNoMemory; + if(!iChannel1) + iChannel1 = (DTestResManLdd*)aChannel; + else if(!iChannel2) + iChannel2 = (DTestResManLdd*)aChannel; + else + { + delete aChannel; + return KErrInUse; + } + return KErrNone; + } + +/** Constructor */ +DTestResManLdd::DTestResManLdd() + { + iClientThreadPtr=&Kern::CurrentThread(); + iResClientId = 0; + + // Increase the DThread's ref count so that it does not close without us + ((DObject*)iClientThreadPtr)->Open(); + } + +/** Destructor */ +DTestResManLdd::~DTestResManLdd() + { + Kern::SafeClose((DObject*&)iClientThreadPtr,NULL); + } + +/** Second stage constructor. */ +TInt DTestResManLdd::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer) + { + // Check version + if (!Kern::QueryVersionSupported(RTestResMan::VersionRequired(),aVer)) + return KErrNotSupported; + + SetDfcQ(((DTestResManLddFactory*)iDevice)->iLddQue); + iMsgQ.Receive(); + return KErrNone; + } + +/** Process a message for this logical channel */ +void DTestResManLdd::HandleMsg(TMessageBase* aMsg) + { + TThreadMessage& m=*(TThreadMessage*)aMsg; + TInt id=m.iValue; + + if (id==(TInt)ECloseMsg) + { + // Channel close. + m.Complete(KErrNone,EFalse); + return; + } + else if (id==KMaxTInt) + { + // DoCancel + m.Complete(KErrNone,ETrue); + return; + } + else if (id<0) + { + // DoRequest + TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); + TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2()); + if (r!=KErrNone) + Kern::RequestComplete(iClientThreadPtr,pS,r); + m.Complete(KErrNone,ETrue); + } + else + { + // DoControl + TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); + m.Complete(r,ETrue); + } + } + +/** + Process synchronous 'control' requests +*/ +TInt DTestResManLdd::DoControl(TInt aFunction, TAny* /*a1*/, TAny* /*a2*/) + { + TInt r = KErrNone; + + switch(aFunction) + { + case RTestResMan::ERegisterClient: + { + Kern::Printf("RTestResMan::ERegisterClient"); + if(iResClientId!=0) + { + r = KErrInUse; + break; + } + if(((DTestResManLddFactory*)iDevice)->iResourceClientRegisterCount==0) + { + r = PowerResourceManager::RegisterClient(iResClientId, KResClientName1); + } + else if(((DTestResManLddFactory*)iDevice)->iResourceClientRegisterCount==1) + { + r = PowerResourceManager::RegisterClient(iResClientId, KResClientName2); + } + else + r = KErrInUse; + + (((DTestResManLddFactory*)iDevice)->iResourceClientRegisterCount)++; + + break; + } + case RTestResMan::EDeRegisterClient: + { + Kern::Printf("RTestResMan::EDeRegisterClient"); + if(iResClientId==0) + { + r = KErrArgument; + break; + } + r = PowerResourceManager::DeRegisterClient(iResClientId); + break; + } + case RTestResMan::EPrintResourceInfo: + { + Kern::Printf("RTestResMan::EPrintResourceInfo"); + TPowerResourceInfoBuf01 info; + info.SetLength(0); + Kern::Printf("EPrintResourceInfo"); + r = PowerResourceManager::GetResourceInfo(iResClientId,KResourceId,&info); + Kern::Printf("EPrintResourceInfo:%S", info().iResourceName); + break; + } + default: + { + r = KErrNotSupported; + break; + } + } + return r; + + } + + +TInt DTestResManLdd::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* /*a1*/, TAny* /*a2*/) + { + TInt r = KErrNone; + + if(r != KErrNone) + Kern::RequestComplete(iClientThreadPtr, aStatus, r); + switch(aReqNo) + { + case RTestResMan::EWaitAndChangeResource: + // Queue a dfc which wait for the semaphore and then call ChangeResourceState + Kern::Printf("RTestResMan::EWaitAndChangeResource 0x%x [#1.1]", &(Kern::CurrentThread().iNThread)); + if(iStatus) + { + r = KErrInUse; + break; + } + iStatus = aStatus; + + iWaitAndChangeResourceDfc = new TDfc(WaitAndChangeResourceDfcFn, this, + ((DTestResManLddFactory*)iDevice)->iLddHelperQue, 5); + iWaitAndChangeResourceDfc->Enque(); + + break; + case RTestResMan::EChangeResourceAndSignal: + // call ChangeResourceState and signal the semaphore + Kern::Printf("RTestResMan::EChangeResourceAndSignal 0x%x [#1.2]", &(Kern::CurrentThread().iNThread)); + if(iStatus) + { + r = KErrInUse; + break; + } + iStatus = aStatus; + PowerResourceManager::ChangeResourceState(iResClientId, KResourceId, KResourceMin, + ((DTestResManLddFactory*)iDevice)->iAsyncResourceCallback); + ((DTestResManLddFactory*)iDevice)->iCallbackState = DTestResManLddFactory::ESignallerCallback; + + break; + default: + break; + } + return r; + }