Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <kernel/kern_priv.h>
17 #include "d_sharedchunk.h"
19 static TInt ChunkDestroyedCount=1; // Test counter
25 class DSharedChunkFactory : public DLogicalDevice
28 ~DSharedChunkFactory();
29 virtual TInt Install();
30 virtual void GetCaps(TDes8& aDes) const;
31 virtual TInt Create(DLogicalChannelBase*& aChannel);
38 class DSharedChunkChannel : public DLogicalChannelBase
41 DSharedChunkChannel();
42 ~DSharedChunkChannel();
43 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
44 virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
45 DChunk* OpenChunk(TLinAddr* aKernelAddr=0, TInt* aMaxSize=0);
46 inline void LockWait()
47 { iFactory->LockWait(); }
48 inline void LockSignal()
49 { iFactory->LockSignal(); }
51 DSharedChunkFactory* iFactory;
53 TLinAddr iKernelAddress;
57 /** Require physically contiguous memory */
59 /** Caching attribute to create chunks memory */
63 class TChunkCleanup : public TDfc
66 TChunkCleanup(DSharedChunkFactory* aFactory);
68 static void ChunkDestroyed(TChunkCleanup* aSelf);
71 DSharedChunkFactory* iFactory;
78 TChunkCleanup::TChunkCleanup(DSharedChunkFactory* aFactory)
79 : TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
86 TChunkCleanup::~TChunkCleanup()
92 void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
94 DSharedChunkFactory* factory = aSelf->iFactory;
98 ++ChunkDestroyedCount;
99 factory->LockSignal();
104 void TChunkCleanup::Cancel()
114 // DSharedChunkFactory
117 TInt DSharedChunkFactory::Install()
119 return SetName(&KSharedChunkLddName);
122 DSharedChunkFactory::~DSharedChunkFactory()
127 void DSharedChunkFactory::GetCaps(TDes8& /*aDes*/) const
129 // Not used but required as DLogicalDevice::GetCaps is pure virtual
132 TInt DSharedChunkFactory::Create(DLogicalChannelBase*& aChannel)
135 DSharedChunkChannel* channel=new DSharedChunkChannel;
138 channel->iFactory = this;
143 void DSharedChunkFactory::LockWait()
145 NKern::FMWait(&iLock);
148 void DSharedChunkFactory::LockSignal()
150 NKern::FMSignal(&iLock);
153 DECLARE_STANDARD_LDD()
155 return new DSharedChunkFactory;
159 // DSharedChunkChannel
162 TInt DSharedChunkChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
167 DSharedChunkChannel::DSharedChunkChannel()
168 :iFactory(0),iChunk(0),iKernelAddress(0),iMaxSize(0), iContiguous(0),iCacheAttrib(0)
172 DSharedChunkChannel::~DSharedChunkChannel()
178 DChunk* DSharedChunkChannel::OpenChunk(TLinAddr* aKernelAddr,TInt* aMaxSize)
180 __ASSERT_CRITICAL // Thread must be in critical section (to avoid leaking access count on chunk)
182 DChunk* chunk=iChunk;
184 if(chunk->Open()!=KErrNone)
187 *aKernelAddr = chunk ? iKernelAddress : NULL;
189 *aMaxSize = chunk ? iMaxSize : 0;
194 TInt DSharedChunkChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
199 TInt r=KErrNotSupported;
204 case RSharedChunkLdd::ECreateChunk:
206 if(ChunkDestroyedCount==0)
207 NKern::Sleep(NKern::TimerTicks(100)); // Go idle for a while to let chunk cleanup DFCs to be called
209 NKern::ThreadEnterCS();
211 TChunkCleanup* cleanup = new TChunkCleanup(this->iFactory);
214 NKern::ThreadLeaveCS();
218 // Try and create chunk...
220 TChunkCreateInfo info;
222 info.iType = (i1&EMultiple)
223 ? TChunkCreateInfo::ESharedKernelMultiple
224 : TChunkCreateInfo::ESharedKernelSingle;
226 info.iMaxSize = i1&~ECreateFlagsMask;
228 info.iMapAttr = (i1&ECached) ? EMapAttrCachedMax
229 : EMapAttrFullyBlocking;
234 info.iOwnsMemory = (i1&EOwnsMemory)!=0;
236 info.iDestroyedDfc = cleanup;
238 if(i1&EBadType) *(TUint8*)&info.iType = 0xff;
242 r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
245 Kern::Printf("Chunk create failed with reason: %d",r);
247 NKern::ThreadLeaveCS();
251 // Setup data members
255 r = KErrAlreadyExists;
259 iKernelAddress = kernAddr;
260 iMaxSize = info.iMaxSize;
262 TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
263 TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
264 TBool chunkIsNotcached = ((level2Info == EMapAttrL2Uncached) &&
265 ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
266 (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
267 iCacheAttrib = (chunkIsNotcached) ? ENotCached : ECached;
272 ChunkDestroyedCount = 0;
278 // There was an error, so discard created chunk
280 Kern::ChunkClose(chunk);
281 NKern::ThreadLeaveCS();
285 NKern::ThreadLeaveCS();
287 // Write back kernel address of chunk
289 kumemput32(a2,(TAny*)&kernAddr,4);
295 case RSharedChunkLdd::EGetChunkHandle:
297 NKern::ThreadEnterCS();
298 DChunk* chunk=OpenChunk();
301 Kern::Printf("We can open a chunk here.");
302 r = Kern::MakeHandleAndOpen(0,chunk);
303 Kern::Printf("The chunk handle we get is: %d", r);
308 NKern::ThreadLeaveCS();
313 case RSharedChunkLdd::ECloseChunkHandle:
315 NKern::ThreadEnterCS();
316 r = Kern::CloseHandle(0,i1);
317 NKern::ThreadLeaveCS();
322 case RSharedChunkLdd::ECommitMemory:
324 NKern::ThreadEnterCS();
325 TUint32 chunkKernelAddress;
326 DChunk* chunk=OpenChunk(&chunkKernelAddress);
329 TInt type = i1&ECommitTypeMask;
330 i1 &= ~ECommitTypeMask;
335 r = Kern::ChunkCommit(chunk,i1,i2);
340 TUint32 physAddr=~0u;
341 r = Kern::ChunkCommitContiguous(chunk,i1,i2,physAddr);
342 if(r!=KErrNone || i2==0)
345 { r=KErrGeneral; break; }
347 // Check that ChunkPhysicalAddress returns addresses consistant with the commit
351 r = Kern::ChunkPhysicalAddress(chunk, i1, i2, kernAddr, mapAttr, physAddr2);
353 if(kernAddr!=chunkKernelAddress+i1 || physAddr2!=physAddr)
359 r = KErrNotSupported;
366 NKern::ThreadLeaveCS();
370 case RSharedChunkLdd::ECloseChunk:
372 NKern::ThreadEnterCS();
374 // Claim ownership of the chunk
376 DChunk* chunk=iChunk;
382 r = Kern::ChunkClose(chunk);
386 NKern::ThreadLeaveCS();
390 case RSharedChunkLdd::ECacheAttribute:
392 Kern::Printf("In my shared chunk, the iCacheAttrib is: %d", iCacheAttrib);
396 case RSharedChunkLdd::EContiguousAttribute:
398 Kern::Printf("In my shared chunk, the iContiguous is: %d", iContiguous);
403 return KErrNotSupported;