os/graphics/graphicshwdrivers/surfacemgr/test/testdriver/d_sharedchunk.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <kernel/kern_priv.h>
sl@0
    17
#include "d_sharedchunk.h"
sl@0
    18
sl@0
    19
static TInt ChunkDestroyedCount=1;	// Test counter
sl@0
    20
sl@0
    21
//
sl@0
    22
// Class definitions
sl@0
    23
//
sl@0
    24
sl@0
    25
class DSharedChunkFactory : public DLogicalDevice
sl@0
    26
	{
sl@0
    27
public:
sl@0
    28
	~DSharedChunkFactory();
sl@0
    29
	virtual TInt Install();
sl@0
    30
	virtual void GetCaps(TDes8& aDes) const;
sl@0
    31
	virtual TInt Create(DLogicalChannelBase*& aChannel);
sl@0
    32
	void LockWait();
sl@0
    33
	void LockSignal();
sl@0
    34
private:
sl@0
    35
	NFastMutex iLock;
sl@0
    36
	};
sl@0
    37
sl@0
    38
class DSharedChunkChannel : public DLogicalChannelBase
sl@0
    39
	{
sl@0
    40
public:
sl@0
    41
	DSharedChunkChannel();
sl@0
    42
	~DSharedChunkChannel();
sl@0
    43
	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
sl@0
    44
	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
sl@0
    45
	DChunk* OpenChunk(TLinAddr* aKernelAddr=0, TInt* aMaxSize=0);
sl@0
    46
	inline void LockWait()
sl@0
    47
		{ iFactory->LockWait(); }
sl@0
    48
	inline void LockSignal()
sl@0
    49
		{ iFactory->LockSignal(); }
sl@0
    50
public:
sl@0
    51
	DSharedChunkFactory*	iFactory;
sl@0
    52
	DChunk*					iChunk;
sl@0
    53
	TLinAddr				iKernelAddress;
sl@0
    54
	TInt					iMaxSize;
sl@0
    55
sl@0
    56
public:
sl@0
    57
	/** Require physically contiguous memory */
sl@0
    58
	TInt iContiguous;
sl@0
    59
	/** Caching attribute to create chunks memory */
sl@0
    60
	TInt iCacheAttrib;
sl@0
    61
	};
sl@0
    62
sl@0
    63
class TChunkCleanup : public TDfc
sl@0
    64
	{
sl@0
    65
public:
sl@0
    66
	TChunkCleanup(DSharedChunkFactory* aFactory);
sl@0
    67
	~TChunkCleanup();
sl@0
    68
	static void ChunkDestroyed(TChunkCleanup* aSelf);
sl@0
    69
	void Cancel();
sl@0
    70
public:
sl@0
    71
	DSharedChunkFactory* iFactory;
sl@0
    72
	};
sl@0
    73
sl@0
    74
//
sl@0
    75
// TChunkCleanup
sl@0
    76
//
sl@0
    77
sl@0
    78
TChunkCleanup::TChunkCleanup(DSharedChunkFactory* aFactory)
sl@0
    79
	: TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
sl@0
    80
	, iFactory(0)
sl@0
    81
	{
sl@0
    82
	aFactory->Open();
sl@0
    83
	iFactory = aFactory;
sl@0
    84
	}
sl@0
    85
sl@0
    86
TChunkCleanup::~TChunkCleanup()
sl@0
    87
	{
sl@0
    88
	if(iFactory)
sl@0
    89
		iFactory->Close(0);
sl@0
    90
	}
sl@0
    91
sl@0
    92
void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
sl@0
    93
	{
sl@0
    94
	DSharedChunkFactory* factory = aSelf->iFactory;
sl@0
    95
	if(factory)
sl@0
    96
		{
sl@0
    97
		factory->LockWait();
sl@0
    98
		++ChunkDestroyedCount;
sl@0
    99
		factory->LockSignal();
sl@0
   100
		}
sl@0
   101
	delete aSelf;
sl@0
   102
	}
sl@0
   103
sl@0
   104
void TChunkCleanup::Cancel()
sl@0
   105
	{
sl@0
   106
	if(iFactory)
sl@0
   107
		{
sl@0
   108
		iFactory->Close(0);
sl@0
   109
		iFactory = 0;
sl@0
   110
		}
sl@0
   111
	};
sl@0
   112
sl@0
   113
//
sl@0
   114
// DSharedChunkFactory
sl@0
   115
//
sl@0
   116
sl@0
   117
