webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp
changeset 1 7c90e6132015
parent 0 dd21522fd290
child 10 a359256acfc6
--- a/webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp	Mon Mar 30 12:54:55 2009 +0300
+++ b/webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp	Fri May 08 08:25:06 2009 +0300
@@ -25,7 +25,9 @@
 #include "MemoryPool.h"
 #include "StopScheduler.h"
 #include "fast_malloc.h"
+#include "SymbianDlHeap.h"
 #include <OOMMonitorSession.h>
+#include <hal.h>
 
 // CONSTANTS
 
@@ -390,11 +392,29 @@
     // avoid small checkings
     if( aTotalSize < 1024 ) return ETrue;
 
+	// first check the application heap's max free block
+	TInt maxFreeBlock = 0;
+	User::Allocator().Available(maxFreeBlock);
+	if (aTotalSize < maxFreeBlock)
+		return ETrue;
+	
+
     // free memory in Hal
     TMemoryInfoV1Buf info;
     UserHal::MemoryInfo( info );
     TInt sizeNeeded = aTotalSize + iRescueBufferSize;
-    if( sizeNeeded > info().iFreeRamInBytes )
+
+	// check if there is enough space for the heap to grow
+	bool needSysCheck = EFalse;
+	if (info().iFreeRamInBytes > sizeNeeded) {
+		RHeap& heap = User::Heap();
+		if (heap.MaxLength() - heap.Size() > sizeNeeded)
+			return ETrue;
+
+		needSysCheck = ETrue;
+	}
+
+	if(sizeNeeded > info().iFreeRamInBytes || needSysCheck)
         {
         CollectMemory(sizeNeeded);
         
@@ -425,4 +445,215 @@
     // do nothing here.
     }
 
