201031_07
authorhgs
Fri, 06 Aug 2010 16:34:38 +0100
changeset 243 c7a0ce20c48c
parent 231 75252ea6123b
child 244 a77889bee936
201031_07
kernel/eka/drivers/dma/dma2_pil.cpp
kernel/eka/include/drivers/dma_hai.h
kernel/eka/include/drivers/dma_v2.h
kernel/eka/include/e32ver.h
kernel/eka/kernel/sutils.cpp
kernel/eka/release.txt
kerneltest/e32test/defrag/t_ramdefrag.cpp
kerneltest/e32test/dma/d_dma.cpp
kerneltest/e32test/dmav2/d_dma2.cpp
kerneltest/e32test/dmav2/d_dma2.h
kerneltest/e32test/dmav2/dma2_sim.cpp
kerneltest/e32test/dmav2/t_dma2.cpp
kerneltest/e32test/dmav2/t_dma2.h
kerneltest/e32test/dmav2/test_cases.cpp
kerneltest/e32test/mmu/t_alias_remove.cpp
kerneltest/e32test/power/t_domain.cpp
kerneltest/f32test/fileutils/inc/tf32testtimer.h
kerneltest/f32test/group/t_wcache.mmp
kerneltest/f32test/server/t_fsched.cpp
kerneltest/f32test/server/t_wcache.cpp
userlibandfileserver/domainmgr/src/domaincli.cpp
userlibandfileserver/fileserver/group/release.txt
userlibandfileserver/fileserver/inc/F32plugin.h
userlibandfileserver/fileserver/inc/f32ver.h
userlibandfileserver/fileserver/sfile/sf_dir.cpp
userlibandfileserver/fileserver/sfile/sf_ops.h
userlibandfileserver/fileserver/sfile/sf_plugin.cpp
userlibandfileserver/fileserver/sfile/sf_plugin.h
userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp
userlibandfileserver/fileserver/sfile/sf_plugin_ops.cpp
userlibandfileserver/fileserver/sfile/sf_request.cpp
userlibandfileserver/fileserver/sfsrv/cl_scan.cpp
--- a/kernel/eka/drivers/dma/dma2_pil.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/drivers/dma/dma2_pil.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -1932,9 +1932,7 @@
 		{
 		iQueued = ETrue;
 		iChannel.iReqQ.Add(&iLink);
-		// iChannel.iNullPtr points to iChannel.iCurHdr for an empty queue
-		*iChannel.iNullPtr = iFirstHdr;
-		iChannel.iNullPtr = &(iLastHdr->iNext);
+		iChannel.SetNullPtr(*this);
 		if (iIsrCb)
 			{
 			// Since we've made sure that there is no other request in the
@@ -1946,7 +1944,7 @@
 			// possible.
 			__e32_atomic_store_rel32(&iChannel.iIsrCbRequest, ETrue);
 			}
-		iChannel.DoQueue(const_cast<const DDmaRequest&>(*this));
+		iChannel.DoQueue(*this);
 		r = KErrNone;
 		__DMA_INVARIANT();
 		iChannel.Signal();
@@ -2124,21 +2122,6 @@
 	__KTRACE_OPT(KDMA, Kern::Printf("DDmaRequest::TotalNumSrcElementsTransferred"));
 
 	// Not yet implemented.
-
-	// So far largely bogus code (just to touch some symbols)...
-	iTotalNumSrcElementsTransferred = 0;
-	TDmac& c = *(iChannel.iController);
-	if (c.iCapsHwDes)
-		{
-		for (const SDmaDesHdr* pH = iFirstHdr; pH != NULL; pH = pH->iNext)
-			{
-			iTotalNumSrcElementsTransferred += c.HwDesNumDstElementsTransferred(*pH);
-			}
-		}
-	else
-		{
-		// Do something different for pseudo descriptors...
-		}
 	return iTotalNumSrcElementsTransferred;
 	}
 
@@ -2433,7 +2416,8 @@
 		// ISR should not happen after this function returns.
 		iController->StopTransfer(*this);
 
-		ResetStateMachine();
+		DoCancelAll();
+		ResetNullPtr();
 
 		// Clean-up the request queue.
 		SDblQueLink* pL;
@@ -2707,8 +2691,7 @@
 				{
 				SDmaDesHdr* pCompletedSrcHdr = NULL;
 				SDmaDesHdr* pCompletedDstHdr = NULL;
-				DoDfc(const_cast<const DDmaRequest&>(*pCurReq),
-					  pCompletedSrcHdr, pCompletedDstHdr);
+				DoDfc(*pCurReq, pCompletedSrcHdr, pCompletedDstHdr);
 				// We don't support asymmetrical ISR notifications and request
 				// completions yet, hence we can do the following assert test
 				// here; also 'complete' is determined equally by either the
@@ -2720,7 +2703,7 @@
 			else
 				{
 				SDmaDesHdr* pCompletedHdr = NULL;
-				DoDfc(const_cast<const DDmaRequest&>(*pCurReq), pCompletedHdr);
+				DoDfc(*pCurReq, pCompletedHdr);
 				complete = (pCompletedHdr == pCurReq->iLastHdr);
 				}
 			// If just completed last fragment from current request, switch to
@@ -2731,7 +2714,7 @@
 				pCurReq->iLink.Deque();
 				iQueuedRequests--;
 				if (iReqQ.IsEmpty())
-					iNullPtr = &iCurHdr;
+					ResetNullPtr();
 				pCompletedReq->OnDeque();
 				}
 			}
@@ -2818,17 +2801,6 @@
 	}
 
 
-//
-// Reset state machine only, request queue is unchanged */
-//
-void TDmaChannel::ResetStateMachine()
-	{
-	DoCancelAll();
-	iCurHdr = NULL;
-	iNullPtr = &iCurHdr;
-	}
-
-
 void TDmaChannel::DoQueue(const DDmaRequest& /*aReq*/)
 	{
 	// Must be overridden
@@ -2865,6 +2837,21 @@
 	}
 
 
+void TDmaChannel::SetNullPtr(const DDmaRequest& aReq)
+	{
+	// iNullPtr points to iCurHdr for an empty queue
+	*iNullPtr = aReq.iFirstHdr;
+	iNullPtr = &(aReq.iLastHdr->iNext);
+	}
+
+
+void TDmaChannel::ResetNullPtr()
+	{
+	iCurHdr = NULL;
+	iNullPtr = &iCurHdr;
+	}
+
+
 /** PSL may override */
 void TDmaChannel::QueuedRequestCountChanged()
 	{
@@ -3038,6 +3025,35 @@
 //////////////////////////////////////////////////////////////////////////////
 // TDmaAsymSgChannel
 
+TDmaAsymSgChannel::TDmaAsymSgChannel()
+	: iSrcCurHdr(NULL),
+	  iSrcNullPtr(&iSrcCurHdr),
+	  iDstCurHdr(NULL),
+	  iDstNullPtr(&iDstCurHdr)
+	{
+	__DMA_INVARIANT();
+	}
+
+
+void TDmaAsymSgChannel::SetNullPtr(const DDmaRequest& aReq)
+	{
+	// i{Src|Dst}NullPtr points to i{Src|Dst}CurHdr for an empty queue
+	*iSrcNullPtr = aReq.iSrcFirstHdr;
+	*iDstNullPtr = aReq.iDstFirstHdr;
+	iSrcNullPtr = &(aReq.iSrcLastHdr->iNext);
+	iDstNullPtr = &(aReq.iDstLastHdr->iNext);
+	}
+
+
+void TDmaAsymSgChannel::ResetNullPtr()
+	{
+	iSrcCurHdr = NULL;
+	iSrcNullPtr = &iSrcCurHdr;
+	iDstCurHdr = NULL;
+	iDstNullPtr = &iDstCurHdr;
+	}
+
+
 void TDmaAsymSgChannel::DoQueue(const DDmaRequest& aReq)
 	{
 	if (iState == ETransferring)
@@ -3082,3 +3098,34 @@
 	iState = (iSrcCurHdr != NULL) ? ETransferring : EIdle;
 	}
 
+
+#ifdef _DEBUG
+void TDmaAsymSgChannel::Invariant()
+	{
+	Wait();
+
+	__DMA_ASSERTD(iReqCount >= 0);
+
+	__DMA_ASSERTD(iSrcCurHdr == NULL || iController->IsValidHdr(iSrcCurHdr));
+	__DMA_ASSERTD(iDstCurHdr == NULL || iController->IsValidHdr(iDstCurHdr));
+
+	// should always point to NULL pointer ending fragment queue
+	__DMA_ASSERTD(*iSrcNullPtr == NULL);
+	__DMA_ASSERTD(*iDstNullPtr == NULL);
+
+	__DMA_ASSERTD((0 <= iAvailDesCount) && (iAvailDesCount <= iMaxDesCount));
+
+	__DMA_ASSERTD((iSrcCurHdr && iDstCurHdr && !IsQueueEmpty()) ||
+				  (!iSrcCurHdr && !iDstCurHdr && IsQueueEmpty()));
+	if (iSrcCurHdr == NULL)
+		{
+		__DMA_ASSERTD(iSrcNullPtr == &iSrcCurHdr);
+		}
+	if (iDstCurHdr == NULL)
+		{
+		__DMA_ASSERTD(iDstNullPtr == &iDstCurHdr);
+		}
+
+	Signal();
+	}
+#endif
--- a/kernel/eka/include/drivers/dma_hai.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/include/drivers/dma_hai.h	Fri Aug 06 16:34:38 2010 +0100
@@ -896,12 +896,17 @@
 */
 class TDmaAsymSgChannel : public TDmaChannel
 	{
+public:
+	TDmaAsymSgChannel();
+
 private:
 	virtual void DoQueue(const DDmaRequest& aReq);
 	virtual void DoCancelAll();
 	virtual void DoUnlink(SDmaDesHdr& aHdr);
 	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aSrcCompletedHdr,
 					   SDmaDesHdr*& aDstCompletedHdr);
+	virtual void SetNullPtr(const DDmaRequest& aReq);
+	virtual void ResetNullPtr();
 
 protected:
 	SDmaDesHdr* iSrcCurHdr;	  // source fragment being transferred or NULL
@@ -909,6 +914,8 @@
 	SDmaDesHdr* iDstCurHdr;	  // destination fragment being transferred or NULL
 	SDmaDesHdr** iDstNullPtr; // Pointer to NULL pointer following last destination fragment
 	enum {EIdle = 0, ETransferring} iState;
+
+	__DMA_DECLARE_VIRTUAL_INVARIANT
 	};
 
 
--- a/kernel/eka/include/drivers/dma_v2.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/include/drivers/dma_v2.h	Fri Aug 06 16:34:38 2010 +0100
@@ -42,10 +42,12 @@
 #ifdef _DEBUG
 #define __DMA_CANT_HAPPEN() Kern::Fault(KDmaPanicCat, __LINE__)
 #define __DMA_DECLARE_INVARIANT public: void Invariant();
+#define __DMA_DECLARE_VIRTUAL_INVARIANT public: virtual void Invariant();
 #define __DMA_INVARIANT() Invariant()
 #else
 #define __DMA_CANT_HAPPEN()
 #define __DMA_DECLARE_INVARIANT
+#define __DMA_DECLARE_VIRTUAL_INVARIANT
 #define __DMA_INVARIANT()
 #endif
 
@@ -1255,17 +1257,18 @@
 	*/
 	virtual void QueuedRequestCountChanged();
 
-#if defined(__CPU_ARM) && !defined(__EABI__)
-	inline virtual ~TDmaChannel() {}	// kill really annoying warning
-#endif
+	virtual void SetNullPtr(const DDmaRequest& aReq);
+	virtual void ResetNullPtr();
+
+	inline virtual ~TDmaChannel() {}
+
+	inline void Wait();
+	inline void Signal();
+	inline TBool Flash();
 
 private:
 	static void Dfc(TAny*);
 	void DoDfc();
-	inline void Wait();
-	inline void Signal();
-	inline TBool Flash();
-	void ResetStateMachine();
 
 protected:
 	TDmac* iController;		 // DMAC this channel belongs to (NULL when closed)
@@ -1293,7 +1296,7 @@
 	TBool iRedoRequest;		// client ISR callback wants a redo of request
 	TBool iIsrCbRequest;	// request on queue using ISR callback
 
-	__DMA_DECLARE_INVARIANT
+	__DMA_DECLARE_VIRTUAL_INVARIANT
 	};
 
 
--- a/kernel/eka/include/e32ver.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/include/e32ver.h	Fri Aug 06 16:34:38 2010 +0100
@@ -28,7 +28,7 @@
 
 const TInt KE32MajorVersionNumber=2;
 const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=3109;
