diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/sfile/sf_memory_man.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/sfile/sf_memory_man.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,347 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// f32\sfile\sf_memory_man.cpp +// +// + +/** + @file + @internalTechnology +*/ + + +#include +#include +#include "sf_std.h" +#include +#include +#include +#include +#include "sf_memory_man.h" +#include "sf_memory_client.h" + +/** +Destructor of the CCacheMemoryManager, need to destroy all registered clients. +*/ +CCacheMemoryManager::~CCacheMemoryManager() + { + for (TInt i = 0; i < iRegisteredClients.Count(); i++) + { + iRegisteredClients[i]->Reset(); + delete iRegisteredClients[i]; + } + iRegisteredClients.Close(); + } + +/** +Static factory function of CCacheMemoryManager +@param aCacheSize the total size of the virtual address space +*/ +CCacheMemoryManager* CCacheMemoryManager::NewL(TInt aCacheSize) + { + CCacheMemoryManager* cacheMemoryManager = new (ELeave) CCacheMemoryManager(aCacheSize); + + CleanupStack::PushL(cacheMemoryManager); + cacheMemoryManager->ConstructL(); + CleanupStack::Pop(1, cacheMemoryManager); + + return cacheMemoryManager; + } + +/** +Constructor of CCacheMemoryManager +@param aMaxSize the total size of the virtual address space +*/ +CCacheMemoryManager::CCacheMemoryManager(TUint32 aMaxSize) +:iBase(NULL), +iSizeInBytes(aMaxSize), +iCurrentOffsetMark(0) + { + } + +/** +Second phase constructor of CCacheMemoryManager. +Creates RChunk object and sets low memory threshold. +*/ +void CCacheMemoryManager::ConstructL() + { + // calculate the low-memory threshold below which we fail any attempt to allocate memory + TMemoryInfoV1Buf meminfo; + TInt r = UserHal::MemoryInfo(meminfo); + ASSERT(r==KErrNone); + User::LeaveIfError(r); + iLowMemoryThreshold = (meminfo().iTotalRamInBytes * TGlobalCacheMemorySettings::LowMemoryThreshold()) / 100; + TChunkCreateInfo createInfo; + createInfo.SetCache(iSizeInBytes); + createInfo.SetOwner(EOwnerProcess); + r = iChunk.Create(createInfo); + ASSERT(r==KErrNone); + User::LeaveIfError(r); + UserSvr::RegisterTrustedChunk(iChunk.Handle()); + iBase = iChunk.Base(); + iRegisteredClients.ReserveL(10); + __PRINT3(_L("CCacheMemoryManager::ConstructL(lowMem=%d, iSize=%d, base=0x%lx)"), iLowMemoryThreshold, iSizeInBytes, iBase); + } + +/** +Connect or register a client. +Note: callers of this function should be constructor of various caches, it is their resposibility + to make sure that parameters are sensible when calling this function + +@internalTechnology +@released + +@param aClientName an identifier of the client to be connected +@param aMinSizeInSegs minimum client size in segments +@param aMaxSizeInSegs maximum client size in segments +@return CCacheMemoryClient* pointer to the client that connected, or NULL if parameters are not valid. +@leave if no memory +*/ +EXPORT_C CCacheMemoryClient* CCacheMemoryManager::ConnectClientL(const TDesC& aClientName, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs) + { + __PRINT3(_L("CCacheMemoryManager::ConnectClientL: [%S], minSeg=%d, maxSeg=%d"), &aClientName, aMinSizeInSegs, aMaxSizeInSegs); + for (TInt i = 0; i < iRegisteredClients.Count(); i++) + { + if (aClientName.Compare(iRegisteredClients[i]->Name()) == 0) + { + ASSERT(iRegisteredClients[i]->iTouchedRegionFlag == 0); + __PRINT1(_L("CCacheMemoryManager::ConnectClientL: [%S] found!"), &aClientName); + return iRegisteredClients[i]; + } + } + + // parameter validation + ASSERT(iSizeInBytes > iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())); + if (iSizeInBytes < iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())) + { + ASSERT(0); + return NULL; + } + + // if not found in registered clients, creates new + // this may leave under OOM condition + CCacheMemoryClient* client = CCacheMemoryClient::NewL(*this, aClientName, iCurrentOffsetMark, aMinSizeInSegs, aMaxSizeInSegs); + + // if error happens during client registration, the client will be deleted + // this may leave under OOM condition + TInt err = iRegisteredClients.Append(client); + if (err != KErrNone) + { + ASSERT(0); + delete client; + client = NULL; + User::Leave(err); + } + + // record current offset mark for next client + iCurrentOffsetMark += (aMaxSizeInSegs << SegmentSizeInBytesLog2()); + return client; + } + +/** +Commit a contiguous set of segments. +@param aStartRamAddr the start ram address of the region to be committed. +@param aSegmentCount the segment number of the contiguous region to be committed. +@return TInt KErrNone if succeeded, KErrNoMemory if passed low memory threshold, otherwise a system-wide error code. +*/ +TInt CCacheMemoryManager::AllocateAndLockSegments(TUint8* aStartRamAddr, TInt aSegmentCount) + { + __PRINT2(_L("CCacheMemoryManager::AllocateAndLockSegments: base=0x%x, seg=%d"), aStartRamAddr, aSegmentCount); + TMemoryInfoV1Buf meminfo; + TInt r = UserHal::MemoryInfo(meminfo); + __ASSERT_DEBUG(r==KErrNone,Fault(EMemoryInfoFailed)); + if (r != KErrNone) + { + return r; + } + + if (isMemoryLow || (meminfo().iFreeRamInBytes < iLowMemoryThreshold)) + { + __PRINT(_L("CCacheMemoryManager: free RAM below threshold !!!")); + return KErrNoMemory; + } + return Commit(aStartRamAddr, aSegmentCount); + } + +/** +Notify the change of memory status +@param aIsMemoryLow the flag that sets current memory status +*/ +void CCacheMemoryManager::FreeMemoryChanged(TBool aIsMemoryLow) + { + isMemoryLow = aIsMemoryLow; + } + +/** +Decommit a contiguous set of segments. +@param aStartRamAddr the start ram address of the region to be decommitted. +@param aSegmentCount the segment number of the contiguous region to be decommitted. +@return TInt KErrNone if succeeded, otherwise a system-wide error code. +*/ +TInt CCacheMemoryManager::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) + { + return Decommit(aStartRamAddr, aSegmentCount); + } + +/** +Lock a contiguous set of segments. +@param aStartRamAddr the start ram address of the region to be locked. +@param aSegmentCount the segment number of the contiguous region to be locked. +@return TInt KErrNone if succeeded, otherwise a system-wide error code. +*/ +TInt CCacheMemoryManager::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) + { + return Lock(aStartRamAddr, aSegmentCount); + } + +/** +Unlock a contiguous set of segments. +@param aStartRamAddr the start ram address of the region to be unlocked. +@param aSegmentCount the segment number of the contiguous region to be unlocked. +@return TInt KErrNone if succeeded, otherwise a system-wide error code. +*/ +TInt CCacheMemoryManager::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) + { + return Unlock(aStartRamAddr, aSegmentCount); + } + +/** +Commit a contiguous set of segments. +@param aStartRamAddr the start ram address of the region to be committed. +@param aSegmentCount the segment number of the contiguous region to be committed. +@return TInt KErrNone if succeeded, otherwise a system-wide error code. +*/ +TInt CCacheMemoryManager::Commit(TUint8* aStartRamAddr, TInt aSegmentCount) + { + TInt offset = aStartRamAddr - iBase; + TInt r = iChunk.Commit(offset, aSegmentCount << KSegmentSizeLog2); + return r; + } + +/** +Actual implementation of DecommitSegments(). +@see CCacheMemoryManager::DecommitSegments(). +*/ +TInt CCacheMemoryManager::Decommit(TUint8* aStartRamAddr, TInt aSegmentCount) + { + return iChunk.Decommit(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); + } + +/** +Actual implementation of UnlockSegments(). +@see CCacheMemoryManager::UnlockSegments(). +*/ +TInt CCacheMemoryManager::Unlock(TUint8* aStartRamAddr, TInt aSegmentCount) + { + TInt r = iChunk.Unlock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); + return r; + } + +/** +Actual implementation of LockSegments(). +@see CCacheMemoryManager::LockSegments(). +*/ +TInt CCacheMemoryManager::Lock(TUint8* aStartRamAddr, TInt aSegmentCount) + { + return iChunk.Lock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); + } + + +//===================================================================== +TUint8* CCacheMemoryManager::Base() + { + return iChunk.Base(); + } + +/** +Get function, returns log2 value of a segment size in bytes. + +@internalTechnology +@released +*/ +EXPORT_C TUint CCacheMemoryManager::SegmentSizeInBytesLog2() const + { + return KSegmentSizeLog2; + } + + +//============================================================================= +/** +The singleton of global cache memory manager +*/ +CCacheMemoryManager* CCacheMemoryManagerFactory::iCacheMemoryManager = NULL; + +/** +Global factory function of CCacheMemoryManager. +*/ +void CCacheMemoryManagerFactory::CreateL() + { + iCacheMemoryManager = CCacheMemoryManager::NewL(TGlobalCacheMemorySettings::CacheSize()); + } + +/** +Global get function of CCacheMemoryManager. + +@internalTechnology +@released +*/ +EXPORT_C CCacheMemoryManager* CCacheMemoryManagerFactory::CacheMemoryManager() + { + return iCacheMemoryManager; + } + +/** +Global destroy function of CCacheMemoryManager. +*/ +void CCacheMemoryManagerFactory::Destroy() + { + delete iCacheMemoryManager; + iCacheMemoryManager = NULL; + } + +//============================================================================= +const TInt KByteToByteShift = 10; +TInt32 TGlobalCacheMemorySettings::iCacheSizeInBytes = KDefaultGlobalCacheMemorySize << KByteToByteShift; +TInt32 TGlobalCacheMemorySettings::iLowMemoryThreshold = KDefaultLowMemoryThreshold; +_LIT8(KLitSectionNameCacheMemory,"CacheMemory"); + +/** +Read ESTART.TXT file for global cache memory settings +*/ +void TGlobalCacheMemorySettings::ReadPropertiesFile() + { + // Get size of cache in kilobytes + TInt32 cacheSizeInKBytes; + if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("GlobalCacheMemorySize"), cacheSizeInKBytes)) + { + iCacheSizeInBytes = cacheSizeInKBytes << KByteToByteShift; + } + + // Get low memory threshold + TInt32 lowMemoryThreshold; + if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("LowMemoryThreshold"), lowMemoryThreshold)) + iLowMemoryThreshold = lowMemoryThreshold; + } + +TInt TGlobalCacheMemorySettings::CacheSize() + { + return iCacheSizeInBytes; + } + +TInt TGlobalCacheMemorySettings::LowMemoryThreshold() + { + return iLowMemoryThreshold; + } + +