TInt DSharedChunkFactory::Install()
sl@0
   118
	{
sl@0
   119
	return SetName(&KSharedChunkLddName);
sl@0
   120
	}
sl@0
   121
sl@0
   122
DSharedChunkFactory::~DSharedChunkFactory()
sl@0
   123
	{
sl@0
   124
sl@0
   125
	}
sl@0
   126
sl@0
   127
void DSharedChunkFactory::GetCaps(TDes8& /*aDes*/) const
sl@0
   128
	{
sl@0
   129
	// Not used but required as DLogicalDevice::GetCaps is pure virtual
sl@0
   130
	}
sl@0
   131
sl@0
   132
TInt DSharedChunkFactory::Create(DLogicalChannelBase*& aChannel)
sl@0
   133
	{
sl@0
   134
	aChannel = NULL;
sl@0
   135
	DSharedChunkChannel* channel=new DSharedChunkChannel;
sl@0
   136
	if(!channel)
sl@0
   137
		return KErrNoMemory;
sl@0
   138
	channel->iFactory = this;
sl@0
   139
	aChannel = channel;
sl@0
   140
	return KErrNone;
sl@0
   141
	}
sl@0
   142
sl@0
   143
void DSharedChunkFactory::LockWait()
sl@0
   144
	{
sl@0
   145
	NKern::FMWait(&iLock);
sl@0
   146
	}
sl@0
   147
sl@0
   148
void DSharedChunkFactory::LockSignal()
sl@0
   149
	{
sl@0
   150
	NKern::FMSignal(&iLock);
sl@0
   151
	}
sl@0
   152
sl@0
   153
DECLARE_STANDARD_LDD()
sl@0
   154
	{
sl@0
   155
	return new DSharedChunkFactory;
sl@0
   156
	}
sl@0
   157
sl@0
   158
//
sl@0
   159
// DSharedChunkChannel
sl@0
   160
//
sl@0
   161
sl@0
   162
TInt DSharedChunkChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
sl@0
   163
	{
sl@0
   164
	return KErrNone;
sl@0
   165
	}
sl@0
   166
sl@0
   167
DSharedChunkChannel::DSharedChunkChannel()
sl@0
   168
:iFactory(0),iChunk(0),iKernelAddress(0),iMaxSize(0), iContiguous(0),iCacheAttrib(0)
sl@0
   169
	{
sl@0
   170
	}
sl@0
   171
sl@0
   172
DSharedChunkChannel::~DSharedChunkChannel()
sl@0
   173
	{
sl@0
   174
	if(iChunk)
sl@0
   175
		iChunk->Close(0);
sl@0
   176
	}
sl@0
   177
sl@0
   178
DChunk* DSharedChunkChannel::OpenChunk(TLinAddr* aKernelAddr,TInt* aMaxSize)
sl@0
   179
	{
sl@0
   180
	__ASSERT_CRITICAL	// Thread must be in critical section (to avoid leaking access count on chunk)
sl@0
   181
	LockWait();
sl@0
   182
	DChunk* chunk=iChunk;
sl@0
   183
	if(chunk)
sl@0
   184
		if(chunk->Open()!=KErrNone)
sl@0
   185
			chunk = NULL;
sl@0
   186
	if(aKernelAddr)
sl@0
   187
		*aKernelAddr = chunk ? iKernelAddress : NULL;
sl@0
   188
	if(aMaxSize)
sl@0
   189
		*aMaxSize = chunk ? iMaxSize : 0;
sl@0
   190
	LockSignal();
sl@0
   191
	return chunk;
sl@0
   192
	}
sl@0
   193
sl@0
   194