+const TInt KE32BuildVersionNumber=3110;
 
 const TInt KMachineConfigurationMajorVersionNumber=1;
 const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/kernel/sutils.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/kernel/sutils.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -3548,10 +3548,19 @@
 
 void TClientRequest::EndComplete(DThread* aThread)
 	{
+	// NB: if the callback is successfully queued, the target thread may run and
+	// process it before we get back from the call to QueueUserModeCallback().
+	// In that case, 'iStatus' will be changed; and in general it is not safe to
+	// look at any element of 'this' once the callback is queued, as it may change
+	// asynchronously.  Therefore, we must cache the value of 'iStatus' beforehand
+	// and later use this saved copy to decide whether to signal the target thread.
+	T_UintPtr status = iStatus;
 	TInt r = NKern::QueueUserModeCallback(&aThread->iNThread, this);
+
 	if (r == KErrNone)
 		{
-		if (iStatus != (KClientRequestNullStatus | KClientRequestFlagInUse))
+		__NK_ASSERT_DEBUG(status & KClientRequestFlagInUse);
+		if ((status & ~KClientRequestFlagInUse) != KClientRequestNullStatus)
 			NKern::ThreadRequestSignal(&aThread->iNThread);
 		}
 	else
--- a/kernel/eka/release.txt	Mon Jul 26 10:52:56 2010 +0100
+++ b/kernel/eka/release.txt	Fri Aug 06 16:34:38 2010 +0100
@@ -1,4 +1,27 @@
-Version 2.00.3108
+Version 2.00.3110
+=================
+(Made by fadhliM 22/07/2010)
+
+1.	davegord
+	1.	ou1cimx1#488456 (MCL) Kernel signals MTP server unexpectedly and cause it panic
+
+2.	dogunjom
+	1.	ou1cimx1#413278 MCL:Domain Manager - Correct the usage of RArray::Append()
+
+3.	jcoppear
+	1.	ou1cimx1#479322 ENV E32TEST T_RAMDEFRAG test failure investigation (t_ramdefrag.cpp:549)
+
+4.	vfebvre
+	1.	ou1cimx1#460995 ENV E32TEST T_PAGETABLE_LIMIT test failure investigation (t_pagetable_limit.cpp:276)
+
+5.	seolney
+	1.	ou1cimx1#486893 DEV DMA functions missing test code (pt. 2)
+
+6.	mipetzol
+	1.	ou1cimx1#479623 DMA V2 framework PIL enhancement required for management of AsymmmetricSgChannel class descriptors
+
+
+Version 2.00.3109
 =================
 (Made by fadhliM 19/07/2010)
 
--- a/kerneltest/e32test/defrag/t_ramdefrag.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/defrag/t_ramdefrag.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -543,7 +543,20 @@
 	Ldd.ResetDriver();
 	
 	Ldd.CallDefrag(DEFRAG_TYPE_GEN, DEFRAG_VER_SYNC);
-	if (VerifyMovDisAlloc() != KErrNone)
+	TInt r;
+	r = VerifyMovDisAlloc();
+	if (r == KErrGeneral)
+		{
+		// A rare set of circumstances may cause some of the movable pages to be in
+		// use during the defrag and thus not be moved to the correct RAM zone. Run
+		// the defrag once more to give it a chance to move these pages. We ensure
+		// that there is no pending asynchronous clean up operation before doing so.
+		UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
+		Ldd.CallDefrag(DEFRAG_TYPE_GEN, DEFRAG_VER_SYNC);
+		r = VerifyMovDisAlloc();
+		}
+
+	if (r != KErrNone)
 		{
 		CLEANUP(;);
 		TEST_FAIL;
--- a/kerneltest/e32test/dma/d_dma.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dma/d_dma.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -260,6 +260,19 @@
 		r = TDmaChannel::Open(info, iChannel);
 		if (r!= KErrNone)
 			return r;
+
+		// ---> Code coverage of rarely called functions
+		const TDmac* const c = iChannel->Controller();
+		if (!c)
+			return KErrGeneral;
+		const TInt mts = iChannel->MaxTransferSize(0, iCookie);
+		if (mts == 0)
+			return KErrGeneral;
+		const TUint mam = iChannel->MemAlignMask(0, iCookie);
+		if (~mam == 0)
+			return KErrGeneral;
+		// <--- Code coverage of rarely called functions
+
 		iClient = &Kern::CurrentThread();
 		for (TInt i=0; i<KMaxRequests; ++i)
 			{
--- a/kerneltest/e32test/dmav2/d_dma2.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/d_dma2.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -111,7 +111,13 @@
 	TInt CancelAllByCookie(TUint aDriverCookie);
 	TInt IsrRedoRequestByCookie(TUint aDriverCookie,TUint32 aSrcAddr,TUint32 aDstAddr,TInt aTransferCount,TUint32 aPslRequestInfo,TBool aIsrCb);
 	TInt IsQueueEmptyByCookie(TUint aDriverCookie, TBool& aQueueEmpty);		
-	TInt ChannelIsOpenedByCookie(TUint aDriverCookie, TBool& aChannelOpen);		
+	TInt ChannelIsOpenedByCookie(TUint aDriverCookie, TBool& aChannelOpen);	
+	TInt EnableDstElementCountingByCookie(TUint aDriverCookie);
+	TInt EnableSrcElementCountingByCookie(TUint aDriverCookie);
+	TInt DisableDstElementCountingByCookie(TUint aDriverCookie);
+	TInt DisableSrcElementCountingByCookie(TUint aDriverCookie);
+	TInt TotalNumDstElementsTransferredByCookie(TUint aDriverCookie);
+	TInt TotalNumSrcElementsTransferredByCookie(TUint aDriverCookie);
 	void CloseDmaChannelByIndex(TInt aIndex);
 	void CancelAllByIndex(TInt aIndex);
 	TInt LinkDmaChannelByIndex(TInt aIndex);
@@ -119,6 +125,12 @@
 	TInt PauseDmaChannelByIndex(TInt aIndex);
 	TInt ResumeDmaChannelByIndex(TInt aIndex);		
 	TInt IsrRedoRequestByIndex(TInt aIndex,TUint32 aSrcAddr,TUint32 aDstAddr,TInt aTransferCount,TUint32 aPslRequestInfo,TBool aIsrCb);
+	void EnableDstElementCountingByIndex(TInt aIndex);
+	void EnableSrcElementCountingByIndex(TInt aIndex);
+	void DisableDstElementCountingByIndex(TInt aIndex);
+	void DisableSrcElementCountingByIndex(TInt aIndex);
+	TInt TotalNumDstElementsTransferredByIndex(TInt aIndex);
+	TInt TotalNumSrcElementsTransferredByIndex(TInt aIndex);
 	TInt CreateSharedChunk();
 	TUint OpenSharedChunkHandle();
 
@@ -149,7 +161,6 @@
 	TInt QueueRequest(TUint aRequestCookie, TRequestStatus* aStatus, TCallbackRecord* aRecord, TUint64* aDurationMicroSecs);
 	DClientDmaRequest* RequestFromCookie(TUint aRequestCookie) const;
 	TInt RequestFragmentCount(TUint aRequestCookie);
-
 	TDmaV2TestInfo ConvertTestInfo(const TDmaTestInfo& aOldInfo) const;
 private:
 	DThread* iClient;
@@ -665,6 +676,42 @@
 			TInt r = RequestFragmentCount(requestCookie);
 			return r;
 			}
+	case RDmaSession::EEnableDstElementCounting:
+			{		
+			TUint requestCookie = reinterpret_cast<TUint>(a1);
+			TInt r = EnableDstElementCountingByCookie(requestCookie);
+			return r;
+			}
+	case RDmaSession::EEnableSrcElementCounting:
+			{
+			TUint requestCookie = reinterpret_cast<TUint>(a1);		
+			TInt r = EnableSrcElementCountingByCookie(requestCookie);
+			return r;
+			}
+	case RDmaSession::EDisableDstElementCounting:
+			{
+			TUint requestCookie = reinterpret_cast<TUint>(a1);
+			TInt r = DisableDstElementCountingByCookie(requestCookie);
+			return r;
+			}
+	case RDmaSession::EDisableSrcElementCounting:
+			{
+			TUint requestCookie = reinterpret_cast<TUint>(a1);
+			TInt r = DisableSrcElementCountingByCookie(requestCookie);
+			return r;
+			}
+	case RDmaSession::ETotalNumDstElementsTransferred:
+			{
+			TUint requestCookie = reinterpret_cast<TUint>(a1);
+			TInt r = TotalNumDstElementsTransferredByCookie(requestCookie);
+			return r;
+			}
+	case RDmaSession::ETotalNumSrcElementsTransferred:
+			{
+			TUint requestCookie = reinterpret_cast<TUint>(a1);
+			TInt r = TotalNumSrcElementsTransferredByCookie(requestCookie);
+			return r;
+			}
 	case RDmaSession::ERequestOpen:
 			{
 			RDmaSession::TRequestCreateArgs createArgs(0, EFalse, 0);
@@ -1054,6 +1101,164 @@
 		}
 	}
 
+TInt DDmaTestSession::EnableDstElementCountingByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("EnableDstElementCountingByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		EnableDstElementCountingByIndex(index);
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+void DDmaTestSession::EnableDstElementCountingByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("EnableDstElementCountingByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+#ifdef DMA_APIV2	
+	iClientDmaReqs[aIndex]->EnableDstElementCounting();
+#endif
+	}
+
+TInt DDmaTestSession::EnableSrcElementCountingByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("EnableSrcElementCountingByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		EnableSrcElementCountingByIndex(index);
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+void DDmaTestSession::EnableSrcElementCountingByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("EnableSrcElementCountingByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+	
+#ifdef DMA_APIV2
+	iClientDmaReqs[aIndex]->EnableSrcElementCounting();
+#endif
+	}
+
+TInt DDmaTestSession::DisableDstElementCountingByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("DisableDstElementCountingByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		DisableDstElementCountingByIndex(index);
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+void DDmaTestSession::DisableDstElementCountingByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("DisableDstElementCountingByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+#ifdef DMA_APIV2
+	iClientDmaReqs[aIndex]->DisableDstElementCounting();
+#endif
+	}
+
+TInt DDmaTestSession::DisableSrcElementCountingByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("DisableSrcElementCountingByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		DisableSrcElementCountingByIndex(index);
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+void DDmaTestSession::DisableSrcElementCountingByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("DisableSrcElementCountingByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+#ifdef DMA_APIV2
+	iClientDmaReqs[aIndex]->DisableSrcElementCounting();
+#endif
+	}
+
+TInt DDmaTestSession::TotalNumDstElementsTransferredByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("TotalNumDstElementsTransferredByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		TInt r = TotalNumDstElementsTransferredByIndex(index);
+		return r;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+TInt DDmaTestSession::TotalNumDstElementsTransferredByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("TotalNumDstElementsTransferredByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+	
+#ifdef DMA_APIV2
+	TInt r = iClientDmaReqs[aIndex]->TotalNumDstElementsTransferred();
+	return r;
+#else
+	return KErrNotSupported;
+#endif
+	}
+
+TInt DDmaTestSession::TotalNumSrcElementsTransferredByCookie(TUint aDriverCookie)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("TotalNumSrcElementsTransferredByCookie: 0x%08x", aDriverCookie)); 
+	const TInt index = CookieToRequestIndex(aDriverCookie);
+	
+	if(index >= 0)
+		{
+		TInt r = TotalNumSrcElementsTransferredByIndex(index);
+		return r;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+TInt DDmaTestSession::TotalNumSrcElementsTransferredByIndex(TInt aIndex)
+	{
+	__KTRACE_OPT(KDMA, Kern::Printf("TotalNumSrcElementsTransferredByIndex: %d", aIndex)); 		
+	__NK_ASSERT_DEBUG(aIndex < iClientDmaReqs.Count()); 
+	
+#ifdef DMA_APIV2
+	TInt r = iClientDmaReqs[aIndex]->TotalNumSrcElementsTransferred();
+	return r;
+#else
+	return KErrNotSupported;
+#endif
+	}
 TInt DDmaTestSession::IsrRedoRequestByCookie(TUint aDriverCookie,TUint32 aSrcAddr,TUint32 aDstAddr,TInt aTransferCount,TUint32 aPslRequestInfo,TBool aIsrCb)
 {
 	__KTRACE_OPT(KDMA, Kern::Printf("IsrRedoRequestByCookie: 0x%08x", aDriverCookie)); 
--- a/kerneltest/e32test/dmav2/d_dma2.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/d_dma2.h	Fri Aug 06 16:34:38 2010 +0100
@@ -508,6 +508,36 @@
 		return DoControl(EFragmentCount, reinterpret_cast<TAny*>(aRequestCookie));
 		}
 
+	TInt RequestEnableDstElementCounting(TUint aRequestCookie)
+		{					
+		return DoControl(EEnableDstElementCounting, reinterpret_cast<TAny*>(aRequestCookie));		
+		}
+
+	TInt RequestEnableSrcElementCounting(TUint aRequestCookie)
+		{		
+		return DoControl(EEnableSrcElementCounting, reinterpret_cast<TAny*>(aRequestCookie));
+		}
+
+	TInt RequestDisableDstElementCounting(TUint aRequestCookie)
+		{	
+		return DoControl(EDisableDstElementCounting, reinterpret_cast<TAny*>(aRequestCookie));
+		}
+
+	TInt RequestDisableSrcElementCounting(TUint aRequestCookie)
+		{	
+		return DoControl(EDisableSrcElementCounting, reinterpret_cast<TAny*>(aRequestCookie));
+		}
+
+	TInt RequestTotalNumDstElementsTransferred(TUint aRequestCookie)
+		{	
+		return DoControl(ETotalNumDstElementsTransferred, reinterpret_cast<TAny*>(aRequestCookie));
+		}
+
+	TInt RequestTotalNumSrcElementsTransferred(TUint aRequestCookie)
+		{	
+		return DoControl(ETotalNumSrcElementsTransferred, reinterpret_cast<TAny*>(aRequestCookie));
+		}
+
 	/**
 	Will fragment a DMA request using the legacy API
 	*/
@@ -614,8 +644,7 @@
 		TPckgC<TRequestCreateArgs> package(args);
 		return DoControl(ERequestOpen, &package, &aRequestCookie);
 		}
-
-
+	
 	struct TRequestCreateArgs
 		{
 		TRequestCreateArgs(TUint aChannelCookie, TBool aNewStyle, TUint aMaxFragmentSize)
@@ -690,6 +719,12 @@
 		EQueueRequestWithReque,
 		ELinkChannel,
 		EUnlinkChannel,
+		EEnableDstElementCounting,
+		EEnableSrcElementCounting,
+		EDisableDstElementCounting,
+		EDisableSrcElementCounting,
+		ETotalNumDstElementsTransferred,
+		ETotalNumSrcElementsTransferred,
 		};
 	};
 #endif // __D_DMA2_H__
--- a/kerneltest/e32test/dmav2/dma2_sim.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/dma2_sim.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -31,6 +31,12 @@
 static const TInt KMemAlignMask = 0; // memory addresses passed to DMAC must be multiple of 8
 static const TInt KDesCount = 160;				// Initial DMA descriptor count
 
+#define TEST_RETURN(X) if (!(X))\
+	{\
+	__KTRACE_OPT(KPANIC, Kern::Printf("Simulated Dma test failure: " __FILE__ " line %d", __LINE__));\
+	return KErrAbort;\
+	}
+
 class TDmaDesc
 //
 // Hardware DMA descriptor
@@ -101,10 +107,14 @@
 // Simulated channel
 //////////////////////////////////////////////////////////////////////////////
 
+/**
+An interface class to add simulation specific functionallity to any DMA channel
+*/
 class MSimChannel
 	{
 public:
-	virtual void PreOpen() {}
+	virtual TInt PreOpen() =0;
+	virtual TDmaChannel& Channel() =0;
 	};
 
 //////////////////////////////////////////////////////////////////////////////
@@ -168,9 +178,11 @@
 	void DoCancelAll();
 
 	void CallDefaultVirtuals();
+	TInt CheckExtensionStubs();
 
 	// From MSimChannel
-	void PreOpen();
+	TInt PreOpen();
+	TDmaChannel& Channel() {return *this;}
 	};
 
 void TEmptyChannel::DoCancelAll()
@@ -192,9 +204,23 @@
 	QueuedRequestCountChanged();
 	}
 
-void TEmptyChannel::PreOpen()
+TInt TEmptyChannel::CheckExtensionStubs()
+	{
+	DMA_PSL_TRACE("Calling extension stubs");
+
+	TInt r = Extension(0, NULL);
+	TEST_RETURN(r == KErrNotSupported)
+
+	r = StaticExtension(0, NULL);
+	TEST_RETURN(r == KErrNotSupported)
+
+	return KErrNone;
+	}
+
+TInt TEmptyChannel::PreOpen()
 	{
 	CallDefaultVirtuals();
+	return CheckExtensionStubs();
 	}
 
 //////////////////////////////////////////////////////////////////////////////
@@ -258,8 +284,6 @@
 //
 	: TDmac(aInfo)
 	{
-	// TODO remove this once DMAC can be created and destroyed from test LDD entry
-	// point
 	TInt r = Create(aInfo);
 	__NK_ASSERT_ALWAYS(r == KErrNone);
 
@@ -554,8 +578,6 @@
 //
 	: TDmac(KInfo)
 	{
-	// TODO remove this once DMAC can be created and destroyed from test LDD entry
-	// point
 	TInt r = Create();
 	__NK_ASSERT_ALWAYS(r == KErrNone);
 	}
@@ -654,15 +676,15 @@
 
 struct TChanEntry
 	{
-	TChanEntry(TDmac& aController, TDmaChannel& aChannel, const SDmacCaps& aCaps)
+	TChanEntry(TDmac& aController, MSimChannel& aChannel, const SDmacCaps& aCaps)
 		:
 			iController(aController),
-			iChannel(aChannel),
+			iSimChannel(aChannel),
 			iCaps(aCaps)
 	{}
 
 	TDmac& iController;
-	TDmaChannel& iChannel;
+	MSimChannel& iSimChannel;
 	const SDmacCaps& iCaps;
 	};
 
@@ -686,7 +708,7 @@
 	__DMA_ASSERTA(aOpenId < static_cast<TUint32>(KChannelCount));
 
 	const TChanEntry& entry = ChannelTable[aOpenId];
-	TDmaChannel* pC = &entry.iChannel;
+	TDmaChannel* pC = &entry.iSimChannel.Channel();
 	if (pC->IsOpened())
 		{
 		pC = NULL;
@@ -702,9 +724,19 @@
 		// as taken
 		Signal();
 
-		static_cast<TEmptyChannel*>(pC)->PreOpen();
+		TInt r = entry.iSimChannel.PreOpen();
 
 		Wait();
+
+		// If there was an error
+		// Close channel after retaking mutex
+		if(r != KErrNone)
+			{
+			pC->iController = NULL;
+			pC = NULL;
+			}
+
+
 		}
 	return pC;
 	}
--- a/kerneltest/e32test/dmav2/t_dma2.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/t_dma2.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -131,7 +131,10 @@
 	if(iDmaSession.Handle() == KNullHandle)
 		{
 		TInt r = iDmaSession.Open();
-		RDebug::Printf("CDmaTest::OpenDmaSession = %d\n", r);
+		if(KErrNone != r)
+			{
+			RDebug::Printf("CDmaTest::OpenDmaSession = %d\n", r);
+			}
 		TEST_ASSERT(r == KErrNone);
 		r = iDmaSession.OpenSharedChunk(iChunk);
 		TEST_ASSERT(r == KErrNone);
@@ -782,6 +785,78 @@
 	}
 
 //////////////////////////////////////////////////////////////////////
+//	CElementCountingTest
+//
+//	-Open DMA Channel
+//	-Create Request
+//	-Fragment and Make calls to Element Counting APIs
+//  -Check that TotalNumDstElementsTransferred() and TotalNumSrcElementsTransferred()
+//	 return non zero values
+//  -Check that KErrNone(from test driver) returned for other API calls
+//	-Queue Request 
+//	-Close DMA Channel
+//////////////////////////////////////////////////////////////////////
+CElementCountingTest::~CElementCountingTest()
+	{
+	}
+
+void CElementCountingTest::RunTest()
+	{
+	OpenDmaSession();
+	PreTransferSetup();
+
+	//Open a single DMA channel for a transfer
+	OpenChannel();
+	
+	//Setup a DMA request and Fragment the request.
+	RDebug::Printf("Create and Fragment DMA Request");
+	CreateDmaRequest();
+	Fragment();
+
+	//Enable src/dst counting
+	RDebug::Printf("Enable DstElementCounting");
+	TInt r = iDmaSession.RequestEnableDstElementCounting(iRequestSessionCookie);
+	TEST_ASSERT(KErrNone == r);
+
+	RDebug::Printf("Enable SrcElementCounting");
+	r = iDmaSession.RequestEnableSrcElementCounting(iRequestSessionCookie);
+	TEST_ASSERT(KErrNone == r);
+
+	//Queue request
+	RDebug::Printf("Queue DMA Request");
+	Queue();
+
+	//Disable src/dst counting
+	RDebug::Printf("Disable DstElementCounting");
+	r = iDmaSession.RequestDisableDstElementCounting(iRequestSessionCookie);
+	TEST_ASSERT(KErrNone == r);
+
+	RDebug::Printf("Disable SrcElementCounting");
+	r = iDmaSession.RequestDisableSrcElementCounting(iRequestSessionCookie);
+	TEST_ASSERT(KErrNone == r);
+
+	//check total src/dst elements transferred
+	RDebug::Printf("Get Total Number of DstElementsTransferred");
+	r = iDmaSession.RequestTotalNumDstElementsTransferred(iRequestSessionCookie);
+	TEST_ASSERT(r >= 0);
+
+	RDebug::Printf("Get Total Number of SrcElementsTransferred");
+	r = iDmaSession.RequestTotalNumSrcElementsTransferred(iRequestSessionCookie);
+	TEST_ASSERT(r >= 0);
+
+	FreeRequest();
+	CloseChannel();
+
+	PostTransferCheck();
+	CloseDmaSession();
+	}
+
+void CElementCountingTest::PrintTestType() const
+	{
+	RDebug::RawPrint(_L("Element Counting Tests"));
+	}
+
+//////////////////////////////////////////////////////////////////////
 // COpenCloseTest
 //////////////////////////////////////////////////////////////////////
 COpenCloseTest::~COpenCloseTest()
--- a/kerneltest/e32test/dmav2/t_dma2.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/t_dma2.h	Fri Aug 06 16:34:38 2010 +0100
@@ -621,6 +621,33 @@
 	inline CPauseResumeNegTest& UseNewDmaApi(TBool aFlag) {CSingleTransferTest::UseNewDmaApi(aFlag); return *this;}
 	};
 
+
+/**
+Used for testing element counting 
+
+Extends CSingle transfer by adding the capability to test
+Element Counting APIs
+*/
+class CElementCountingTest : public CSingleTransferTest
+	{
+public:
+	 CElementCountingTest(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aArgs, const TResultSet& aExpected)
+		:CSingleTransferTest(aName, aIterations, aArgs, aExpected)
+	 {}
+
+	~CElementCountingTest();
+
+	virtual void RunTest();
+	virtual void PrintTestType() const;
+
+	virtual CTest* Clone() const {return new CElementCountingTest(*this);}
+
+	// The methods below is a setters ie. The Named Parameter Idiom
+	// @see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.18
+	inline CElementCountingTest& UseNewDmaApi(TBool aFlag) {CSingleTransferTest::UseNewDmaApi(aFlag); return *this;}
+	};
+
+
 /**
 Used for testing Linking of DMA Channels ( Negative Testing)
 
--- a/kerneltest/e32test/dmav2/test_cases.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/dmav2/test_cases.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -1183,6 +1183,40 @@
 	TTestCase testCaseChannelLinking(&testChannelLinking , EFalse, capAboveV1,LinkingNotWanted);	
 	}
 
+//--------------------------------------------------------------------------------------------
+//! TestCaseID      KBASE-DMA-2574
+//! TestType        CIT
+//! PREQ            REQ
+//! TestCaseDesc    This test verifies that the DMA Element Counting APIs can be called. The calls 
+//!					to these functions are meant to be used to meet a code coverage requirement.These APIs
+//!					are not yet supported so the functionality of the APIs are not currently tested.
+//!
+//! TestActions     
+//!						1.	Open a DMA channel for a transfer.
+//!						2.  Make calls to Element Counting APIs
+//!						3.  Close DMA channel.
+//!					
+//! 
+//!	TestExpectedResults 1.  DMA channel opens and KErrNone returned.
+//!						2.  Element Counting APIs are called without crashing the framework
+//!						3.	DMA channel closes and KErrNone returned.
+//!
+//! TestPriority        High
+//! TestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+namespace ElementCountingTest
+	{
+	const TInt srcAddr		= 0;
+	const TInt desAddr		= 2 * KMega;	
+	const TInt transferSize = 1 * KMega;	
+
+	TDmaTransferArgs transferArgs(srcAddr, desAddr, transferSize, KDmaMemAddr);	
+
+	const TResultSet expectedResults(threadCallback);
+	CElementCountingTest testElementCounting(_L("DMA Element Counting Test"), 1, transferArgs, expectedResults);
+	TTestCase testCaseElementCounting(&testElementCounting, EFalse, capAboveV1);
+	}
+
 static TTestCase* StaticSimpleTestArray[] = {
 	&Simple_1::testCase,
 	&Simple_1::testCaseConcurrent,
@@ -1341,6 +1375,7 @@
 	&CancelAllTest::testCase,
 	&IsQueueEmptyTest::testCase,
 	&ChannelLinkingTest::testCaseChannelLinking,
+	&ElementCountingTest::testCaseElementCounting,
 };
 
 RPointerArray<TTestCase> TestArray(StaticTestArray, ARRAY_LENGTH(StaticTestArray));
--- a/kerneltest/e32test/mmu/t_alias_remove.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/mmu/t_alias_remove.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -207,7 +207,7 @@
 		if ((fillValue & 0xf) == 1)
 			test.Printf(_L("."));
 
-		PRINTF(T_PRINTF(_L("Process ID %d start slave fill value %d\n"), aProcessId, fillValue));
+		test.Printf(_L("Process ID %d start slave fill value %d\n"), aProcessId, fillValue);
 		RServer2 masterServer;
 		r = masterServer.CreateGlobal(MasterServerName);
 		test_KErrNone(r);
@@ -269,7 +269,7 @@
 				}
 			}
 		
-		PRINTF(T_PRINTF(_L("Process ID %d Wait for alias to complete\n"), aProcessId));
+		test.Printf(_L("Process ID %d Wait for alias to complete\n"), aProcessId);
 		masterMessage.Complete(KErrNone);
 		User::WaitForRequest(threadStatus);
 		TInt statusInt = threadStatus.Int();
@@ -280,7 +280,7 @@
 		test_Equal(EExitKill, readThread.ExitType());
 		readThread.Close();
 
-		PRINTF(T_PRINTF(_L("Process ID %d Wait for slave to complete\n"), aProcessId));
+		test.Printf(_L("Process ID %d Wait for slave to complete\n"), aProcessId);
 		User::WaitForRequest(slaveStatus);
 		test_Equal(EExitKill, slaveProcess.ExitType());
 		test_Equal(KErrNone, slaveProcess.ExitReason());
--- a/kerneltest/e32test/power/t_domain.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/e32test/power/t_domain.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-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"
@@ -806,7 +806,9 @@
 	void Perform();
 	void Release();
 	TInt TransitionNotification(MDmDomainMember& aDomainMember);
-	void TransitionRequestComplete();
+	void TransitionRequestComplete();	
+	void RunTestOnGetTransitionFailures(RArray<const TTransitionFailure>& aTransitionFailure);
+	
 	CDmTest5(TDmDomainId aPowerId, TDmDomainId aTestId, TDmDomainState aPowerState, TDmDomainState aTestState) : 
 		CActive(CActive::EPriorityStandard), 
 		iPowerDomainId(aPowerId), iTestDomainId(aTestId), iPowerState(aPowerState), iTestState(aTestState) {}
@@ -846,7 +848,28 @@
 	TInt				iTransitionsExpected;
 	};
 
-
+void CDmTest5::RunTestOnGetTransitionFailures(RArray<const TTransitionFailure>& aTransitionFailure)
+	{
+	//*************************************************
+	// Test - OOM Testing on GetTransitionFailures()
+	// Simulates heap failure in GetTransitionFailures()
+	//*************************************************
+	TInt error = 0;
+	TInt count = 0;	
+	do
+		{		
+		__UHEAP_SETFAIL(RHeap::EFailNext, ++count);
+		error = iTestDomainManager.GetTransitionFailures(aTransitionFailure);						
+		test.Printf( _L( "CDmTest5::RunTestOnGetTransitionFailures, simulating heap failure on GetTransitionFailures(), Error=%d, Run=%d\n" ), error, count );
+		}while(error == KErrNoMemory);		
+		
+	__UHEAP_RESET;
+	
+	//Actual count of heap failure as the final iteration which terminates the loop would not return KErrNoMemory 
+	--count;
+	test(count > 0);
+	test.Printf( _L( "Out of memory tests on GetTransitionFailures() succeeded at heap failure rate of %i\n" ), count );
+	}
 
 //! @SYMTestCaseID PBASE-T_DOMAIN-5
 //! @SYMTestType CT
@@ -1106,6 +1129,18 @@
 	testFailureCount = iTestDomainManager.GetTransitionFailureCount();
 	test (testFailureCount == 1);
 
+#ifdef _DEBUG
+	//***************************************************************
+	// OOM Testing: Simulates heap failure in GetTransitionFailures()
+	//***************************************************************
+	__UHEAP_MARK;
+	RArray<const TTransitionFailure> oomTestFailures;
+	RunTestOnGetTransitionFailures(oomTestFailures);
+	test(oomTestFailures.Count()==1);
+	oomTestFailures.Close();
+	__UHEAP_MARKEND;
+#endif
+	
 	r = iTestDomainManager.GetTransitionFailures(testFailures);
 	test(r == KErrNone);
 	test(testFailureCount == testFailures.Count());
@@ -2210,7 +2245,6 @@
 		{
 		MDmTest* tests[] = 
 			{
-
 			new CDmTest1(KDmIdRoot, EPwStandby),
 			new CDmTest1(KDmIdRoot, EPwOff),
 			new CDmTest1(KDmIdRoot, EPwActive),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/fileutils/inc/tf32testtimer.h	Fri Aug 06 16:34:38 2010 +0100
@@ -0,0 +1,154 @@
+// 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:
+// @file
+// 
+// 
+//
+
+
+class TF32TestTimer
+{
+public:
+    TF32TestTimer();
+
+    void Start();
+    void Stop();
+
+    TInt64 TimeTaken() const;
+    TTimeIntervalMicroSeconds Time() const;
+    TTimeIntervalMicroSeconds32 Time32() const;
+    int TimeInMicroSeconds() const;
+    int TimeInMilliSeconds() const;
+
+    static TInt TimeInMilliSeconds(TTimeIntervalMicroSeconds aTime);
+    static TInt TimeInMilliSeconds(TTimeIntervalMicroSeconds32 aTime);
+
+protected:
+    TInt64 Diff(TUint32 aTicks) const;
+
+protected:
+    TInt iFastCounterFreq;
+    TUint32 startTicks;
+    TUint32 endTicks;
+};
+
+
+class TF32TestTimer2: public TF32TestTimer
+{
+public:
+    void Stop2();
+
+    TInt64 TimeTaken2() const;
+    TTimeIntervalMicroSeconds32 Time2() const;
+    int Time2InMicroSeconds() const;
+
+private:
+    TUint32 endTicks2;
+};
+
+inline TF32TestTimer::TF32TestTimer()
+{   
+    TInt r = HAL::Get(HAL::EFastCounterFrequency, iFastCounterFreq);
+    test_KErrNone(r);
+}
+
+inline void TF32TestTimer::Start()
+{
+    startTicks = User::FastCounter();
+}
+
+inline void TF32TestTimer::Stop()
+{
+    endTicks = User::FastCounter();;
+}
+
+inline void TF32TestTimer2::Stop2()
+{
+    endTicks2 = User::FastCounter();;
+}
+
+inline TInt64 TF32TestTimer::Diff(TUint32 aTicks) const
+{
+    if (aTicks == startTicks)
+        {
+        test.Printf(_L("Warning: tick not advanced"));
+        }
+
+    TInt64 diff;
+    if (aTicks > startTicks)
+        {
+        diff = static_cast<TInt64>(aTicks) - static_cast<TInt64>(startTicks);
+        }
+    else
+        {
+        // handle counter rollover
+        diff = ((static_cast<TInt64>(KMaxTUint32) + 1 + aTicks) - static_cast<TInt64>(startTicks));
+        }
+    //RDebug::Printf("%x %x %ld", aTicks, startTicks, diff);
+    diff *= TInt64(1000000);
+    diff /= TInt64(iFastCounterFreq);
+    
+    return diff;
+}
+
+inline TInt64 TF32TestTimer::TimeTaken() const
+{
+    return Diff(endTicks);
+}
+
+inline TInt64 TF32TestTimer2::TimeTaken2() const
+{
+    return Diff(endTicks2);
+}
+
+inline int TF32TestTimer::TimeInMicroSeconds() const
+{
+    return static_cast <int>(TimeTaken());
+}
+
+inline int TF32TestTimer2::Time2InMicroSeconds() const
+{
+    return static_cast <int>(TimeTaken2());
+}
+
+inline TTimeIntervalMicroSeconds TF32TestTimer::Time() const
+{
+    return TimeTaken();
+}
+
+inline TTimeIntervalMicroSeconds32 TF32TestTimer2::Time2() const
+{    
+    return static_cast <int>(TimeTaken2());
+}
+
+inline TTimeIntervalMicroSeconds32 TF32TestTimer::Time32() const
+{
+    return static_cast <int>(TimeTaken());
+}
+
+inline int TF32TestTimer::TimeInMilliSeconds() const
+{
+    return static_cast <int>(TimeTaken() / 1000);
+}
+
+TInt TF32TestTimer::TimeInMilliSeconds(TTimeIntervalMicroSeconds aTime)
+{
+    return static_cast <int>(aTime.Int64()/static_cast<TInt64>(1000));
+}
+
+TInt TF32TestTimer::TimeInMilliSeconds(TTimeIntervalMicroSeconds32 aTime)
+{
+    return static_cast <int>(aTime.Int()/1000);
+}
+
--- a/kerneltest/f32test/group/t_wcache.mmp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/f32test/group/t_wcache.mmp	Fri Aug 06 16:34:38 2010 +0100
@@ -23,6 +23,7 @@
 
 LIBRARY		euser.lib efsrv.lib hal.lib 
 OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+USERINCLUDE		../fileutils/inc
 EPOCSTACKSIZE	0x10000
 
 CAPABILITY		TCB DISKADMIN ALLFILES
--- a/kerneltest/f32test/server/t_fsched.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/f32test/server/t_fsched.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -29,9 +29,11 @@
 #include "t_server.h"
 #include <e32twin.h>
 #include <e32cmn.h>
+#include <hal.h>
+#include "tf32testtimer.h"
 #include "f32_test_utils.h"
+using namespace F32_Test_Utils;
 
-using namespace F32_Test_Utils;
 
 //----------------------------------------------------------------------------------------------
 //! @SYMTestCaseID      PBASE-T_FSCHED-0191
@@ -117,7 +119,6 @@
 HBufC8* gBufSec = NULL;
 TPtr8 gBufWritePtr(NULL, 0);	
 
-const TInt KuStomS = 1000;
 const TInt KOneK = 1024;
 const TInt KOneMeg = KOneK * 1024;
 const TInt KBigBlockSize = KOneMeg ; 
@@ -134,8 +135,8 @@
 TTimeIntervalMicroSeconds32 gTimeTakenBigBlock(0);
 TBuf16<45> gSmallFile, gBigFile;
 TInt gNextFile=0;
-TTime gTime1;
-TTime gTime2;
+
+TF32TestTimer gTestTimer;
 
 RSemaphore gSync;
 
@@ -154,6 +155,9 @@
 	ENoThreads	
 	};
 
+
+
+
 /** Generates a file name of the form FFFFF*<aPos>.TXT (aLong.3)
 
 	@param aBuffer The filename will be returned here
@@ -613,32 +617,30 @@
 	}
 
 
-
 /** Measure the time taken for a big block to be written synchronously
 */
 void TimeTakenToWriteBigBlock() 
 {
-	TTime startTime;
-	TTime endTime;
 	RFile fileWrite;
 	
 	TInt r = fileWrite.Replace(TheFs,gBigFile,EFileShareAny|EFileWrite|EFileWriteDirectIO);
 	TESTERROR(r);
 
 	// Calculate how long it takes to write a big block to be able to issue at the right time the concurrent writes
-	startTime.HomeTime();
+    TF32TestTimer timer;
+	timer.Start();
 	
 	r = fileWrite.Write(gBufWritePtr, KBigBlockSize); 
-	
-	endTime.HomeTime();
-	
+
+    timer.Stop();
+
 	fileWrite.Close();
 
 	TESTERROR(r);
 	
-	gTimeTakenBigBlock = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()/3);
-
-	test.Printf(_L("\nTime spent to write the big block in isolation: %d ms\n"), gTimeTakenBigBlock.Int() / KuStomS);
+	gTimeTakenBigBlock = timer.TimeInMicroSeconds()/3;
+        
+	test.Printf(_L("\nTime spent to write the big block in isolation: %d ms\n"), TF32TestTimer::TimeInMilliSeconds(gTimeTakenBigBlock));
 }
 	
 
