1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_memory_man.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,349 @@
1.4 +// Copyright (c) 2008-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 the License "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 +// f32\sfile\sf_memory_man.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +/**
1.22 + @file
1.23 + @internalTechnology
1.24 +*/
1.25 +
1.26 +
1.27 +#include <e32std.h>
1.28 +#include <e32std_private.h>
1.29 +#include "sf_std.h"
1.30 +#include <e32uid.h>
1.31 +#include <e32wins.h>
1.32 +#include <f32file.h>
1.33 +#include <hal.h>
1.34 +#include "sf_memory_man.h"
1.35 +#include "sf_memory_client.h"
1.36 +
1.37 +/**
1.38 +Destructor of the CCacheMemoryManager, need to destroy all registered clients.
1.39 +*/
1.40 +CCacheMemoryManager::~CCacheMemoryManager()
1.41 + {
1.42 + for (TInt i = 0; i < iRegisteredClients.Count(); i++)
1.43 + {
1.44 + iRegisteredClients[i]->Reset();
1.45 + delete iRegisteredClients[i];
1.46 + }
1.47 + iRegisteredClients.Close();
1.48 + }
1.49 +
1.50 +/**
1.51 +Static factory function of CCacheMemoryManager
1.52 +@param aCacheSize the total size of the virtual address space
1.53 +*/
1.54 +CCacheMemoryManager* CCacheMemoryManager::NewL(TInt aCacheSize)
1.55 + {
1.56 + CCacheMemoryManager* cacheMemoryManager = new (ELeave) CCacheMemoryManager(aCacheSize);
1.57 +
1.58 + CleanupStack::PushL(cacheMemoryManager);
1.59 + cacheMemoryManager->ConstructL();
1.60 + CleanupStack::Pop(1, cacheMemoryManager);
1.61 +
1.62 + return cacheMemoryManager;
1.63 + }
1.64 +
1.65 +/**
1.66 +Constructor of CCacheMemoryManager
1.67 +@param aMaxSize the total size of the virtual address space
1.68 +*/
1.69 +CCacheMemoryManager::CCacheMemoryManager(TUint32 aMaxSize)
1.70 +:iBase(NULL),
1.71 +iSizeInBytes(aMaxSize),
1.72 +iCurrentOffsetMark(0)
1.73 + {
1.74 + }
1.75 +
1.76 +/**
1.77 +Second phase constructor of CCacheMemoryManager.
1.78 +Creates RChunk object and sets low memory threshold.
1.79 +*/
1.80 +void CCacheMemoryManager::ConstructL()
1.81 + {
1.82 + // calculate the low-memory threshold below which we fail any attempt to allocate memory
1.83 + TMemoryInfoV1Buf meminfo;
1.84 + TInt r = UserHal::MemoryInfo(meminfo);
1.85 + ASSERT(r==KErrNone);
1.86 + User::LeaveIfError(r);
1.87 + iLowMemoryThreshold = (meminfo().iTotalRamInBytes * TGlobalCacheMemorySettings::LowMemoryThreshold()) / 100;
1.88 + TChunkCreateInfo createInfo;
1.89 + createInfo.SetCache(iSizeInBytes);
1.90 + createInfo.SetOwner(EOwnerProcess);
1.91 + r = iChunk.Create(createInfo);
1.92 + ASSERT(r==KErrNone);
1.93 + User::LeaveIfError(r);
1.94 + UserSvr::RegisterTrustedChunk(iChunk.Handle());
1.95 + iBase = iChunk.Base();
1.96 + iRegisteredClients.ReserveL(10);
1.97 + __PRINT3(_L("CCacheMemoryManager::ConstructL(lowMem=%d, iSize=%d, base=0x%lx)"), iLowMemoryThreshold, iSizeInBytes, iBase);
1.98 + }
1.99 +
1.100 +/**
1.101 +Connect or register a client.
1.102 +Note: callers of this function should be constructor of various caches, it is their resposibility
1.103 + to make sure that parameters are sensible when calling this function
1.104 +
1.105 +@internalTechnology
1.106 +@released
1.107 +
1.108 +@param aClientName an identifier of the client to be connected
1.109 +@param aMinSizeInSegs minimum client size in segments
1.110 +@param aMaxSizeInSegs maximum client size in segments
1.111 +@return CCacheMemoryClient* pointer to the client that connected, or NULL if parameters are not valid.
1.112 +@leave if no memory
1.113 +*/
1.114 +EXPORT_C CCacheMemoryClient* CCacheMemoryManager::ConnectClientL(const TDesC& aClientName, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs)
1.115 + {
1.116 + __PRINT3(_L("CCacheMemoryManager::ConnectClientL([%S], minSeg=%d, maxSeg=%d)"), &aClientName, aMinSizeInSegs, aMaxSizeInSegs);
1.117 +
1.118 + // search for existing clients by name
1.119 + for (TInt i = 0; i < iRegisteredClients.Count(); i++)
1.120 + {
1.121 + if (aClientName.Compare(iRegisteredClients[i]->Name()) == 0)
1.122 + {
1.123 + ASSERT(iRegisteredClients[i]->iTouchedRegionFlag == 0);
1.124 + __PRINT1(_L("CCacheMemoryManager::ConnectClientL: [%S] found!"), &aClientName);
1.125 + return iRegisteredClients[i];
1.126 + }
1.127 + }
1.128 +
1.129 + // if it is a new drive/file system who wants to connect, create a new client for it
1.130 + // parameter validation
1.131 + ASSERT(iSizeInBytes > iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2()));
1.132 + if (iSizeInBytes < iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2()))
1.133 + {
1.134 + ASSERT(0);
1.135 + User::Leave(KErrArgument);
1.136 + }
1.137 +
1.138 + // note: client creation may leave under OOM conditions
1.139 + CCacheMemoryClient* client = CCacheMemoryClient::NewL(*this, aClientName, iCurrentOffsetMark, aMinSizeInSegs, aMaxSizeInSegs);
1.140 +
1.141 + // if error happens during client registration, the client will be deleted
1.142 + // this may leave under OOM conditions
1.143 + TInt err = iRegisteredClients.Append(client);
1.144 + if (err != KErrNone)
1.145 + {
1.146 + ASSERT(0);
1.147 + delete client;
1.148 + client = NULL;
1.149 + User::Leave(err);
1.150 + }
1.151 +
1.152 + // record current offset mark for next client
1.153 + iCurrentOffsetMark += (aMaxSizeInSegs << SegmentSizeInBytesLog2());
1.154 + return client;
1.155 + }
1.156 +
1.157 +/**
1.158 +Commit a contiguous set of segments.
1.159 +@param aStartRamAddr the start ram address of the region to be committed.
1.160 +@param aSegmentCount the segment number of the contiguous region to be committed.
1.161 +@return TInt KErrNone if succeeded, KErrNoMemory if passed low memory threshold, otherwise a system-wide error code.
1.162 +*/
1.163 +TInt CCacheMemoryManager::AllocateAndLockSegments(TUint8* aStartRamAddr, TInt aSegmentCount)
1.164 + {
1.165 + __PRINT2(_L("CCacheMemoryManager::AllocateAndLockSegments(base=0x%x, seg=%d)"), aStartRamAddr, aSegmentCount);
1.166 + TMemoryInfoV1Buf meminfo;
1.167 + TInt r = UserHal::MemoryInfo(meminfo);
1.168 + __ASSERT_DEBUG(r==KErrNone,Fault(EMemoryInfoFailed));
1.169 + if (r != KErrNone)
1.170 + {
1.171 + return r;
1.172 + }
1.173 +
1.174 + if (isMemoryLow || (meminfo().iFreeRamInBytes < iLowMemoryThreshold))
1.175 + {
1.176 + __PRINT(_L("CCacheMemoryManager: free RAM below threshold !!!"));
1.177 + return KErrNoMemory;
1.178 + }
1.179 + return Commit(aStartRamAddr, aSegmentCount);
1.180 + }
1.181 +
1.182 +/**
1.183 +Notify the change of memory status
1.184 +@param aIsMemoryLow the flag that sets current memory status
1.185 +*/
1.186 +void CCacheMemoryManager::FreeMemoryChanged(TBool aIsMemoryLow)
1.187 + {
1.188 + isMemoryLow = aIsMemoryLow;
1.189 + }
1.190 +
1.191 +/**
1.192 +Decommit a contiguous set of segments.
1.193 +@param aStartRamAddr the start ram address of the region to be decommitted.
1.194 +@param aSegmentCount the segment number of the contiguous region to be decommitted.
1.195 +@return TInt KErrNone if succeeded, otherwise a system-wide error code.
1.196 +*/
1.197 +TInt CCacheMemoryManager::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
1.198 + {
1.199 + return Decommit(aStartRamAddr, aSegmentCount);
1.200 + }
1.201 +
1.202 +/**
1.203 +Lock a contiguous set of segments.
1.204 +@param aStartRamAddr the start ram address of the region to be locked.
1.205 +@param aSegmentCount the segment number of the contiguous region to be locked.
1.206 +@return TInt KErrNone if succeeded, otherwise a system-wide error code.
1.207 +*/
1.208 +TInt CCacheMemoryManager::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
1.209 + {
1.210 + return Lock(aStartRamAddr, aSegmentCount);
1.211 + }
1.212 +
1.213 +/**
1.214 +Unlock a contiguous set of segments.
1.215 +@param aStartRamAddr the start ram address of the region to be unlocked.
1.216 +@param aSegmentCount the segment number of the contiguous region to be unlocked.
1.217 +@return TInt KErrNone if succeeded, otherwise a system-wide error code.
1.218 +*/
1.219 +TInt CCacheMemoryManager::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
1.220 + {
1.221 + return Unlock(aStartRamAddr, aSegmentCount);
1.222 + }
1.223 +
1.224 +/**
1.225 +Commit a contiguous set of segments.
1.226 +@param aStartRamAddr the start ram address of the region to be committed.
1.227 +@param aSegmentCount the segment number of the contiguous region to be committed.
1.228 +@return TInt KErrNone if succeeded, otherwise a system-wide error code.
1.229 +*/
1.230 +TInt CCacheMemoryManager::Commit(TUint8* aStartRamAddr, TInt aSegmentCount)
1.231 + {
1.232 + TInt offset = aStartRamAddr - iBase;
1.233 + TInt r = iChunk.Commit(offset, aSegmentCount << KSegmentSizeLog2);
1.234 + return r;
1.235 + }
1.236 +
1.237 +/**
1.238 +Actual implementation of DecommitSegments().
1.239 +@see CCacheMemoryManager::DecommitSegments().
1.240 +*/
1.241 +TInt CCacheMemoryManager::Decommit(TUint8* aStartRamAddr, TInt aSegmentCount)
1.242 + {
1.243 + return iChunk.Decommit(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2);
1.244 + }
1.245 +
1.246 +/**
1.247 +Actual implementation of UnlockSegments().
1.248 +@see CCacheMemoryManager::UnlockSegments().
1.249 +*/
1.250 +TInt CCacheMemoryManager::Unlock(TUint8* aStartRamAddr, TInt aSegmentCount)
1.251 + {
1.252 + TInt r = iChunk.Unlock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2);
1.253 + return r;
1.254 + }
1.255 +
1.256 +/**
1.257 +Actual implementation of LockSegments().
1.258 +@see CCacheMemoryManager::LockSegments().
1.259 +*/
1.260 +TInt CCacheMemoryManager::Lock(TUint8* aStartRamAddr, TInt aSegmentCount)
1.261 + {
1.262 + return iChunk.Lock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2);
1.263 + }
1.264 +
1.265 +
1.266 +//=====================================================================
1.267 +TUint8* CCacheMemoryManager::Base()
1.268 + {
1.269 + return iChunk.Base();
1.270 + }
1.271 +
1.272 +/**
1.273 +Get function, returns log2 value of a segment size in bytes.
1.274 +
1.275 +@internalTechnology
1.276 +@released
1.277 +*/
1.278 +EXPORT_C TUint CCacheMemoryManager::SegmentSizeInBytesLog2() const
1.279 + {
1.280 + return KSegmentSizeLog2;
1.281 + }
1.282 +
1.283 +
1.284 +//=============================================================================
1.285 +/**
1.286 +The singleton of global cache memory manager
1.287 +*/
1.288 +CCacheMemoryManager* CCacheMemoryManagerFactory::iCacheMemoryManager = NULL;
1.289 +
1.290 +/**
1.291 +Global factory function of CCacheMemoryManager.
1.292 +*/
1.293 +void CCacheMemoryManagerFactory::CreateL()
1.294 + {
1.295 + iCacheMemoryManager = CCacheMemoryManager::NewL(TGlobalCacheMemorySettings::CacheSize());
1.296 + }
1.297 +
1.298 +/**
1.299 +Global get function of CCacheMemoryManager.
1.300 +
1.301 +@internalTechnology
1.302 +@released
1.303 +*/
1.304 +EXPORT_C CCacheMemoryManager* CCacheMemoryManagerFactory::CacheMemoryManager()
1.305 + {
1.306 + return iCacheMemoryManager;
1.307 + }
1.308 +
1.309 +/**
1.310 +Global destroy function of CCacheMemoryManager.
1.311 +*/
1.312 +void CCacheMemoryManagerFactory::Destroy()
1.313 + {
1.314 + delete iCacheMemoryManager;
1.315 + iCacheMemoryManager = NULL;
1.316 + }
1.317 +
1.318 +//=============================================================================
1.319 +const TInt KByteToByteShift = 10;
1.320 +TInt32 TGlobalCacheMemorySettings::iCacheSizeInBytes = KDefaultGlobalCacheMemorySize << KByteToByteShift;
1.321 +TInt32 TGlobalCacheMemorySettings::iLowMemoryThreshold = KDefaultLowMemoryThreshold;
1.322 +_LIT8(KLitSectionNameCacheMemory,"CacheMemory");
1.323 +
1.324 +/**
1.325 +Read ESTART.TXT file for global cache memory settings
1.326 +*/
1.327 +void TGlobalCacheMemorySettings::ReadPropertiesFile()
1.328 + {
1.329 + // Get size of cache in kilobytes
1.330 + TInt32 cacheSizeInKBytes;
1.331 + if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("GlobalCacheMemorySize"), cacheSizeInKBytes))
1.332 + {
1.333 + iCacheSizeInBytes = cacheSizeInKBytes << KByteToByteShift;
1.334 + }
1.335 +
1.336 + // Get low memory threshold
1.337 + TInt32 lowMemoryThreshold;
1.338 + if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("LowMemoryThreshold"), lowMemoryThreshold))
1.339 + iLowMemoryThreshold = lowMemoryThreshold;
1.340 + }
1.341 +
1.342 +TInt TGlobalCacheMemorySettings::CacheSize()
1.343 + {
1.344 + return iCacheSizeInBytes;
1.345 + }
1.346 +
1.347 +TInt TGlobalCacheMemorySettings::LowMemoryThreshold()
1.348 + {
1.349 + return iLowMemoryThreshold;
1.350 + }
1.351 +
1.352 +