TInt DSharedChunkChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
sl@0
   195
	{
sl@0
   196
	TInt i1 = (TInt)a1;
sl@0
   197
	TInt i2 = (TInt)a2;
sl@0
   198
sl@0
   199
	TInt r=KErrNotSupported;
sl@0
   200
sl@0
   201
	switch(aFunction)
sl@0
   202
		{
sl@0
   203
sl@0
   204
	case RSharedChunkLdd::ECreateChunk:
sl@0
   205
		{
sl@0
   206
		if(ChunkDestroyedCount==0)
sl@0
   207
			NKern::Sleep(NKern::TimerTicks(100)); // Go idle for a while to let chunk cleanup DFCs to be called
sl@0
   208
sl@0
   209
		NKern::ThreadEnterCS();
sl@0
   210
sl@0
   211
		TChunkCleanup* cleanup = new TChunkCleanup(this->iFactory);
sl@0
   212
		if(!cleanup)
sl@0
   213
			{
sl@0
   214
			NKern::ThreadLeaveCS();
sl@0
   215
			return KErrNoMemory;
sl@0
   216
			}
sl@0
   217
sl@0
   218
		// Try and create chunk...
sl@0
   219
		DChunk* chunk;
sl@0
   220
		TChunkCreateInfo info;
sl@0
   221
sl@0
   222
		info.iType		 = (i1&EMultiple)
sl@0
   223
							? TChunkCreateInfo::ESharedKernelMultiple
sl@0
   224
							: TChunkCreateInfo::ESharedKernelSingle;
sl@0
   225
sl@0
   226
		info.iMaxSize	 = i1&~ECreateFlagsMask;
sl@0
   227
#ifndef __WINS__
sl@0
   228
		info.iMapAttr = (i1&ECached) ? EMapAttrCachedMax
sl@0
   229
						 : EMapAttrFullyBlocking;
sl@0
   230
#else
sl@0
   231
		info.iMapAttr = 0;
sl@0
   232
#endif
sl@0
   233
sl@0
   234
		info.iOwnsMemory = (i1&EOwnsMemory)!=0;
sl@0
   235
sl@0
   236
		info.iDestroyedDfc = cleanup;
sl@0
   237
sl@0
   238
		if(i1&EBadType) *(TUint8*)&info.iType = 0xff;
sl@0
   239
sl@0
   240
		TUint32 mapAttr;
sl@0
   241
		TUint32 kernAddr;
sl@0
   242
		r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
sl@0
   243
		if(r!=KErrNone)
sl@0
   244
			{
sl@0
   245
			Kern::Printf("Chunk create failed with reason: %d",r);
sl@0
   246
			delete cleanup;
sl@0
   247
			NKern::ThreadLeaveCS();
sl@0
   248
			return r;
sl@0
   249
			}
sl@0
   250
sl@0
   251
		// Setup data members
sl@0
   252
		LockWait();
sl@0
   253
		
sl@0
   254
		if(iChunk)
sl@0
   255
			r = KErrAlreadyExists;
sl@0
   256
		else
sl@0
   257
			{
sl@0
   258
			iChunk = chunk;
sl@0
   259
			iKernelAddress = kernAddr;
sl@0
   260
			iMaxSize = info.iMaxSize;
sl@0
   261
#ifndef __WINS__
sl@0
   262
			TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
sl@0
   263
			TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
sl@0
   264
			TBool chunkIsNotcached =  ((level2Info == EMapAttrL2Uncached) &&
sl@0
   265
			    ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
sl@0
   266
			     (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
sl@0
   267
			iCacheAttrib = (chunkIsNotcached) ? ENotCached : ECached;
sl@0
   268
sl@0
   269
#else
sl@0
   270
			iCacheAttrib = 0;
sl@0
   271
#endif
sl@0
   272
			ChunkDestroyedCount = 0;
sl@0
   273
			}
sl@0
   274
		LockSignal();
sl@0
   275
sl@0
   276
		if(r!=KErrNone)
sl@0
   277
			{
sl@0
   278
			// There was an error, so discard created chunk
sl@0
   279
			cleanup->Cancel();
sl@0
   280
			Kern::ChunkClose(chunk);
sl@0
   281
			NKern::ThreadLeaveCS();
sl@0
   282
			return r;
sl@0
   283
			}
sl@0
   284
sl@0
   285
		NKern::ThreadLeaveCS();
sl@0
   286
sl@0
   287
		// Write back kernel address of chunk
sl@0
   288
		if(a2)
sl@0
   289
			kumemput32(a2,(TAny*)&kernAddr,4);
sl@0
   290
sl@0
   291
		return KErrNone;
sl@0
   292
		}
sl@0
   293
sl@0
   294
sl@0
   295
	case RSharedChunkLdd::EGetChunkHandle:
sl@0
   296
		{
sl@0
   297
		NKern::ThreadEnterCS();
sl@0
   298
		DChunk* chunk=OpenChunk();
sl@0
   299
		if(chunk)
sl@0
   300
			{
sl@0
   301
			Kern::Printf("We can open a chunk here.");
sl@0
   302
			r = Kern::MakeHandleAndOpen(0,chunk);
sl@0
   303
			Kern::Printf("The chunk handle we get is: %d", r);
sl@0
   304
			chunk->Close(0);
sl@0
   305
			}
sl@0
   306
		else
sl@0
   307
			r = KErrNotFound;
sl@0
   308
		NKern::ThreadLeaveCS();
sl@0
   309
		return r;
sl@0
   310
		}
sl@0
   311
sl@0
   312
sl@0
   313
	case RSharedChunkLdd::ECloseChunkHandle:
sl@0
   314
		{
sl@0
   315
		NKern::ThreadEnterCS();
sl@0
   316
		r = Kern::CloseHandle(0,i1);
sl@0
   317
		NKern::ThreadLeaveCS();
sl@0
   318
		return r;
sl@0
   319
		}
sl@0
   320
sl@0
   321
sl@0
   322
	case RSharedChunkLdd::ECommitMemory:
sl@0
   323
		{
sl@0
   324
		NKern::ThreadEnterCS();
sl@0
   325
		TUint32 chunkKernelAddress;
sl@0
   326
		DChunk* chunk=OpenChunk(&chunkKernelAddress);
sl@0
   327
		if(chunk)
sl@0
   328
			{
sl@0
   329
			TInt type = i1&ECommitTypeMask;
sl@0
   330
			i1 &= ~ECommitTypeMask;
sl@0
   331
			iContiguous = type;
sl@0
   332
			switch(type)
sl@0
   333
				{
sl@0
   334
			case ENonContiguous:
sl@0
   335
				r = Kern::ChunkCommit(chunk,i1,i2);
sl@0
   336
				break;
sl@0
   337
sl@0
   338
			case EContiguous:
sl@0
   339
				{
sl@0
   340
				TUint32 physAddr=~0u;
sl@0
   341
				r = Kern::ChunkCommitContiguous(chunk,i1,i2,physAddr);
sl@0
   342
				if(r!=KErrNone || i2==0)
sl@0
   343
					break;
sl@0
   344
				if(physAddr==~0u)
sl@0
   345
					{ r=KErrGeneral; break; }
sl@0
   346
sl@0
   347
				// Check that ChunkPhysicalAddress returns addresses consistant with the commit
sl@0
   348
				TUint32 kernAddr;
sl@0
   349
				TUint32 mapAttr;
sl@0
   350
				TUint32 physAddr2;
sl@0
   351
				r = Kern::ChunkPhysicalAddress(chunk, i1, i2, kernAddr, mapAttr, physAddr2);
sl@0
   352
				if(r==KErrNone)
sl@0
   353
					if(kernAddr!=chunkKernelAddress+i1 || physAddr2!=physAddr)
sl@0
   354
						r=KErrGeneral;
sl@0
   355
				}
sl@0
   356
				break;
sl@0
   357
sl@0
   358
			default:
sl@0
   359
				r = KErrNotSupported;
sl@0
   360
				break;
sl@0
   361
				}
sl@0
   362
			chunk->Close(0);
sl@0
   363
			}
sl@0
   364
		else
sl@0
   365
			r = KErrNotFound;
sl@0
   366
		NKern::ThreadLeaveCS();
sl@0
   367
		return r;
sl@0
   368
		}
sl@0
   369
sl@0
   370
	case RSharedChunkLdd::ECloseChunk:
sl@0
   371
		{
sl@0
   372
		NKern::ThreadEnterCS();
sl@0
   373
sl@0
   374
		// Claim ownership of the chunk
sl@0
   375
		LockWait();
sl@0
   376
		DChunk* chunk=iChunk;
sl@0
   377
		iChunk = 0;
sl@0
   378
		LockSignal();
sl@0
   379
sl@0
   380
		// Close the chunk
sl@0
   381
		if(chunk)
sl@0
   382
			r = Kern::ChunkClose(chunk);
sl@0
   383
		else
sl@0
   384
			r = KErrNotFound;
sl@0
   385
sl@0
   386
		NKern::ThreadLeaveCS();
sl@0
   387
		return r;
sl@0
   388
		}
sl@0
   389
sl@0
   390
	case RSharedChunkLdd::ECacheAttribute:
sl@0
   391
		{
sl@0
   392
		Kern::Printf("In my shared chunk, the iCacheAttrib is: %d", iCacheAttrib);
sl@0
   393
		return iCacheAttrib;
sl@0
   394
		}
sl@0
   395
sl@0
   396
	case RSharedChunkLdd::EContiguousAttribute:
sl@0
   397
		{
sl@0
   398
		Kern::Printf("In my shared chunk, the iContiguous is: %d", iContiguous);
sl@0
   399
		return iContiguous;
sl@0
   400
		}
sl@0
   401
sl@0
   402
	default:
sl@0
   403
		return KErrNotSupported;
sl@0
   404
		}
sl@0
   405
	}
sl@0
   406