@@ -646,51 +648,44 @@
 */
 void TimeTakenToWriteBigFile(TInt aPos) 
 {
-	TTime startTime;
-	TTime endTime;
-	
 	test((aPos >= 0) && (aPos <= 1));
-	startTime.HomeTime();
-	
+    TF32TestTimer timer;
+    timer.Start();
+
 	WriteFile(TheFs,gBigFile, gBigFileSize, KBigBlockSize, ENoThreads);
 	
-	endTime.HomeTime();
+	timer.Stop();
 
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
+	gTimeTakenBigFile = timer.Time32();
+		
+	test.Printf(_L("\nTime spent to write the big file in isolation: %d ms\n"), TF32TestTimer::TimeInMilliSeconds(gTimeTakenBigFile));
 	
-	
-	test.Printf(_L("\nTime spent to write the big file in isolation: %d ms\n"), gTimeTakenBigFile.Int() / KuStomS);
-	
-	gTotalTimeSync[aPos] = Max((gTimeTakenBigFile.Int()/KuStomS), gTotalTimeSync[aPos]) ;
+	gTotalTimeSync[aPos] = Max(TF32TestTimer::TimeInMilliSeconds(gTimeTakenBigFile), gTotalTimeSync[aPos]) ;
 }
 
 /** Measure the time taken for this file to be written asynchronously
 */
 void TimeTakenToWriteBigFileAsync(TInt aPos) 
 {
-	TTime startTime;
-	TTime endTime;
-	TTime endTime2;
 	TRequestStatus status[KWaitRequestsTableSize];
 	RFile bigFile;
 	
 	test((aPos >= 0) && (aPos <= 1));
-	
-	startTime.HomeTime();
+
+    TF32TestTimer2 timer;
+	timer.Start();
 	WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize,KBigBlockSize,status); 