+#ifdef __NEW_ALLOCATOR__
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::FreeMemory
+//-----------------------------------------------------------------------------
+TUint CNewSymbianHeapPool::FreeMemory(TFreeMem& /*aFree*/ )
+    {
+    // TODO: implement free_memory
+    return KMaxTUint;
+//    return free_memory( aFree.iPool, aFree.iHeap, aFree.iHal );
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::DoAlloc
+//-----------------------------------------------------------------------------
+TAny* CNewSymbianHeapPool::DoAlloc( TUint aSize )
+    {
+    return iAlloc->Alloc( aSize );
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::ReAllocate
+//-----------------------------------------------------------------------------
+TAny* CNewSymbianHeapPool::ReAllocate( TAny* aPtr, TUint aSize )
+    {
+    // reset the status for next allocation
+    iMemStatus &= ~ERescueOOM;
+
+    TAny* p = iAlloc->ReAlloc( aPtr, aSize );
+    
+    // check memory manager status
+    if( !p || iMemStatus & ERescueOOM )
+        {
+        if( !iIsCollecting )
+            {
+            CollectMemory();
+            }
+
+        if( !p )
+			p = iAlloc->ReAlloc( aPtr, aSize );
+
+        NotifyAndStop();
+        }
+
+    return p;
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::PreCheck
+//-----------------------------------------------------------------------------
+TBool CNewSymbianHeapPool::PreCheck(TUint aTotalSize, TUint aMaxBufSize,
+		const TDesC8& /*aCheckerName*/)
+	{
+	/* aTotalSize - total amount desired
+	 * aMaxBufSize - largest single allocation desired
+	 */
+
+	// avoid small checkings
+	if (aTotalSize < 1024)
+		return ETrue;
+
+	/*
+	 * Browser fast_malloc implementation merges together total/max allocation requests and says YES if system free memory is >6MB
+	 */
+	// mirror existing size calculation
+	aTotalSize = aTotalSize > (aMaxBufSize * 2) ? aTotalSize
+			: (aMaxBufSize * 2);
+
+	// if we have more than 6 MB of free mem, we 
+	// should skip malloc_info call.
+	// free memory in Hal
+    TInt systemFreeMemory = 0;
+	if( HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory) == KErrNone )
+		{
+		const TUint checkThreshold = 6*1024*1024;
+		if(systemFreeMemory> checkThreshold && systemFreeMemory> aTotalSize)
+		return ETrue;
+		}
+
+	/* For a proper implementation of RHeap, the stats available are:
+	 * AllocSize	Total number of allocated bytes
+	 * Size			Total number of bytes held from system
+	 * Available	Max block size and amount of bytes held but not allocated
+	 */
+	/* We don't have those bits of the heap implemented yet
+	 */ 
+	TInt freeSpace = 0; // be conservative, use 0 intead of 64<<10;
+	TInt req = freeSpace + systemFreeMemory - aTotalSize;	
+	
+	if(req > 0)
+		return ETrue;
+	
+	// First, ask system for memory from other applications.
+	ROomMonitorSession oomMs;
+	if (oomMs.Connect() == KErrNone)
+		{
+		oomMs.RequestFreeMemory(aTotalSize);
+		oomMs.Close();
+		}
+
+	// We haven't altered our heap yet, so ask the system how much is free now...
+	HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory);
+	req = freeSpace + systemFreeMemory - aTotalSize;	
+	
+	if(req > 0)
+		return ETrue;
+	
+	// We haven't got the required amount free yet, try the browser heap.
+	CollectMemory(aTotalSize);
+	// ask the system how much is free now...
+	HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory);
+	req = freeSpace + systemFreeMemory - aTotalSize;	
+	
+	// if we still haven't got enough RAM, we should stop the browser from going any further just yet.
+	if (req < 0)
+		{
+		iMemStatus |= ECheckOOM;
+		NotifyAndStop();
+		return EFalse;
+		}
+	
+	return ETrue;
+	}
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::PostCheck
+//-----------------------------------------------------------------------------
+TUint CNewSymbianHeapPool::PostCheck()
+    {
+    return iMemStatus;
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::Free
+//-----------------------------------------------------------------------------
+void CNewSymbianHeapPool::Free( TAny* aPtr )
+    {
+    return iAlloc->Free( aPtr );
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::MemorySize
+//-----------------------------------------------------------------------------
+TUint CNewSymbianHeapPool::MemorySize( TAny* aPtr )
+    {
+    return iAlloc->AllocLen( aPtr );
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::SetRescueBufferSize
+//-----------------------------------------------------------------------------
+void CNewSymbianHeapPool::SetRescueBufferSize( TInt /*aSize*/ )
+    {
+    //fast_set_rescue_buffer_size( aSize );
+    }
+
+//-----------------------------------------------------------------------------
+// CNewSymbianHeapPool::RestoreRescueBuffer
+//-----------------------------------------------------------------------------
+void CNewSymbianHeapPool::RestoreRescueBuffer()
+    {
+    //alloc_rescue_buffer();
+    }
+
+CNewSymbianHeapPool::CNewSymbianHeapPool() : CMemoryPool()
+	{
+	}
+
+CNewSymbianHeapPool::~CNewSymbianHeapPool()
+	{
+//	iAlloc->Close();	// TODO: Need to clean up here, but it's not implemented in the allocator yet.
+						// Not fatal anyway because all the handles are process local and we should only
+						// be deleting this object when we're closing the allocator - which we never do
+						// except at process end.
+	}
+
+const TInt KMaxHeapSize = 0x2000000; //32MB
+const TInt KHeapGrowSize = 0x10000;  //64KB
+
+TBool CNewSymbianHeapPool::Create()
+	{
+	// need to know system page size
+	TInt page_size;
+	UserHal::PageSizeInBytes(page_size);
+
+	// Create the thread's heap chunk.
+	//
+	// The chunk needs reserve enough address space for twice the maximum allocation
+	// The heap object is instantiated exactly half way up the chunk, and initially is provided just 1 page of memory
+	// This memory can be committed as part of the call to creat the chunk
+	//
+	TInt maxChunkSize = 2 * KMaxHeapSize;
+	TInt offset = KMaxHeapSize;
+	TInt minLength = page_size;
+	RChunk c;
+	TInt r = c.CreateDisconnectedLocal(offset, offset+minLength, maxChunkSize, EOwnerProcess);
+	if (r!=KErrNone)
+		return EFalse;
+	
+	iAlloc = new (c.Base() + offset) RSymbianDLHeap(c.Handle(), offset, minLength, KMaxHeapSize, KHeapGrowSize, 8, EFalse /* not single threaded! */);
+	iAlloc->iHandles = &iAlloc->iChunkHandle;
+	iAlloc->iHandleCount = 2;
+	// chunk handle now 'owned' by iAlloc
+	r = iAlloc->iLock.CreateLocal(EOwnerProcess);
+
+	if(r != KErrNone)
+		return EFalse;
+	
+	return CMemoryPool::Create();
+	}
+
+#endif
 // END OF FILE