1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicshwdrivers/surfacemgr/test/testdriver/d_sharedchunk.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,406 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <kernel/kern_priv.h>
1.20 +#include "d_sharedchunk.h"
1.21 +
1.22 +static TInt ChunkDestroyedCount=1; // Test counter
1.23 +
1.24 +//
1.25 +// Class definitions
1.26 +//
1.27 +
1.28 +class DSharedChunkFactory : public DLogicalDevice
1.29 + {
1.30 +public:
1.31 + ~DSharedChunkFactory();
1.32 + virtual TInt Install();
1.33 + virtual void GetCaps(TDes8& aDes) const;
1.34 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.35 + void LockWait();
1.36 + void LockSignal();
1.37 +private:
1.38 + NFastMutex iLock;
1.39 + };
1.40 +
1.41 +class DSharedChunkChannel : public DLogicalChannelBase
1.42 + {
1.43 +public:
1.44 + DSharedChunkChannel();
1.45 + ~DSharedChunkChannel();
1.46 + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
1.47 + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
1.48 + DChunk* OpenChunk(TLinAddr* aKernelAddr=0, TInt* aMaxSize=0);
1.49 + inline void LockWait()
1.50 + { iFactory->LockWait(); }
1.51 + inline void LockSignal()
1.52 + { iFactory->LockSignal(); }
1.53 +public:
1.54 + DSharedChunkFactory* iFactory;
1.55 + DChunk* iChunk;
1.56 + TLinAddr iKernelAddress;
1.57 + TInt iMaxSize;
1.58 +
1.59 +public:
1.60 + /** Require physically contiguous memory */
1.61 + TInt iContiguous;
1.62 + /** Caching attribute to create chunks memory */
1.63 + TInt iCacheAttrib;
1.64 + };
1.65 +
1.66 +class TChunkCleanup : public TDfc
1.67 + {
1.68 +public:
1.69 + TChunkCleanup(DSharedChunkFactory* aFactory);
1.70 + ~TChunkCleanup();
1.71 + static void ChunkDestroyed(TChunkCleanup* aSelf);
1.72 + void Cancel();
1.73 +public:
1.74 + DSharedChunkFactory* iFactory;
1.75 + };
1.76 +
1.77 +//
1.78 +// TChunkCleanup
1.79 +//
1.80 +
1.81 +TChunkCleanup::TChunkCleanup(DSharedChunkFactory* aFactory)
1.82 + : TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
1.83 + , iFactory(0)
1.84 + {
1.85 + aFactory->Open();
1.86 + iFactory = aFactory;
1.87 + }
1.88 +
1.89 +TChunkCleanup::~TChunkCleanup()
1.90 + {
1.91 + if(iFactory)
1.92 + iFactory->Close(0);
1.93 + }
1.94 +
1.95 +void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
1.96 + {
1.97 + DSharedChunkFactory* factory = aSelf->iFactory;
1.98 + if(factory)
1.99 + {
1.100 + factory->LockWait();
1.101 + ++ChunkDestroyedCount;
1.102 + factory->LockSignal();
1.103 + }
1.104 + delete aSelf;
1.105 + }
1.106 +
1.107 +void TChunkCleanup::Cancel()
1.108 + {
1.109 + if(iFactory)
1.110 + {
1.111 + iFactory->Close(0);
1.112 + iFactory = 0;
1.113 + }
1.114 + };
1.115 +
1.116 +//
1.117 +// DSharedChunkFactory
1.118 +//
1.119 +
1.120 +TInt DSharedChunkFactory::Install()
1.121 + {
1.122 + return SetName(&KSharedChunkLddName);
1.123 + }
1.124 +
1.125 +DSharedChunkFactory::~DSharedChunkFactory()
1.126 + {
1.127 +
1.128 + }
1.129 +
1.130 +void DSharedChunkFactory::GetCaps(TDes8& /*aDes*/) const
1.131 + {
1.132 + // Not used but required as DLogicalDevice::GetCaps is pure virtual
1.133 + }
1.134 +
1.135 +TInt DSharedChunkFactory::Create(DLogicalChannelBase*& aChannel)
1.136 + {
1.137 + aChannel = NULL;
1.138 + DSharedChunkChannel* channel=new DSharedChunkChannel;
1.139 + if(!channel)
1.140 + return KErrNoMemory;
1.141 + channel->iFactory = this;
1.142 + aChannel = channel;
1.143 + return KErrNone;
1.144 + }
1.145 +
1.146 +void DSharedChunkFactory::LockWait()
1.147 + {
1.148 + NKern::FMWait(&iLock);
1.149 + }
1.150 +
1.151 +void DSharedChunkFactory::LockSignal()
1.152 + {
1.153 + NKern::FMSignal(&iLock);
1.154 + }
1.155 +
1.156 +DECLARE_STANDARD_LDD()
1.157 + {
1.158 + return new DSharedChunkFactory;
1.159 + }
1.160 +
1.161 +//
1.162 +// DSharedChunkChannel
1.163 +//
1.164 +
1.165 +TInt DSharedChunkChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.166 + {
1.167 + return KErrNone;
1.168 + }
1.169 +
1.170 +DSharedChunkChannel::DSharedChunkChannel()
1.171 +:iFactory(0),iChunk(0),iKernelAddress(0),iMaxSize(0), iContiguous(0),iCacheAttrib(0)
1.172 + {
1.173 + }
1.174 +
1.175 +DSharedChunkChannel::~DSharedChunkChannel()
1.176 + {
1.177 + if(iChunk)
1.178 + iChunk->Close(0);
1.179 + }
1.180 +
1.181 +DChunk* DSharedChunkChannel::OpenChunk(TLinAddr* aKernelAddr,TInt* aMaxSize)
1.182 + {
1.183 + __ASSERT_CRITICAL // Thread must be in critical section (to avoid leaking access count on chunk)
1.184 + LockWait();
1.185 + DChunk* chunk=iChunk;
1.186 + if(chunk)
1.187 + if(chunk->Open()!=KErrNone)
1.188 + chunk = NULL;
1.189 + if(aKernelAddr)
1.190 + *aKernelAddr = chunk ? iKernelAddress : NULL;
1.191 + if(aMaxSize)
1.192 + *aMaxSize = chunk ? iMaxSize : 0;
1.193 + LockSignal();
1.194 + return chunk;
1.195 + }
1.196 +
1.197 +TInt DSharedChunkChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
1.198 + {
1.199 + TInt i1 = (TInt)a1;
1.200 + TInt i2 = (TInt)a2;
1.201 +
1.202 + TInt r=KErrNotSupported;
1.203 +
1.204 + switch(aFunction)
1.205 + {
1.206 +
1.207 + case RSharedChunkLdd::ECreateChunk:
1.208 + {
1.209 + if(ChunkDestroyedCount==0)
1.210 + NKern::Sleep(NKern::TimerTicks(100)); // Go idle for a while to let chunk cleanup DFCs to be called
1.211 +
1.212 + NKern::ThreadEnterCS();
1.213 +
1.214 + TChunkCleanup* cleanup = new TChunkCleanup(this->iFactory);
1.215 + if(!cleanup)
1.216 + {
1.217 + NKern::ThreadLeaveCS();
1.218 + return KErrNoMemory;
1.219 + }
1.220 +
1.221 + // Try and create chunk...
1.222 + DChunk* chunk;
1.223 + TChunkCreateInfo info;
1.224 +
1.225 + info.iType = (i1&EMultiple)
1.226 + ? TChunkCreateInfo::ESharedKernelMultiple
1.227 + : TChunkCreateInfo::ESharedKernelSingle;
1.228 +
1.229 + info.iMaxSize = i1&~ECreateFlagsMask;
1.230 +#ifndef __WINS__
1.231 + info.iMapAttr = (i1&ECached) ? EMapAttrCachedMax
1.232 + : EMapAttrFullyBlocking;
1.233 +#else
1.234 + info.iMapAttr = 0;
1.235 +#endif
1.236 +
1.237 + info.iOwnsMemory = (i1&EOwnsMemory)!=0;
1.238 +
1.239 + info.iDestroyedDfc = cleanup;
1.240 +
1.241 + if(i1&EBadType) *(TUint8*)&info.iType = 0xff;
1.242 +
1.243 + TUint32 mapAttr;
1.244 + TUint32 kernAddr;
1.245 + r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
1.246 + if(r!=KErrNone)
1.247 + {
1.248 + Kern::Printf("Chunk create failed with reason: %d",r);
1.249 + delete cleanup;
1.250 + NKern::ThreadLeaveCS();
1.251 + return r;
1.252 + }
1.253 +
1.254 + // Setup data members
1.255 + LockWait();
1.256 +
1.257 + if(iChunk)
1.258 + r = KErrAlreadyExists;
1.259 + else
1.260 + {
1.261 + iChunk = chunk;
1.262 + iKernelAddress = kernAddr;
1.263 + iMaxSize = info.iMaxSize;
1.264 +#ifndef __WINS__
1.265 + TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
1.266 + TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
1.267 + TBool chunkIsNotcached = ((level2Info == EMapAttrL2Uncached) &&
1.268 + ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
1.269 + (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
1.270 + iCacheAttrib = (chunkIsNotcached) ? ENotCached : ECached;
1.271 +
1.272 +#else
1.273 + iCacheAttrib = 0;
1.274 +#endif
1.275 + ChunkDestroyedCount = 0;
1.276 + }
1.277 + LockSignal();
1.278 +
1.279 + if(r!=KErrNone)
1.280 + {
1.281 + // There was an error, so discard created chunk
1.282 + cleanup->Cancel();
1.283 + Kern::ChunkClose(chunk);
1.284 + NKern::ThreadLeaveCS();
1.285 + return r;
1.286 + }
1.287 +
1.288 + NKern::ThreadLeaveCS();
1.289 +
1.290 + // Write back kernel address of chunk
1.291 + if(a2)
1.292 + kumemput32(a2,(TAny*)&kernAddr,4);
1.293 +
1.294 + return KErrNone;
1.295 + }
1.296 +
1.297 +
1.298 + case RSharedChunkLdd::EGetChunkHandle:
1.299 + {
1.300 + NKern::ThreadEnterCS();
1.301 + DChunk* chunk=OpenChunk();
1.302 + if(chunk)
1.303 + {
1.304 + Kern::Printf("We can open a chunk here.");
1.305 + r = Kern::MakeHandleAndOpen(0,chunk);
1.306 + Kern::Printf("The chunk handle we get is: %d", r);
1.307 + chunk->Close(0);
1.308 + }
1.309 + else
1.310 + r = KErrNotFound;
1.311 + NKern::ThreadLeaveCS();
1.312 + return r;
1.313 + }
1.314 +
1.315 +
1.316 + case RSharedChunkLdd::ECloseChunkHandle:
1.317 + {
1.318 + NKern::ThreadEnterCS();
1.319 + r = Kern::CloseHandle(0,i1);
1.320 + NKern::ThreadLeaveCS();
1.321 + return r;
1.322 + }
1.323 +
1.324 +
1.325 + case RSharedChunkLdd::ECommitMemory:
1.326 + {
1.327 + NKern::ThreadEnterCS();
1.328 + TUint32 chunkKernelAddress;
1.329 + DChunk* chunk=OpenChunk(&chunkKernelAddress);
1.330 + if(chunk)
1.331 + {
1.332 + TInt type = i1&ECommitTypeMask;
1.333 + i1 &= ~ECommitTypeMask;
1.334 + iContiguous = type;
1.335 + switch(type)
1.336 + {
1.337 + case ENonContiguous:
1.338 + r = Kern::ChunkCommit(chunk,i1,i2);
1.339 + break;
1.340 +
1.341 + case EContiguous:
1.342 + {
1.343 + TUint32 physAddr=~0u;
1.344 + r = Kern::ChunkCommitContiguous(chunk,i1,i2,physAddr);
1.345 + if(r!=KErrNone || i2==0)
1.346 + break;
1.347 + if(physAddr==~0u)
1.348 + { r=KErrGeneral; break; }
1.349 +
1.350 + // Check that ChunkPhysicalAddress returns addresses consistant with the commit
1.351 + TUint32 kernAddr;
1.352 + TUint32 mapAttr;
1.353 + TUint32 physAddr2;
1.354 + r = Kern::ChunkPhysicalAddress(chunk, i1, i2, kernAddr, mapAttr, physAddr2);
1.355 + if(r==KErrNone)
1.356 + if(kernAddr!=chunkKernelAddress+i1 || physAddr2!=physAddr)
1.357 + r=KErrGeneral;
1.358 + }
1.359 + break;
1.360 +
1.361 + default:
1.362 + r = KErrNotSupported;
1.363 + break;
1.364 + }
1.365 + chunk->Close(0);
1.366 + }
1.367 + else
1.368 + r = KErrNotFound;
1.369 + NKern::ThreadLeaveCS();
1.370 + return r;
1.371 + }
1.372 +
1.373 + case RSharedChunkLdd::ECloseChunk:
1.374 + {
1.375 + NKern::ThreadEnterCS();
1.376 +
1.377 + // Claim ownership of the chunk
1.378 + LockWait();
1.379 + DChunk* chunk=iChunk;
1.380 + iChunk = 0;
1.381 + LockSignal();
1.382 +
1.383 + // Close the chunk
1.384 + if(chunk)
1.385 + r = Kern::ChunkClose(chunk);
1.386 + else
1.387 + r = KErrNotFound;
1.388 +
1.389 + NKern::ThreadLeaveCS();
1.390 + return r;
1.391 + }
1.392 +
1.393 + case RSharedChunkLdd::ECacheAttribute:
1.394 + {
1.395 + Kern::Printf("In my shared chunk, the iCacheAttrib is: %d", iCacheAttrib);
1.396 + return iCacheAttrib;
1.397 + }
1.398 +
1.399 + case RSharedChunkLdd::EContiguousAttribute:
1.400 + {
1.401 + Kern::Printf("In my shared chunk, the iContiguous is: %d", iContiguous);
1.402 + return iContiguous;
1.403 + }
1.404 +
1.405 + default:
1.406 + return KErrNotSupported;
1.407 + }
1.408 + }
1.409 +