-	endTime.HomeTime();
-
+	timer.Stop();
 	
 	WaitForAll(status, gBigFileSize, KBigBlockSize);	
+	timer.Stop2();
 	
-	endTime2.HomeTime();
-	
-	gTimeTakenBigFile=I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
+	gTimeTakenBigFile = timer.Time32();        
 	bigFile.Close();
-	test.Printf(_L("\nTime to queue the blocks in isolation asynchronously: %d ms, "), gTimeTakenBigFile.Int() / KuStomS);
-	gTimeTakenBigFile=I64LOW(endTime2.MicroSecondsFrom(startTime).Int64());
-	test.Printf(_L("to actually write it: %d ms\n"),gTimeTakenBigFile.Int() / KuStomS);
-	gTotalTimeAsync[aPos] = Max((gTimeTakenBigFile.Int() / KuStomS), gTotalTimeAsync[aPos]) ; 
+	test.Printf(_L("\nTime to queue the blocks in isolation asynchronously: %d ms, "), timer.TimeInMilliSeconds());
+	gTimeTakenBigFile = timer.Time2();
+	test.Printf(_L("to actually write it: %d ms\n"), TF32TestTimer::TimeInMilliSeconds(gTimeTakenBigFile));
+	gTotalTimeAsync[aPos] = Max(TF32TestTimer::TimeInMilliSeconds(gTimeTakenBigFile), gTotalTimeAsync[aPos]) ; 
 }
 
 /**  Delete content of directory
@@ -728,7 +723,7 @@
 	TESTERROR(r);
 	
 	ReadFile(fs,gSmallFile,KBlockSize, EThreadWait);
-	gTime2.HomeTime();
+	gTestTimer.Start();
 	
 	client.Signal();
 	
@@ -753,7 +748,7 @@
 	TESTERROR(r);
 	
 	ReadFile(fs,gBigFile,KBlockSize, EThreadWait);
-	gTime2.HomeTime();
+	gTestTimer.Stop();
 	
 	client.Signal();
 		
@@ -778,7 +773,7 @@
 	TESTERROR(r);
 	
 	WriteFile(fs,gSmallFile,gSmallFileSize, KBlockSize, EThreadWait);
-	gTime2.HomeTime();
+	gTestTimer.Start();
 	
 	client.Signal();
 	
@@ -803,7 +798,7 @@
 	TESTERROR(r);
 	
 	WriteFile(fs, gBigFile, gBigFileSize, KBigBlockSize, EThreadSignal); 
-	gTime1.HomeTime();
+	gTestTimer.Stop();
 	
 	client.Signal();
 	
@@ -828,7 +823,7 @@
 	TESTERROR(r);
 	
 	WriteFile(fs, gSmallFile, gBigFileSize, KBigBlockSize, EThreadWait); 
-	gTime2.HomeTime();
+	gTestTimer.Stop();
 	
 	client.Signal();
 	
@@ -900,19 +895,13 @@
 
 */
 void TestReadingWhileWriting() 
