diff -r 000000000000 -r 5d03bc08d59c windowing/windowserver/nonnga/SERVER/WsMemMgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/windowing/windowserver/nonnga/SERVER/WsMemMgr.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,198 @@ +// 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 "WsMemMgr.h" +#include "inifile.h" +#include "panics.h" +#include "wstop.h" + +CWsMemoryManager * CWsMemoryManager::iStatic = NULL; + +CWsMemoryManager * CWsMemoryManager::Static() + { + return iStatic; + } + +CWsMemoryManager * CWsMemoryManager::NewLC() + { + CWsMemoryManager * self = new (ELeave) CWsMemoryManager; + CleanupStack::PushL(self); + self->ConstructL(); + iStatic = self; + return iStatic; + } + +CWsMemoryManager::CWsMemoryManager() + { + iImpl = User::SwitchAllocator(this); + } + +CWsMemoryManager::~CWsMemoryManager() + { + WS_ASSERT_ALWAYS(this == User::SwitchAllocator(iImpl),EWsPanicMemoryManager); + iStatic = 0; + if (iReserve!=NULL) + { + Free(iReserve); + iReserve = NULL; + } + } + +void CWsMemoryManager::ConstructL() + { + _LIT(KMemMgrReserve, "MEMORYRESERVE"); + const TInt KDefaultMemMgrReserve = 1024; + + if (!WsIniFile->FindVar(KMemMgrReserve, iReserveSize)) + iReserveSize = KDefaultMemMgrReserve; + + if (iReserveSize > 0) + iReserve = Alloc(iReserveSize); + } + +/** +Implementing RAllocator +*/ + +/** +Alloc and ReAlloc attempt to obtain memory through CWsTop::ReleaseMemory when they run low. +ReleaseMemory looks for blocks of memory that the window server doesn't need urgently and frees +them. +*/ +TAny* CWsMemoryManager::Alloc(TInt aSize) + { + TBool keepTrying = ETrue; + do + { + if(iReleasing) + return iImpl->Alloc(aSize); //fallback on RAllocator + + if(TAny* ret = iImpl->Alloc(aSize)) //normal case + return ret; + + if(iReserveEnabled && iReserve && (aSize < iReserveSize)) + { + Free(iReserve); + iReserve = NULL; + } + else + { + iReleasing = ETrue; + keepTrying = CWsTop::ReleaseMemory(); + if(keepTrying) + { + const TInt reclaimed = Compress(); //Try to give back to the OS + } + iReleasing = EFalse; + } + + } while(keepTrying); + + return NULL; + } + +TAny* CWsMemoryManager::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode) + { + TBool keepTrying = ETrue; + do + { + if(iReleasing) + return iImpl->ReAlloc(aPtr, aSize, aMode); //fallback on RAllocator + + if(TAny* ret = iImpl->ReAlloc(aPtr, aSize, aMode)) //normal case + return ret; + + if(iReserveEnabled && iReserve && (aSize < iReserveSize)) + { + Free(iReserve); + iReserve = NULL; + } + else + { + iReleasing = ETrue; + keepTrying = CWsTop::ReleaseMemory(); + if(keepTrying) + { + const TInt reclaimed = Compress(); //Try to give back to the OS + } + iReleasing = EFalse; + } + + } while(keepTrying); + + return NULL; + } + +/** +The rest of these functions just call the default implementation +*/ +void CWsMemoryManager::Free(TAny* aPtr) + { + return iImpl->Free(aPtr); + } + +TInt CWsMemoryManager::AllocLen(const TAny* aCell) const + { + return iImpl->AllocLen(aCell); + } + +TInt CWsMemoryManager::Compress() + { + return iImpl->Compress(); + } + +void CWsMemoryManager::Reset() + { + iImpl->Reset(); + } + +TInt CWsMemoryManager::AllocSize(TInt& aTotalAllocSize) const + { + return iImpl->AllocSize(aTotalAllocSize); + } + +TInt CWsMemoryManager::Available(TInt& aBiggestBlock) const + { + return iImpl->Available(aBiggestBlock); + } + +TInt CWsMemoryManager::DebugFunction(TInt aFunc, TAny* a1, TAny* a2) + { + return iImpl->DebugFunction(aFunc,a1,a2); + } + +TInt CWsMemoryManager::Count() const + { + return iImpl->Count(); + } +/** This is a fairly dumb way to enable and disable the reserve, but we normally +get away with it because wserv is high priority. A better approach would be to +use placement new into the reserve memory and manage it directly. This would also +allow us to track misbehaving code which allocated during OOM drawing and didn't +free at the end. +*/ +void CWsMemoryManager::EnableReserve() + { + WS_ASSERT_DEBUG(!iReserveEnabled, EWsPanicMemoryManager); + iReserveEnabled = ETrue; + } + +void CWsMemoryManager::DisableReserve() + { + WS_ASSERT_DEBUG(iReserveEnabled, EWsPanicMemoryManager); + iReserveEnabled = EFalse; + if((!iReserve) && (iReserveSize > 0)) + iReserve = Alloc(iReserveSize); + }