graphicshwdrivers/surfacemgr/test/testdriver/d_sharedchunk.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicshwdrivers/surfacemgr/test/testdriver/d_sharedchunk.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,406 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+
+#include <kernel/kern_priv.h>
+#include "d_sharedchunk.h"
+
+static TInt ChunkDestroyedCount=1;	// Test counter
+
+//
+// Class definitions
+//
+
+class DSharedChunkFactory : public DLogicalDevice
+	{
+public:
+	~DSharedChunkFactory();
+	virtual TInt Install();
+	virtual void GetCaps(TDes8& aDes) const;
+	virtual TInt Create(DLogicalChannelBase*& aChannel);
+	void LockWait();
+	void LockSignal();
+private:
+	NFastMutex iLock;
+	};
+
+class DSharedChunkChannel : public DLogicalChannelBase
+	{
+public:
+	DSharedChunkChannel();
+	~DSharedChunkChannel();
+	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
+	DChunk* OpenChunk(TLinAddr* aKernelAddr=0, TInt* aMaxSize=0);
+	inline void LockWait()
+		{ iFactory->LockWait(); }
+	inline void LockSignal()
+		{ iFactory->LockSignal(); }
+public:
+	DSharedChunkFactory*	iFactory;
+	DChunk*					iChunk;
+	TLinAddr				iKernelAddress;
+	TInt					iMaxSize;
+
+public:
+	/** Require physically contiguous memory */
+	TInt iContiguous;
+	/** Caching attribute to create chunks memory */
+	TInt iCacheAttrib;
+	};
+
+class TChunkCleanup : public TDfc
+	{
+public:
+	TChunkCleanup(DSharedChunkFactory* aFactory);
+	~TChunkCleanup();
+	static void ChunkDestroyed(TChunkCleanup* aSelf);
+	void Cancel();
+public:
+	DSharedChunkFactory* iFactory;
+	};
+
+//
+// TChunkCleanup
+//
+
+TChunkCleanup::TChunkCleanup(DSharedChunkFactory* aFactory)
+	: TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
+	, iFactory(0)
+	{
+	aFactory->Open();
+	iFactory = aFactory;
+	}
+
+TChunkCleanup::~TChunkCleanup()
+	{
+	if(iFactory)
+		iFactory->Close(0);
+	}
+
+void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
+	{
+	DSharedChunkFactory* factory = aSelf->iFactory;
+	if(factory)
+		{
+		factory->LockWait();
+		++ChunkDestroyedCount;
+		factory->LockSignal();
+		}
+	delete aSelf;
+	}
+
+void TChunkCleanup::Cancel()
+	{
+	if(iFactory)
+		{
+		iFactory->Close(0);
+		iFactory = 0;
+		}
+	};
+
+//
+// DSharedChunkFactory
+//
+
+TInt DSharedChunkFactory::Install()
+	{
+	return SetName(&KSharedChunkLddName);
+	}
+
+DSharedChunkFactory::~DSharedChunkFactory()
+	{
+
+	}
+
+void DSharedChunkFactory::GetCaps(TDes8& /*aDes*/) const
+	{
+	// Not used but required as DLogicalDevice::GetCaps is pure virtual
+	}
+
+TInt DSharedChunkFactory::Create(DLogicalChannelBase*& aChannel)
+	{
+	aChannel = NULL;
+	DSharedChunkChannel* channel=new DSharedChunkChannel;
+	if(!channel)
+		return KErrNoMemory;
+	channel->iFactory = this;
+	aChannel = channel;
+	return KErrNone;
+	}
+
+void DSharedChunkFactory::LockWait()
+	{
+	NKern::FMWait(&iLock);
+	}
+
+void DSharedChunkFactory::LockSignal()
+	{
+	NKern::FMSignal(&iLock);
+	}
+
+DECLARE_STANDARD_LDD()
+	{
+	return new DSharedChunkFactory;
+	}
+
+//
+// DSharedChunkChannel
+//
+
+TInt DSharedChunkChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
+	{
+	return KErrNone;
+	}
+
+DSharedChunkChannel::DSharedChunkChannel()
+:iFactory(0),iChunk(0),iKernelAddress(0),iMaxSize(0), iContiguous(0),iCacheAttrib(0)
+	{
+	}
+
+DSharedChunkChannel::~DSharedChunkChannel()
+	{
+	if(iChunk)
+		iChunk->Close(0);
+	}
+
+DChunk* DSharedChunkChannel::OpenChunk(TLinAddr* aKernelAddr,TInt* aMaxSize)
+	{
+	__ASSERT_CRITICAL	// Thread must be in critical section (to avoid leaking access count on chunk)
+	LockWait();
+	DChunk* chunk=iChunk;
+	if(chunk)
+		if(chunk->Open()!=KErrNone)
+			chunk = NULL;
+	if(aKernelAddr)
+		*aKernelAddr = chunk ? iKernelAddress : NULL;
+	if(aMaxSize)
+		*aMaxSize = chunk ? iMaxSize : 0;
+	LockSignal();
+	return chunk;
+	}
+
+TInt DSharedChunkChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
+	{
+	TInt i1 = (TInt)a1;
+	TInt i2 = (TInt)a2;
+
+	TInt r=KErrNotSupported;
+
+	switch(aFunction)
+		{
+
+	case RSharedChunkLdd::ECreateChunk:
+		{
+		if(ChunkDestroyedCount==0)
+			NKern::Sleep(NKern::TimerTicks(100)); // Go idle for a while to let chunk cleanup DFCs to be called
+
+		NKern::ThreadEnterCS();
+
+		TChunkCleanup* cleanup = new TChunkCleanup(this->iFactory);
+		if(!cleanup)
+			{
+			NKern::ThreadLeaveCS();
+			return KErrNoMemory;
+			}
+
+		// Try and create chunk...
+		DChunk* chunk;
+		TChunkCreateInfo info;
+
+		info.iType		 = (i1&EMultiple)
+							? TChunkCreateInfo::ESharedKernelMultiple
+							: TChunkCreateInfo::ESharedKernelSingle;
+
+		info.iMaxSize	 = i1&~ECreateFlagsMask;
+#ifndef __WINS__
+		info.iMapAttr = (i1&ECached) ? EMapAttrCachedMax
+						 : EMapAttrFullyBlocking;
+#else
+		info.iMapAttr = 0;
+#endif
+
+		info.iOwnsMemory = (i1&EOwnsMemory)!=0;
+
+		info.iDestroyedDfc = cleanup;
+
+		if(i1&EBadType) *(TUint8*)&info.iType = 0xff;
+
+		TUint32 mapAttr;
+		TUint32 kernAddr;
+		r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
+		if(r!=KErrNone)
+			{
+			Kern::Printf("Chunk create failed with reason: %d",r);
+			delete cleanup;
+			NKern::ThreadLeaveCS();
+			return r;
+			}
+
+		// Setup data members
+		LockWait();
+		
+		if(iChunk)
+			r = KErrAlreadyExists;
+		else
+			{
+			iChunk = chunk;
+			iKernelAddress = kernAddr;
+			iMaxSize = info.iMaxSize;
+#ifndef __WINS__
+			TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
+			TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
+			TBool chunkIsNotcached =  ((level2Info == EMapAttrL2Uncached) &&
+			    ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
+			     (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
+			iCacheAttrib = (chunkIsNotcached) ? ENotCached : ECached;
+
+#else
+			iCacheAttrib = 0;
+#endif
+			ChunkDestroyedCount = 0;
+			}
+		LockSignal();
+
+		if(r!=KErrNone)
+			{
+			// There was an error, so discard created chunk
+			cleanup->Cancel();
+			Kern::ChunkClose(chunk);
+			NKern::ThreadLeaveCS();
+			return r;
+			}
+
+		NKern::ThreadLeaveCS();
+
+		// Write back kernel address of chunk
+		if(a2)
+			kumemput32(a2,(TAny*)&kernAddr,4);
+
+		return KErrNone;
+		}
+
+
+	case RSharedChunkLdd::EGetChunkHandle:
+		{
+		NKern::ThreadEnterCS();
+		DChunk* chunk=OpenChunk();
+		if(chunk)
+			{
+			Kern::Printf("We can open a chunk here.");
+			r = Kern::MakeHandleAndOpen(0,chunk);
+			Kern::Printf("The chunk handle we get is: %d", r);
+			chunk->Close(0);
+			}
+		else
+			r = KErrNotFound;
+		NKern::ThreadLeaveCS();
+		return r;
+		}
+
+
+	case RSharedChunkLdd::ECloseChunkHandle:
+		{
+		NKern::ThreadEnterCS();
+		r = Kern::CloseHandle(0,i1);
+		NKern::ThreadLeaveCS();
+		return r;
+		}
+
+
+	case RSharedChunkLdd::ECommitMemory:
+		{
+		NKern::ThreadEnterCS();
+		TUint32 chunkKernelAddress;
+		DChunk* chunk=OpenChunk(&chunkKernelAddress);
+		if(chunk)
+			{
+			TInt type = i1&ECommitTypeMask;
+			i1 &= ~ECommitTypeMask;
+			iContiguous = type;
+			switch(type)
+				{
+			case ENonContiguous:
+				r = Kern::ChunkCommit(chunk,i1,i2);
+				break;
+
+			case EContiguous:
+				{
+				TUint32 physAddr=~0u;
+				r = Kern::ChunkCommitContiguous(chunk,i1,i2,physAddr);
+				if(r!=KErrNone || i2==0)
+					break;
+				if(physAddr==~0u)
+					{ r=KErrGeneral; break; }
+
+				// Check that ChunkPhysicalAddress returns addresses consistant with the commit
+				TUint32 kernAddr;
+				TUint32 mapAttr;
+				TUint32 physAddr2;
+				r = Kern::ChunkPhysicalAddress(chunk, i1, i2, kernAddr, mapAttr, physAddr2);
+				if(r==KErrNone)
+					if(kernAddr!=chunkKernelAddress+i1 || physAddr2!=physAddr)
+						r=KErrGeneral;
+				}
+				break;
+
+			default:
+				r = KErrNotSupported;
+				break;
+				}
+			chunk->Close(0);
+			}
+		else
+			r = KErrNotFound;
+		NKern::ThreadLeaveCS();
+		return r;
+		}
+
+	case RSharedChunkLdd::ECloseChunk:
+		{
+		NKern::ThreadEnterCS();
+
+		// Claim ownership of the chunk
+		LockWait();
+		DChunk* chunk=iChunk;
+		iChunk = 0;
+		LockSignal();
+
+		// Close the chunk
+		if(chunk)
+			r = Kern::ChunkClose(chunk);
+		else
+			r = KErrNotFound;
+
+		NKern::ThreadLeaveCS();
+		return r;
+		}
+
+	case RSharedChunkLdd::ECacheAttribute:
+		{
+		Kern::Printf("In my shared chunk, the iCacheAttrib is: %d", iCacheAttrib);
+		return iCacheAttrib;
+		}
+
+	case RSharedChunkLdd::EContiguousAttribute:
+		{
+		Kern::Printf("In my shared chunk, the iContiguous is: %d", iContiguous);
+		return iContiguous;
+		}
+
+	default:
+		return KErrNotSupported;
+		}
+	}
+