-{
-	TInt r = 0;
-	TTime time1;
-	TTime time2;
-
-	time1.HomeTime();
-	
+{	
 	// Write the small file and take the appropriate measures
 	WriteFile(TheFs,gSmallFile,KBlockSize, KBlockSize, ENoThreads);
 
 	// Sync test
 	TBuf<20> buf=_L("Big Write");
-	r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
+	TInt r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
 	TEST(r == KErrNone);
 
 	buf = _L("Small Read");
@@ -928,15 +917,13 @@
 	gBig.Close();
 	gSmall.Close();
 	
-	
-	TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2);
-	test.Printf(_L("\nSync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
-	TReal time=I64LOW(timeTaken.Int64() / KuStomS); 
+	TTimeIntervalMicroSeconds timeTaken = gTestTimer.Time();
+	test.Printf(_L("\nSync read done %d ms before the write ended\n"), TF32TestTimer::TimeInMilliSeconds(timeTaken));
 	#if !defined(__WINS__)
-		// If this condition fails, it means that writing the sync file while fairscheduling a small sync read takes too long
-		test.Printf(_L("time: %f\n"), time);
-		// test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) );  
-		test(time > 0);
+		// If this condition fails, it means that writing the sync file while 
+        // fairscheduling a small sync read takes too long. Reading small file
+        // should complete first.
+		test(timeTaken > 0);
 	#endif 
 	
 	// Async test 
@@ -948,27 +935,26 @@
 	ReadFileAsync(TheFs, smallFile, gSmallFile, KBlockSize, status2 );
 
 	WaitForAll(status2,KBlockSize , KBlockSize );
-	time1.HomeTime(); 
+
+    TF32TestTimer timer;
+	timer.Start();
 
 	WaitForAll(status,gBigFileSize, KBigBlockSize);
 
-	time2.HomeTime();
+	timer.Stop();
 	bigFile.Close();
 	smallFile.Close();
 	
-	timeTaken = time2.MicroSecondsFrom(time1);
+	timeTaken = timer.Time();
 	
-	test.Printf(_L("\nAsync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
-	time = I64LOW(timeTaken.Int64() / KuStomS); 
+	test.Printf(_L("\nAsync read done %d ms before the write ended\n"), timer.TimeInMilliSeconds());
 
 	#if !defined(__WINS__)
 	if (!Is_HVFS(TheFs, gDrive))
 		{
 		// If this condition fails, it means that writing the async file while fairscheduling a small async read takes too long
-		test.Printf(_L("time: %f\n"), time);
 		test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] );
-		// test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) );
-		test(time > 0);
+		test(timeTaken > 0);
 		}
 	#endif
 }
@@ -979,8 +965,6 @@
 void TestWritingWhileWriting() 
 {
 	TInt r = 0;
-	TTime time1;
-	TTime time2;
 
 	// Sync test
 	TBuf<20> buf = _L("Big Write II");
@@ -1000,14 +984,12 @@
 	gBig.Close();
 	gSmall.Close();
 	
-	TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2);
-	test.Printf(_L("\nSync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
-	TReal time=I64LOW(timeTaken.Int64() / KuStomS); 
+	TTimeIntervalMicroSeconds timeTaken = gTestTimer.Time();
+	test.Printf(_L("\nSync write done %d ms before the big write ended\n"), gTestTimer.TimeInMilliSeconds());
 	#if !defined(__WINS__)
-		// If this condition fails, it means that writing the sync file while fairscheduling a small sync write takes too long
-		test.Printf(_L("time: %f\n"), time);
-		// test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) ); 
-		test(time > 0);
+		// If this condition fails, it means that writing the sync file while 
+        // fairscheduling a small sync write takes too long		
+		test(timeTaken > 0);
 	#endif 
 
 	// Async test 
@@ -1018,21 +1000,19 @@
 	WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status); 
 	WriteFileAsync(TheFs,smallFile, gSmallFile,gSmallFileSize,KBlockSize,status2);
 	WaitForAll(status2,gSmallFileSize, KBlockSize);
-	time1.HomeTime();
+    TF32TestTimer timer;
+	timer.Start();
 	WaitForAll(status, gBigFileSize, KBigBlockSize);
-	time2.HomeTime();
+	timer.Stop();
 	
-	timeTaken = time2.MicroSecondsFrom(time1);
-	test.Printf(_L("\nAsync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
-	time=I64LOW(timeTaken.Int64() / KuStomS);
+	timeTaken = timer.Time();
+	test.Printf(_L("\nAsync write done %d ms before the big write ended\n"),timer.TimeInMilliSeconds());
 	#if !defined(__WINS__)
 	if (!Is_HVFS(TheFs, gDrive))
 		{
 		// If this condition fails, it means that writing the async file while fairscheduling a small async write takes too long
-		test.Printf(_L("time: %f\n"), time);
 		test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] );
-		// test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) );
-		test(time > 0);
+		test(timeTaken > 0);
 		}
 	#endif
 	bigFile.Close();
@@ -1045,8 +1025,6 @@
 void TestTwoBigOnes()
 {
 	TInt r = 0;
-	TTime time1;
-	TTime time2;
 
 	// Sync test
 	TBuf<20> buf = _L("Big Write IIII");
@@ -1066,8 +1044,8 @@
 	gBig.Close();
 	gSmall.Close();
 	
-	TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1);
-	test.Printf(_L("\nSync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS));
+	TTimeIntervalMicroSeconds timeTaken = gTestTimer.Time();
+	test.Printf(_L("\nSync first write ended %d ms before the second write ended (same file size)\n"),TF32TestTimer::TimeInMilliSeconds(timeTaken));
 
 	// Async test 
 	TRequestStatus status[KWaitRequestsTableSize];
@@ -1077,12 +1055,13 @@
 	WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status); 
 	WriteFileAsync(TheFs, bigFile2, gSmallFile, gBigFileSize, KBigBlockSize, status2);
 	WaitForAll(status, gBigFileSize, KBigBlockSize);
-	time1.HomeTime();
+    TF32TestTimer timer;
+	timer.Start();
 	WaitForAll(status2, gBigFileSize, KBigBlockSize);
-	time2.HomeTime();
+	timer.Stop();
 	
-	timeTaken = time2.MicroSecondsFrom(time1);
-	test.Printf(_L("\nAsync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS));
+	timeTaken = timer.Time();
+	test.Printf(_L("\nAsync first write ended %d ms before the second write ended (same file size)\n"),TF32TestTimer::TimeInMilliSeconds(timeTaken));
 	bigFile.Close();
 	bigFile2.Close();	
 }
@@ -1093,9 +1072,9 @@
 void TestReadingWhileWritingSameFile() 
 {
 	TInt r = 0;
-	TTime time1;
+	TF32TestTimer timer;
 	
-	time1.HomeTime();
+	timer.Start();
 	
 	// Sync test
 	TBuf<20> buf = _L("Big Write IV");
@@ -1115,8 +1094,8 @@
 	CLOSE_AND_WAIT(gBig);
 	CLOSE_AND_WAIT(gSmall);
 	
-	TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1);
-	test.Printf(_L("\nSync write finished %d ms before the read ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
+	TTimeIntervalMicroSeconds timeTaken = gTestTimer.Time();
+	test.Printf(_L("\nSync write finished %d ms before the read ended\n"),TF32TestTimer::TimeInMilliSeconds(timeTaken));
 	
 }
 
--- a/kerneltest/f32test/server/t_wcache.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/kerneltest/f32test/server/t_wcache.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -28,6 +28,8 @@
 #include <f32dbg.h>
 #include "t_server.h"
 #include <e32twin.h>
+#include <hal.h>
+#include "tf32testtimer.h"
 
 const TInt KTotalCacheSize = 32 * 1024 * 1024;
 const TInt KDefaultCacheSize = (128 + 12) * 1024; 	// This size is the default configuration size
@@ -89,7 +91,6 @@
 const TInt KOneMeg = KOneK * 1024;
 const TInt KBlockSize = KOneK;
 const TInt KWaitRequestsTableSize = 256;
-const TInt KMs = 1000; 
 
 TInt gSecondFileSize = 0; 
 TInt gFirstFileSize = 0;
@@ -102,9 +103,6 @@
 TBuf16<25> gCurrentFile;
 
 TInt gNextFile = 0;
-TTime gTime1;
-TTime gTime2;
-
 
 // Concurrent Threads
 RThread gThread1;
@@ -513,25 +511,22 @@
 	
 	@return time taken to perform the operation in uS
 */
-TInt WriteTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) 
+TTimeIntervalMicroSeconds WriteTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) 
 	{
 	RTest test(_L("T_WCACHE"));
 
-	TTime startTime;
-	TTime endTime;
 	TInt r = 0;
-	
-	startTime.HomeTime();
+
+    TF32TestTimer timer;
+	timer.Start();
 	
 	r = WriteFile(gTheFs,aFile, aFileName , aSize * KOneK, aBlockSize, gBufWritePtr, aMode);
 	test_KErrNone(r);
-	
-	endTime.HomeTime();
-	
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
-	
+
+	timer.Stop();	
+	gTimeTakenBigFile = timer.Time();
 	test.Close();
-	return I64LOW(gTimeTakenBigFile.Int64());
+	return timer.Time();        
 	}
 
 /** Measure the time taken for this file to be read synchronously
@@ -545,18 +540,16 @@
 	@return time taken to perform the operation in uS
 
 */
-TInt ReadTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) 
+TTimeIntervalMicroSeconds ReadTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) 
 	{
-	TTime startTime;
-	TTime endTime;
+    TF32TestTimer timer;
+	timer.Start();
+	ReadFile(gTheFs,aFile, aFileName, aSize * KOneK, aBlockSize, aMode);
+	timer.Stop();
 	
-	startTime.HomeTime();
-	ReadFile(gTheFs,aFile, aFileName, aSize * KOneK, aBlockSize, aMode);
-	endTime.HomeTime();
-	
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
-	
-	return I64LOW(gTimeTakenBigFile.Int64()) ;
+	gTimeTakenBigFile = timer.Time();
+        	
+	return timer.Time();
 	}
 
 /** Read asynchronously the test file from the disc
@@ -569,22 +562,19 @@
 
 	@return time taken to perform the operation in uS
 */
-TInt ReadAsyncTestFile(RFile& file, TDes16& aFile, TInt aSize, TInt aBlockSize, TInt aMode) 
+TTimeIntervalMicroSeconds ReadAsyncTestFile(RFile& file, TDes16& aFile, TInt aSize, TInt aBlockSize, TInt aMode) 
 	{
-	TTime startTime;
-	TTime endTime;
 	TRequestStatus status[KWaitRequestsTableSize];
-	
-	startTime.HomeTime();
+    TF32TestTimer timer;
+	timer.Start();
 	
 	ReadFileAsync(gTheFs, file, aFile, aSize * KOneK, aBlockSize, status, aMode);
 	WaitForAll(status,  (aSize * KOneK)/KBlockSize);
-	
-	endTime.HomeTime();
+	timer.Stop();	
+		
+	gTimeTakenBigFile = timer.Time();
 	
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
-	
-	return I64LOW(gTimeTakenBigFile.Int64());
+	return timer.Time();
 	}
 
 /** Read asynchronously the test file from the disc
@@ -596,22 +586,19 @@
 
 	@return time taken to perform the operation in uS
 */
-TInt WriteAsyncTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aMode) 
+TTimeIntervalMicroSeconds WriteAsyncTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aMode) 
 	{
-	TTime startTime;
-	TTime endTime;
 	TRequestStatus status[KWaitRequestsTableSize];
-	
-	startTime.HomeTime();
+    TF32TestTimer timer;
+    timer.Start();
 	
 	WriteFileAsync(gTheFs, aFile, aFileName, aSize * KOneK, aMode, status );
 	WaitForAll(status, (aSize * KOneK)/KBlockSize);
-	
-	endTime.HomeTime();
+	timer.Stop();	
 	
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
+	gTimeTakenBigFile = timer.Time();
 	
-	return I64LOW(gTimeTakenBigFile.Int64());
+	return timer.Time();
 	}
 
 /**  Test Boundaries
@@ -621,9 +608,9 @@
 void TestBoundaries()
 	{
 	TInt r = 0;
-	TInt time = 0;
-	TInt rtime = 0;
-	TInt tcreate = 0;
+	TTimeIntervalMicroSeconds time = 0;
+	TTimeIntervalMicroSeconds rtime = 0;
+	TTimeIntervalMicroSeconds tcreate = 0;
 	RFile fileWriter;
 	RFile fileWriter2;
 	RFile fileReader;
@@ -641,21 +628,22 @@
 		test.Printf(_L("\nSync: Write from 1 K to %d K \n"), i); 
 
 		tcreate = WriteTestFile(fileWriter, gSecondFile, i, KBlockSize, EFileShareAny|EFileWrite|EFileWriteDirectIO);
-		test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, tcreate/KMs);	
+		test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(tcreate));	
 		fileWriter.Close();
 
 		time =  WriteTestFile(fileWriter2, gFirstFile, i, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered);
-		test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, time/KMs);
+		test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(time));
 
 		rtime = ReadTestFile(fileReader, gFirstFile, i, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered);
-		test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, rtime/KMs);
-
+		test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(rtime));
 
 		fileReader.Close();	
 		fileWriter2.Close();
 		
 		#if !defined(__WINS__)
-			test((tcreate > time) || (tcreate > rtime)); 
+            test(tcreate > TTimeIntervalMicroSeconds(0));  // test measured time is correct
+			test(tcreate > time);
+            test(tcreate > rtime); 
 		#endif
 
 		r = gTheFs.Delete(gFirstFile);
@@ -676,21 +664,23 @@
 		test.Printf(_L("\nAsync: Write from 1 K to %d K \n"), i); 
 
 		tcreate = WriteAsyncTestFile(fileWriter, gSecondFile, i, EFileShareAny|EFileWrite|EFileWriteDirectIO);
-		test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, tcreate/KMs);	
+		test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(tcreate));
 		fileWriter.Close();
 
 		time =  WriteAsyncTestFile(fileWriter2, gFirstFile, i,EFileShareAny|EFileWrite|EFileWriteBuffered);
-		test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, time/KMs);
+		test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(time));
 
 
 		rtime = ReadAsyncTestFile(fileReader, gFirstFile, i, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered);
-		test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, rtime/KMs);
+		test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, TF32TestTimer::TimeInMilliSeconds(rtime));
 
 		fileReader.Close();	
 		fileWriter2.Close();
 		
 		#if !defined(__WINS__)
-			test((tcreate > time) || (tcreate > rtime));  
+            test(tcreate > TTimeIntervalMicroSeconds(0));  // test measured time is correct
+			test(tcreate > time);
+            test(tcreate > rtime);
 		#endif
 
 		r = gTheFs.Delete(gFirstFile);
@@ -749,17 +739,16 @@
 	
 	@return returns the time that took to do the verification in mS, fails if the file is not corrupted/modified
 */
