Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.
// 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;
}
}