-TInt ReadTestFileVerif(TDes16& aFile)
+TTimeIntervalMicroSeconds ReadTestFileVerif(TDes16& aFile)
 	{
-	TTime startTime;
-	TTime endTime;
 	TInt r = 0;
 	TInt size = 0;
 	RFile fileRead;
 	TInt corrupt = 0;
 	TBool isFat=IsFSFAT(gTheFs,gDrive);
-	
-	startTime.HomeTime();
+
+    TF32TestTimer timer;
+	timer.Start();
 	
 	r = fileRead.Open(gTheFs,aFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
 	test_KErrNone(r);
@@ -791,12 +780,11 @@
 	fileRead.Close();
 	
 	test(corrupt>0); // Ensure the cache returns the changed content 
-	
-	endTime.HomeTime();
+	timer.Stop();	
 	
-	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
+	gTimeTakenBigFile = timer.Time();
 	
-	return I64LOW(gTimeTakenBigFile.Int64()) / KMs;
+	return timer.Time();
 	}
 
 /**  Modifies the second file
@@ -840,8 +828,8 @@
 LOCAL_C void TestIntegrity()
 	{
 	TInt r = 0;
-	TInt time;
-	TInt tcreate = 0;
+	TTimeIntervalMicroSeconds time;
+	TTimeIntervalMicroSeconds tcreate = 0;
 	RFile file;
 	
 	// Modify file in some position 
@@ -850,14 +838,14 @@
 	test.Printf(_L("\nSync: Write from 1 K to %d K \n"), 255); 
 
 	tcreate = WriteTestFile(file, gSecondFile, 255, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered);
-	test.Printf(_L("Time to write %d K with caching: %d mS\n"), 255, tcreate/KMs);	
+	test.Printf(_L("Time to write %d K with caching: %d mS\n"), 255, TF32TestTimer::TimeInMilliSeconds(tcreate));	
 	file.Close();
 
 	test.Printf(_L("Mess the content that is still in the cache\n"));
 	CorruptSecondFile(); 
 	
 	time = ReadTestFileVerif(gSecondFile);	
-	test.Printf(_L("Time taken to verify: %d\n"),time);
+	test.Printf(_L("Time taken to verify: %ld\n"),time.Int64());
 	
 	test.Printf(_L("Integrity verified\n"));
 
@@ -1178,7 +1166,7 @@
 */
 void TestRemoval()
 	{	
-	TInt time = 0, rtime = 0;
+	TTimeIntervalMicroSeconds time = 0, rtime = 0;
 	RFile file1, file2;
 	
 		 	
@@ -1227,7 +1215,7 @@
 	test.Printf(_L("\nSync: Write from 1 K to 254 K \n")); 
 
 	time =  WriteTestFile(file1, gSecondFile, KMinSize, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered);
-	test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize, time/KMs);
+	test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize, TF32TestTimer::TimeInMilliSeconds(time));
 	test.Printf(_L("Remove MMC card,! and then press a key\n"));
 	test.Getch();
 
@@ -1235,7 +1223,7 @@
 	test.Getch();
 
 	rtime = ReadTestFile(file2, gSecondFile, KMinSize, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered);
-	test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize, rtime/KMs);
+	test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize, TF32TestTimer::TimeInMilliSeconds(rtime));
 
 	test.Printf(_L("Remove MMC card! and then press a key\n"));
 	test.Getch();
@@ -1247,7 +1235,7 @@
 	test.Printf(_L("\nSync: Write from 1 K to 255 K \n")); 
 
 	time =  WriteTestFile(file1, gFirstFile, KMinSize + 1 , KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered);
-	test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize + 1, time/KMs);
+	test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize + 1, TF32TestTimer::TimeInMilliSeconds(time));
 	test.Printf(_L("Remove MMC card and delete the file //F32-TST//FFFFFFF0.TXT and then press a key\n"));
 	test.Getch();
 
@@ -1255,7 +1243,7 @@
 	test.Getch();
 
 	rtime = ReadTestFile(file2, gFirstFile, KMinSize + 1, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered);
-	test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize + 1, rtime/KMs);
+	test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize + 1, TF32TestTimer::TimeInMilliSeconds(rtime));
 
 	test.Printf(_L("Remove MMC card! and then press a key\n"));
 	test.Getch();
--- a/userlibandfileserver/domainmgr/src/domaincli.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/domainmgr/src/domaincli.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-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"
@@ -19,6 +19,7 @@
 #include <e32base_private.h>
 #include <e32property.h>
 
+
 #include <domainmember.h>
 #include <domainmanager.h>
 #include "domainobserver.h"
@@ -380,26 +381,43 @@
 	{
 	__DM_ASSERT(Handle() != KNullHandle);
 
+	
 	aTransitionFailures.Reset();
 
 	TInt err = KErrNone;
-
+		
 	TInt failureCount = GetTransitionFailureCount();
 	if (failureCount <= 0)
 		return failureCount;
-
+	
+	// Pre-allocate array with a known size which for this case is the value in failureCount 
+	// in order to guarantee that future append operations to the array aTransitionFailures would
+	// not fail. This is assuming that the pre-allocated size is not exceeded.
+	err=aTransitionFailures.Reserve(failureCount); 
+	if (err != KErrNone)
+		return err;
+		
 	TTransitionFailure* failures = new TTransitionFailure[failureCount];
 	if(failures == NULL)
+		{		
+		aTransitionFailures.Reset();
 		return(KErrNoMemory);
+		}
+	
 	TPtr8 dataPtr(reinterpret_cast<TUint8*>(failures), failureCount * sizeof(TTransitionFailure));
 
 	TIpcArgs a(&dataPtr);
 	err = RSessionBase::SendReceive(EDmGetTransitionFailures, a);
-	
+
 	if (err == KErrNone)
 		{
-		for (TInt i=0; i<failureCount; i++)
-			aTransitionFailures.Append(failures[i]);
+		for (TInt i=0; i<failureCount; i++)	
+			{
+			err = aTransitionFailures.Append(failures[i]);		
+			//The pre-allocation made above for the array aTransitionFailures should guarantee
+			//that append operations complete succesfully.			
+			__DM_ASSERT(err == KErrNone);	
+			}
 		}
 
 	delete [] failures;
@@ -439,19 +457,34 @@
 	if (count <= 0)
 		return KErrGeneral;
 
+	// Pre-allocate array with a known size which for this case is the value in count 
+	// in order to guarantee that future append operations to the array aTransitionFailures 
+	// would not fail. This is assuming that the pre-allocated size is not exceeded.
+	TInt ret=aTransitions.Reserve(count); 
+	if (ret != KErrNone)
+		return ret;
+
 	TTransInfo* trans = new TTransInfo[count];
 	if(trans == NULL)
+		{
+		aTransitions.Reset();
 		return(KErrNoMemory);
+		}
 	
 	TPtr8 dataPtr(reinterpret_cast<TUint8*>(trans), count * sizeof(TTransInfo));
 
 	TIpcArgs a(&dataPtr);
-	TInt ret=RSessionBase::SendReceive(EDmObserverGetEvent, a);
+	ret=RSessionBase::SendReceive(EDmObserverGetEvent, a);
 	
 	if(ret==KErrNone)
 		{
 		for (TInt i=0; i<count; i++)
-			aTransitions.Append(trans[i]);
+			{
+			ret = aTransitions.Append(trans[i]);					
+			//The pre-allocation made above for the array aTransitions should guarantee
+			//that append operations complete succesfully.
+			__DM_ASSERT(ret == KErrNone);					
+			}
 		}
 	
 	delete [] trans;
--- a/userlibandfileserver/fileserver/group/release.txt	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/group/release.txt	Fri Aug 06 16:34:38 2010 +0100
@@ -1,3 +1,15 @@
+Version 2.00.3055
+=================
+(Made by fadhliM 23/07/2010)
+
+1.	michcox
+	1.	ou1cimx1#488769 Race condition in file server plugins
+	2.	ou1cimx1#502970 [ENV] Fileserver Coverity Defects
+
+2.	niccox
+	1.	ou1cimx1#486762 ENV T_FSCHED.EXE failure: line 936, after "Sync read done 0 ms before the write ended"
+
+
 Version 2.00.3054
 =================
 (Made by fadhliM 19/07/2010)
--- a/userlibandfileserver/fileserver/inc/F32plugin.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/inc/F32plugin.h	Fri Aug 06 16:34:38 2010 +0100
@@ -448,7 +448,7 @@
 	//Overloaded function - checks all types of TInterceptAtts
 	TBool IsRegistered(TInt aMessage);
 	TBool IsRegistered(TInt aMessage, TInterceptAtts aInterceptAtts);
-	TBool IsPluginThread(CFsRequest& aMessage);
+	TBool OriginatedFromPlugin(CFsRequest& aMessage);
 	TBool IsMounted(TInt aDrive);
 
 private:
--- a/userlibandfileserver/fileserver/inc/f32ver.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/inc/f32ver.h	Fri Aug 06 16:34:38 2010 +0100
@@ -58,6 +58,6 @@
 
 @see TVersion
 */
-const TInt KF32BuildVersionNumber=3054;
+const TInt KF32BuildVersionNumber=3055;
 //
 #endif
--- a/userlibandfileserver/fileserver/sfile/sf_dir.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_dir.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -116,7 +116,8 @@
 	CFsPlugin* plugin = NULL;
 	//Get the next plugin which is mounted on this drive (IsMounted called in NextPlugin)
 	//Do not check whether we're registered for current operation (in case not registered for EFsDirOpen)
-	while(FsPluginManager::NextPlugin(plugin,(CFsMessageRequest*)aRequest,(TBool)ETrue,(TBool)EFalse)==KErrNone && plugin)
+	FsPluginManager::ReadLockChain();                                      //!Check operation
+	while(FsPluginManager::NextPlugin(plugin,(CFsMessageRequest*)aRequest,(TBool)EFalse)==KErrNone && plugin)
 		{
 		if(plugin->IsRegistered(EFsDirReadOne) ||
 			plugin->IsRegistered(EFsDirReadPacked) ||
@@ -129,6 +130,7 @@
 			break;
 			}
 		}
+	FsPluginManager::UnlockChain();
 	
 	TPtrC8 pH((TUint8*)&h,sizeof(TInt));
 	TRAP(r,aRequest->WriteL(KMsgPtr3,pH))
--- a/userlibandfileserver/fileserver/sfile/sf_ops.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_ops.h	Fri Aug 06 16:34:38 2010 +0100
@@ -135,7 +135,7 @@
 		{	EFsAddPlugin,				ESync,					&TFsAddPlugin::Initialise,					NULL,								&TFsAddPlugin::DoRequestL					},
 		{	EFsRemovePlugin,			ESync,					&TFsRemovePlugin::Initialise,				NULL,								&TFsRemovePlugin::DoRequestL				},
 		{	EFsMountPlugin,				ESync,					&TFsMountPlugin::Initialise,				NULL,								&TFsMountPlugin::DoRequestL					},
-		{	EFsDismountPlugin,			0,						&TFsDismountPlugin::Initialise,				NULL,								&TFsDismountPlugin::DoRequestL				},
+		{	EFsDismountPlugin,			0, /*PluginThrdContxt*/	&TFsDismountPlugin::Initialise,				NULL,								&TFsDismountPlugin::DoRequestL				},
 		{	EFsPluginName,				ESync,					&TFsPluginName::Initialise,					NULL,								&TFsPluginName::DoRequestL					},
 		{	EFsPluginOpen,				ESync | EParseSrc,		&TFsPluginOpen::Initialise,					NULL,								&TFsPluginOpen::DoRequestL					},
 		{	EFsPluginSubClose,			ESync,					&TFsSubClose::Initialise,					NULL,								&TFsSubClose::DoRequestL					},
--- a/userlibandfileserver/fileserver/sfile/sf_plugin.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -247,9 +247,9 @@
 	}
 
 /**
-   Return ETrue if the calling thread is the plugin thread
+   Return ETrue if the request originated from this plugin
 */
-TBool CFsPlugin::IsPluginThread(CFsRequest& aRequest)
+TBool CFsPlugin::OriginatedFromPlugin(CFsRequest& aRequest)
 	{
 	if(aRequest.iOwnerPlugin == this)
 		return ETrue;
@@ -361,9 +361,11 @@
 
 
 	CFsPlugin* plugin = this;
-	FsPluginManager::NextPlugin(plugin, &msgRequest,(TBool)ETrue);
+	FsPluginManager::ReadLockChain();
+	FsPluginManager::NextPlugin(plugin, &msgRequest);
 	msgRequest.iCurrentPlugin = plugin;
 	msgRequest.Dispatch();
+	FsPluginManager::UnlockChain();
 	iThreadP->OperationLockWait();
 
 	aDes.SetLength(len);
--- a/userlibandfileserver/fileserver/sfile/sf_plugin.h	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin.h	Fri Aug 06 16:34:38 2010 +0100
@@ -60,8 +60,8 @@
 	static TInt InstallPluginFactory(CFsPluginFactory* aFactory,RLibrary aLib);
 	static CFsPluginFactory* GetPluginFactory(const TDesC& aName);
 
-	static TInt NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock, TBool aCheckCurrentOperation=ETrue);
-	static TInt PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock);
+	static TInt NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aCheckCurrentOperation=ETrue);
+	static TInt PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest);
 	static TInt InsertInPluginStack(CFsPlugin*& aPlugin,TInt aPos);
 	static TInt IsInChain(TInt aUPos, TInt aPos,TInt aDrive, CFsPluginFactory* aPluginFactory);
 	static CFsPlugin* FindByUniquePosition(TInt aPos);
@@ -72,7 +72,8 @@
 	static TInt ChainCount();
 	static TInt Plugin(CFsPlugin*& aPlugin, TInt aPos);
 
-	static void LockChain();
+	static void ReadLockChain();
+	static void WriteLockChain();
 	static void UnlockChain();
 
 	static CFsPluginConn* CreatePluginConnL(TInt aUniquePosition, TUint aClientId);
@@ -91,7 +92,7 @@
 	static CFsObjectCon* iPluginConns;
 
 	static RPointerArray<CFsPlugin> iPluginChain;
-	static RFastLock iChainLock;
+	static RReadWriteLock iChainLock;
 
 	static CFsSyncMessageScheduler* iScheduler;
 
--- a/userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -21,7 +21,7 @@
 
 CFsObjectCon* FsPluginManager::iPluginFactories = NULL;
 CFsObjectCon* FsPluginManager::iPluginConns     = NULL;
-RFastLock FsPluginManager::iChainLock;
+RReadWriteLock FsPluginManager::iChainLock;
 RPointerArray<CFsPlugin> FsPluginManager::iPluginChain;
 CFsSyncMessageScheduler* FsPluginManager::iScheduler = NULL;
 
@@ -153,7 +153,7 @@
 		return err;
 		}
 
-	LockChain();
+	WriteLockChain();
 	err = InsertInPluginStack(pP,aPos);
 	UnlockChain();
 	if(err != KErrNone)
@@ -235,7 +235,7 @@
 Transfer any outstanding requests to next/previous plugin depending on
 if it is post filter or not
 
-Must be called with the plugin chain locked.
+Must be called with the plugin chain write-locked.
 Attains plugin-thread's listlock.
 */
 void FsPluginManager::TransferRequests(CPluginThread* aPluginThread)
@@ -315,12 +315,12 @@
 	        if(pR->IsPostOperation())
 	            {
 	            //[set the plugin to] pass the request backwards in the chain
-	            PrevPlugin(pR->iCurrentPlugin, &mR, EFalse);
+	            PrevPlugin(pR->iCurrentPlugin, &mR);
 	            }
 	        else //IsPreOperations
 	            {
 	            //[set the plugin to] pass the request forwards in the chain
-	            NextPlugin(pR->iCurrentPlugin, &mR, EFalse);
+	            NextPlugin(pR->iCurrentPlugin, &mR);
 	            }
 
 	        if(pR->iCurrentPlugin)
@@ -386,19 +386,18 @@
 /**
 Find the next plugin that supports the operation
 
+Must be called with the plugin chain (at least read-) locked.
+
 @param aPlugin - On calling the function this may contain either NULL or the current plugin.
                  If it is called with NULL, then we start to look for plugins from the beginning of the chain.
                  If is is called with a plugin then we start to look after that plugin for the next one.
                  On return, aPlugin shall contain either a plugin or NULL.
                  
-@param aLock - If this is set to ETRUE, then the function shall lock the plugin chain.
-               If this is set to EFALSE, then the caller of the function MUST already hold the lock.
-
 @param aCheckCurrentOperation - Optional, if false, will return the next plugin,
  								whether the plugin is currently registered
 								for the current function or not. (so long as mounted on the current drive)
 */
-TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest,TBool aLock, TBool aCheckCurrentOperation)
+TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aCheckCurrentOperation)
 	{
 	if(aMsgRequest->DirectToDrive())
 		{
@@ -410,9 +409,6 @@
 	TInt function = aMsgRequest->Operation()->Function();
 	TInt drive = aMsgRequest->DriveNumber();
 
-	if(aLock)
-	    LockChain();
-	
 	//the plugin chain lock must be held by this point.
 	TInt count = iPluginChain.Count();
 
@@ -431,25 +427,22 @@
 					{
 
 					aPlugin = iPluginChain[i];
-					if(aLock)
-					    UnlockChain();
 					return KErrNone;
 					}
 				}
 			}
 		}
 	aPlugin = NULL;
-	if(aLock)
-	    UnlockChain();
 	return KErrNotFound;
 	}
 
 /**
 Find the next plugin that supports the operation
+Must be called with the plugin chain (at least read-) locked.
 
 @see FsPluginManager::NextPlugin
 */
-TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock)
+TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest)
 	{
 	if(aMsgRequest->DirectToDrive() && (aMsgRequest->CurrentOperationPtr() != NULL))
 		{
@@ -460,9 +453,6 @@
 	TInt start;
 	TInt function = aMsgRequest->Operation()->Function();
 	TInt drive = aMsgRequest->DriveNumber();
-
-	if(aLock)
-	    LockChain();
 	
 	//the plugin chain lock must be held by this point.
 	TInt count= iPluginChain.Count();
@@ -486,16 +476,12 @@
 					{
 
 					aPlugin = iPluginChain[i];
-					if(aLock)
-					    UnlockChain();
 					return KErrNone;
 					}
 				}
 			}
 		}
 	aPlugin = NULL;
-	if(aLock)
-	    UnlockChain();
 	return KErrNotFound;
 	}
 /**
@@ -584,7 +570,7 @@
 */
 CFsPlugin* FsPluginManager::FindByUniquePosition(TInt aUniquePosition)
 	{
-	LockChain();
+	ReadLockChain();
 	CFsPlugin* plugin = NULL;
 	TInt count= iPluginChain.Count();
 	for(TInt i=0;i<count;i++)
@@ -671,19 +657,27 @@
 	}
 
 /**
-Locks the chain
+Locks the chain for reading
 */
-void FsPluginManager::LockChain()
+void FsPluginManager::ReadLockChain()
 	{
-	iChainLock.Wait();
+    iChainLock.ReadLock();
 	}
 
 /**
+Locks the chain for writing
+*/
+void FsPluginManager::WriteLockChain()
+    {
+    iChainLock.WriteLock();
+    }
+
+/**
 Unlocks the chain
 */
 void FsPluginManager::UnlockChain()
 	{
-	iChainLock.Signal();
+    iChainLock.Unlock();
 	}
 
 /**
@@ -743,7 +737,7 @@
 	// Iterate through all plugins, cancelling outstanding session requests
 	aRequest->Set(CancelPluginOp, aSession);
 
-	FsPluginManager::LockChain();
+	FsPluginManager::ReadLockChain();
 	TInt count = FsPluginManager::ChainCount();
 	TInt oldCount = count;
 	TInt i;
@@ -759,7 +753,7 @@
 	    //so hopefully this wont take too long.
 	    FsPluginManager::UnlockChain();
 	    User::WaitForRequest(aRequest->Status());
-	    FsPluginManager::LockChain();
+	    FsPluginManager::ReadLockChain();
 	    __ASSERT_ALWAYS(aRequest->Status().Int()==KErrNone||aRequest->Status().Int()==KErrCancel,Fault(ESessionDisconnectThread2));
 	    count = FsPluginManager::ChainCount();
 	    //If a plugin was removed whilst the chain was unlocked we need to make sure we don't skip any plugins
--- a/userlibandfileserver/fileserver/sfile/sf_plugin_ops.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin_ops.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -153,7 +153,7 @@
 	if(pF->IsDriveSupported(drive) == EFalse)
 		return KErrNotSupported;
 
-	FsPluginManager::LockChain();
+	FsPluginManager::ReadLockChain();
 	err = FsPluginManager::IsInChain(pF->UniquePosition(),aRequest->Message().Int2(),aRequest->Message().Int1(), pF);
 
 	// plugin might have been mounted in different pos and drive. Find the right one
@@ -209,7 +209,7 @@
 
 	TInt drive = aRequest->Message().Int1();
 
-	FsPluginManager::LockChain();
+	FsPluginManager::WriteLockChain();
 
 	TInt err = FsPluginManager::IsInChain(pF->UniquePosition(),aRequest->Message().Int2(),drive, pF);
 	if(err >= 0)
@@ -219,11 +219,8 @@
 		err = FsPluginManager::Plugin(plugin, pos);
 		if(err == KErrNone)
 			{
-			if(aRequest->iCurrentPlugin == plugin)
-				{
-				FsPluginManager::DismountPlugin(*pF,pos);
-				aRequest->SetScratchValue(0);
-				}
+			FsPluginManager::DismountPlugin(*pF,pos);
+			aRequest->SetScratchValue(0);
 			}
 		}
 	FsPluginManager::UnlockChain();
@@ -250,7 +247,7 @@
 TInt TFsPluginName::DoRequestL(CFsRequest* aRequest)
 	{
 	CFsPlugin* plugin=NULL;
-	FsPluginManager::LockChain();
+	FsPluginManager::ReadLockChain();
 	TInt err = FsPluginManager::Plugin(plugin, aRequest->Message().Int2());
 	if(err != KErrNone) //should be ok but just in case
 	    {
--- a/userlibandfileserver/fileserver/sfile/sf_request.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_request.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -974,7 +974,7 @@
 //
 	{
 	TInt err = KErrNone;
-	if(!iCurrentPlugin->IsPluginThread(*this))
+	if(!iCurrentPlugin->OriginatedFromPlugin(*this))
 		{
 		// The request hasn't come from this plugin so it's safe to dispatch		
 		TFsPluginRequest request(this);
@@ -997,14 +997,17 @@
 	
 	// Find the previous plugin in the chain and dispatch
 	//  - If no more plugins are interested in this message, then complete
-	FsPluginManager::PrevPlugin(iCurrentPlugin, this, ETrue);
+	FsPluginManager::ReadLockChain();
+	FsPluginManager::PrevPlugin(iCurrentPlugin, this);
 	if(iCurrentPlugin == NULL)
 		{
+	    FsPluginManager::UnlockChain();
 		Complete(GetError());
 		return;
 		}
 
 	Dispatch();
+	FsPluginManager::UnlockChain();
 	return;
 	}
 	
@@ -1015,7 +1018,7 @@
 //
 	{
 	TInt err = KErrNone;
-	if(!iCurrentPlugin->IsPluginThread(*this))
+	if(!iCurrentPlugin->OriginatedFromPlugin(*this))
 		{
 		// The request hasn't come from this plugin so it's safe to dispatch		
 		TFsPluginRequest request(this);		
@@ -1024,7 +1027,7 @@
 
 		if((iOperation->Function() == EFsDismountPlugin) && (err !=  KErrPermissionDenied))
 			{
-			TRAP(leaveValue, err = iOperation->DoRequestL(this));
+		    err = KErrNone;
 			}
 
 		if(leaveValue != KErrNone)
@@ -1042,10 +1045,12 @@
 		// Find the next plugin in the chain and dispatch
 		//  - If no more plugins are interested in this message, 
 		//	  then Dispatch() will process the request in drive/main thread context.
-		FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
+	    FsPluginManager::ReadLockChain();
+		FsPluginManager::NextPlugin(iCurrentPlugin, this);
 		if(iCurrentPlugin && IsPostOperation())
 			SetPostOperation(EFalse);
 		Dispatch();
+		FsPluginManager::UnlockChain();
 		return;
 		}
 	// KErrCompletion may be returned by the plugin to 
@@ -1054,18 +1059,21 @@
 		{
 		// Find the previous plugin in the chain and dispatch
 		//  - If no more plugins are interested in this message, then complete
-		FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
+	    FsPluginManager::ReadLockChain();
+		FsPluginManager::PrevPlugin(iCurrentPlugin, this);
 		if(iCurrentPlugin != NULL)
 			{
 			SetPostOperation(ETrue);
 			err = KErrNone;
 			Dispatch();
+			FsPluginManager::UnlockChain();
 			return;
 			}
 		else
 			{
 			err = KErrNone;	
 			}
+		FsPluginManager::UnlockChain();
 		}
 		
 	Complete(err);
@@ -1124,13 +1132,18 @@
 	iCurrentPlugin = NULL;
 	if (PostInterceptEnabled())
 		{
-		FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
-		if(iCurrentPlugin && !iCurrentPlugin->IsPluginThread(*this))
+	    FsPluginManager::ReadLockChain();
+		FsPluginManager::PrevPlugin(iCurrentPlugin, this);
+		if(iCurrentPlugin && !iCurrentPlugin->OriginatedFromPlugin(*this))
 			{
 			SetPostOperation(ETrue);
 			if (DispatchToPlugin())
+			    {
+		        FsPluginManager::UnlockChain();  
 				return;
+			    }
 			}
+		FsPluginManager::UnlockChain();		
 		}		
 
 	Complete(GetError());
@@ -1409,13 +1422,16 @@
 		iCurrentPlugin = NULL;
 		if (PostInterceptEnabled())
 			{
-			FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
-			if(iCurrentPlugin && !iCurrentPlugin->IsPluginThread(*this))
+		    FsPluginManager::ReadLockChain();
+			FsPluginManager::PrevPlugin(iCurrentPlugin, this);
+			if(iCurrentPlugin && !iCurrentPlugin->OriginatedFromPlugin(*this))
 				{
 				SetPostOperation(ETrue);
 				Dispatch();
+				FsPluginManager::UnlockChain();
 				return r;	// EReqActionComplete
 				}
+			FsPluginManager::UnlockChain();
 			}		
 
 		Complete(KErrNone);
@@ -1443,6 +1459,7 @@
 	__THRD_PRINT1(_L("CFsMessageRequest::Dispatch() req %08x"), this);
 
 	TInt r = KErrNone;
+	TBool pluginChainLocked = EFalse;
 
 	if (iReqState == EReqStateInitialise && aInitialise)
 		{
@@ -1462,16 +1479,18 @@
 			}
 		if(!IsPluginSpecific() && (iOwnerPlugin == NULL))
 			{
+		    FsPluginManager::ReadLockChain(); // Unlocked in DispatchToPlugin
+		    pluginChainLocked = ETrue;
 			iCurrentPlugin = NULL;
 			iClientThreadId = 0;
-			FsPluginManager::NextPlugin(iCurrentPlugin, this, (TBool)ETrue);
+			FsPluginManager::NextPlugin(iCurrentPlugin, this);
 
 			// find out whether there is a plugin registered to post intercept this message
 			CFsPlugin* postInterceptPlugin = NULL;
 			if (iCurrentPlugin == NULL)
-				FsPluginManager::PrevPlugin(postInterceptPlugin, this, (TBool)ETrue);
+				FsPluginManager::PrevPlugin(postInterceptPlugin, this);
 
-			// Save the client's thread Id for subsequent testing by CFsPlugin::IsPluginThread() - doing so on the fly 
+			// Save the client's thread Id for subsequent testing by CFsPlugin::OriginatedFromPlugin() - doing so on the fly 
 			// is risky because some messages are completed early in which case Message().Client() will result in a panic
 			if ((iCurrentPlugin || postInterceptPlugin) && Message().Handle() != NULL && Message().Handle() != KLocalMessageHandle)
 				{
@@ -1490,16 +1509,23 @@
 		__PLUGIN_PRINT1(_L("PLUGIN: CFsMessageRequest %x dispatched to plugin (async)"), this);
 		// The request has been delivered to the plugin thread
 		//  - leave the main thread now and await asynchronous completion
+		if(pluginChainLocked)
+		    FsPluginManager::UnlockChain();
 		return;
 		}
 
+	//DispatchToPlugin didn't (deliver then unlock) so make sure we unlock here.
+    if(pluginChainLocked)
+        FsPluginManager::UnlockChain();
 
 	// Is there a PostInitialise function ?
 	if (iReqState ==  EReqStatePostInitialise && aInitialise && r == KErrNone)
 		{
 		TInt r = PostInitialise();
 		if (r == EReqActionComplete)
+		    {
 			return;
+		    }
 		else if (r == EReqActionBusy)				// request postponed ?
 			SetState(EReqStatePostInitialise);		// reinitialize when request is next processed
 		}
@@ -1559,6 +1585,7 @@
 //
 // Common route: Receive -> Process -> Dispatch -> DispatchToPlugin
 //
+// (Is called with FsPluginManager ReadLocked)
 	{
 	TInt drivenumber = DriveNumber();
 	if(iCurrentPlugin)
@@ -1572,16 +1599,16 @@
 				iCurrentPlugin = NULL;
 				}
 
-			while(iCurrentPlugin && iCurrentPlugin->IsPluginThread(*this))
+			while(iCurrentPlugin && iCurrentPlugin->OriginatedFromPlugin(*this))
 				{
 				// Skip the current plugin if the request originated from the plugin
 				if(IsPostOperation())
 					{
-					FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
+					FsPluginManager::PrevPlugin(iCurrentPlugin, this);
 					}
 				else
 					{
-					FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
+					FsPluginManager::NextPlugin(iCurrentPlugin, this);
 					}
 				}
 				
@@ -1611,7 +1638,7 @@
 					//  - Pass the message on to the next plugin
 					if(FsFunction() != EFsPluginOpen)
 					    {
-	                    FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
+	                    FsPluginManager::NextPlugin(iCurrentPlugin, this);
 	                    continue;
 					    }
 					else // FsFunction == EFsPluginOpen
@@ -1619,7 +1646,6 @@
 					    /* 
 					     * PluginOpen requests should not be passed down the plugin stack.
 					     * 
-
 					     */
 					    iCurrentPlugin = NULL;
 					    continue;
@@ -1630,7 +1656,7 @@
 					// The plugin has processed synchronously (case 2)
 					//  - Pass the message back up the stack
 					SetPostOperation(ETrue);
-					FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
+					FsPluginManager::PrevPlugin(iCurrentPlugin, this);
 					continue;
 					}
 				_LIT(KPanic,"Panic: F32-BAD-PLUGIN-ERROR");
@@ -1652,13 +1678,17 @@
 			}			
 		}
 
+	/*
+	 * Special case- DismountPlugin runs in the context of the plugin thread
+	 */
 	if(iOperation->Function() == EFsDismountPlugin)
 		{
 		// Don't pass plugin dismounts to the drive thread
+	    FsPluginManager::UnlockChain();
 		Process();
+		FsPluginManager::ReadLockChain(); //inverted unlock/lock to get around dismount plugin being a special case
 		return(ETrue);
 		}
-		
 	return EFalse;
 	}
 
--- a/userlibandfileserver/fileserver/sfsrv/cl_scan.cpp	Mon Jul 26 10:52:56 2010 +0100
+++ b/userlibandfileserver/fileserver/sfsrv/cl_scan.cpp	Fri Aug 06 16:34:38 2010 +0100
@@ -411,7 +411,7 @@
 	TInt r;
 	aDirEntries=NULL;
 	
-	if(iStack && iStack->IsEmpty())
+	if(iStack->IsEmpty())
 	    return;
 	
 	CDirList* list=iStack->Peek();