perfsrv/memspy/Driver/Shared/heaputils.cpp
changeset 55 f2950aff7424
parent 48 516af714ebb4
child 62 1c2bb2fc7c87
--- a/perfsrv/memspy/Driver/Shared/heaputils.cpp	Fri Sep 17 08:38:31 2010 +0300
+++ b/perfsrv/memspy/Driver/Shared/heaputils.cpp	Mon Oct 04 02:45:59 2010 +0300
@@ -23,7 +23,7 @@
 
 #include <kern_priv.h>
 #define MEM Kern
-__ASSERT_COMPILE(sizeof(LtkUtils::RKernelSideAllocatorHelper) == 10*4);
+__ASSERT_COMPILE(sizeof(LtkUtils::RUserAllocatorHelper) == 10*4);
 #define KERN_ENTER_CS() NKern::ThreadEnterCS()
 #define KERN_LEAVE_CS() NKern::ThreadLeaveCS()
 #define LOG(args...)
@@ -104,6 +104,23 @@
 
 #ifdef __KERNEL_MODE__
 
+TLinAddr LtkUtils::RAllocatorHelper::GetKernelAllocator(DChunk* aKernelChunk) 
+    {    
+    TLinAddr allocatorAddress;
+#ifdef __WINS__
+    allocatorAddress = (TLinAddr)aKernelChunk->Base();
+#else
+    // Copied from P::KernelInfo
+    const TRomHeader& romHdr=Epoc::RomHeader();
+    const TRomEntry* primaryEntry=(const TRomEntry*)Kern::SuperPage().iPrimaryEntry;
+    const TRomImageHeader* primaryImageHeader=(const TRomImageHeader*)primaryEntry->iAddressLin;
+    TLinAddr stack = romHdr.iKernDataAddress + Kern::RoundToPageSize(romHdr.iTotalSvDataSize);
+    TLinAddr heap = stack + Kern::RoundToPageSize(primaryImageHeader->iStackSize);
+    allocatorAddress = heap;
+#endif
+    return allocatorAddress;
+    }
+
 TInt RAllocatorHelper::OpenKernelHeap()
 	{
 	_LIT(KName, "SvHeap");
@@ -124,18 +141,13 @@
 		}
 	iChunk = foundChunk;
     chunkContainer->Signal();
-#ifdef __WINS__
-	TInt err = OpenChunkHeap((TLinAddr)foundChunk->Base(), 0); // It looks like DChunk::iBase/DChunk::iFixedBase should both be ok for the kernel chunk
-#else
-	// Copied from P::KernelInfo
-	const TRomHeader& romHdr=Epoc::RomHeader();
-	const TRomEntry* primaryEntry=(const TRomEntry*)Kern::SuperPage().iPrimaryEntry;
-	const TRomImageHeader* primaryImageHeader=(const TRomImageHeader*)primaryEntry->iAddressLin;
-	TLinAddr stack = romHdr.iKernDataAddress + Kern::RoundToPageSize(romHdr.iTotalSvDataSize);
-	TLinAddr heap = stack + Kern::RoundToPageSize(primaryImageHeader->iStackSize);
-	TInt err = OpenChunkHeap(heap, 0); // aChunkMaxSize is only used for trying the middle of the chunk for hybrid allocatorness, and the kernel heap doesn't use that (thankfully). So we can safely pass in zero.
+
+    iAllocatorAddress = GetKernelAllocator(foundChunk);
 
-#endif
+    // It looks like DChunk::iBase/DChunk::iFixedBase should both be ok for the kernel chunk
+	// aChunkMaxSize is only used for trying the middle of the chunk for hybrid allocatorness, and the kernel heap doesn't use that (thankfully). So we can safely pass in zero.
+	TInt err = OpenChunkHeap((TLinAddr)foundChunk->Base(), 0); 
+
 	if (!err) err = FinishConstruction();
 	NKern::ThreadLeaveCS();
 	return err;
@@ -288,11 +300,11 @@
 
 #ifdef __KERNEL_MODE__
 
-LtkUtils::RKernelSideAllocatorHelper::RKernelSideAllocatorHelper()
+LtkUtils::RUserAllocatorHelper::RUserAllocatorHelper()
 	: iThread(NULL)
 	{}
 
-void LtkUtils::RKernelSideAllocatorHelper::Close()
+void LtkUtils::RUserAllocatorHelper::Close()
 	{
 	NKern::ThreadEnterCS();
 	if (iThread)
@@ -304,27 +316,27 @@
 	NKern::ThreadLeaveCS();
 	}
 
-TInt LtkUtils::RKernelSideAllocatorHelper::ReadData(TLinAddr aLocation, TAny* aResult, TInt aSize) const
+TInt LtkUtils::RUserAllocatorHelper::ReadData(TLinAddr aLocation, TAny* aResult, TInt aSize) const
 	{
 	return Kern::ThreadRawRead(iThread, (const TAny*)aLocation, aResult, aSize);
 	}
 
-TInt LtkUtils::RKernelSideAllocatorHelper::WriteData(TLinAddr aLocation, const TAny* aData, TInt aSize)
+TInt LtkUtils::RUserAllocatorHelper::WriteData(TLinAddr aLocation, const TAny* aData, TInt aSize)
 	{
 	return Kern::ThreadRawWrite(iThread, (TAny*)aLocation, aData, aSize);
 	}
 
-TInt LtkUtils::RKernelSideAllocatorHelper::TryLock()
+TInt LtkUtils::RUserAllocatorHelper::TryLock()
 	{
 	return KErrNotSupported;
 	}
 
-void LtkUtils::RKernelSideAllocatorHelper::TryUnlock()
+void LtkUtils::RUserAllocatorHelper::TryUnlock()
 	{
 	// Not supported
 	}
 
-TInt LtkUtils::RKernelSideAllocatorHelper::OpenUserHeap(TUint aThreadId, TLinAddr aAllocatorAddress, TBool aEuserIsUdeb)
+TInt LtkUtils::RUserAllocatorHelper::OpenUserHeap(TUint aThreadId, TLinAddr aAllocatorAddress, TBool aEuserIsUdeb)
 	{
 	NKern::ThreadEnterCS();
 	DObjectCon* threads = Kern::Containers()[EThread];
@@ -344,11 +356,77 @@
 	return err;
 	}
 
+LtkUtils::RKernelCopyAllocatorHelper::RKernelCopyAllocatorHelper()
+    : iCopiedChunk(NULL), iOffset(0)
+    {}
+
+TInt LtkUtils::RKernelCopyAllocatorHelper::OpenCopiedHeap(DChunk* aOriginalChunk, DChunk* aCopiedChunk, TInt aOffset)
+    {
+    TInt err = aCopiedChunk->Open();
+    if (!err)
+        {
+        iCopiedChunk = aCopiedChunk;
+        iOffset = aOffset;
+
+        // We need to set iAllocatorAddress to point to the allocator in the original chunk and not the copy
+        // because all the internal pointers will be relative to that. Instead we use iOffset in the Read / Write Data 
+        // calls
+        iAllocatorAddress = GetKernelAllocator(aOriginalChunk);
+        
+        // It looks like DChunk::iBase/DChunk::iFixedBase should both be ok for the kernel chunk
+        // aChunkMaxSize is only used for trying the middle of the chunk for hybrid allocatorness, and the kernel heap doesn't use that (thankfully). So we can safely pass in zero.
+        err = OpenChunkHeap((TLinAddr)aCopiedChunk->Base(), 0);
+        }
+    
+    return err;
+    }
+
+DChunk* LtkUtils::RKernelCopyAllocatorHelper::OpenUnderlyingChunk()
+    {
+    // We should never get here
+    __NK_ASSERT_ALWAYS(EFalse);
+    return NULL;
+    }
+
+void LtkUtils::RKernelCopyAllocatorHelper::Close()
+    {
+    if (iCopiedChunk)
+        {
+        NKern::ThreadEnterCS();
+        iCopiedChunk->Close(NULL);
+        iCopiedChunk = NULL;
+        NKern::ThreadLeaveCS();
+        }
+    iOffset = 0;
+    RAllocatorHelper::Close();
+    }
+
+TInt LtkUtils::RKernelCopyAllocatorHelper::ReadData(TLinAddr aLocation, TAny* aResult, TInt aSize) const
+    {
+    memcpy(aResult, (const TAny*)(aLocation+iOffset), aSize);
+    return KErrNone;
+    }
+
+TInt LtkUtils::RKernelCopyAllocatorHelper::WriteData(TLinAddr aLocation, const TAny* aData, TInt aSize)
+    {
+    memcpy((TAny*)(aLocation+iOffset), aData, aSize);
+    return KErrNone;
+    }
+
+TInt LtkUtils::RKernelCopyAllocatorHelper::TryLock()
+    {
+    return KErrNotSupported;
+    }
+
+void LtkUtils::RKernelCopyAllocatorHelper::TryUnlock()
+    {
+    // Not supported
+    }
+
 #endif // __KERNEL_MODE__
 
 TInt RAllocatorHelper::OpenChunkHeap(TLinAddr aChunkBase, TInt aChunkMaxSize)
 	{
-	iAllocatorAddress = aChunkBase;
 #ifdef __KERNEL_MODE__
 	// Must be in CS
 	// Assumes that this only ever gets called for the kernel heap. Otherwise goes through RKernelSideAllocatorHelper::OpenUserHeap.
@@ -1602,7 +1680,7 @@
 	return iChunk;
 	}
 
-DChunk* LtkUtils::RKernelSideAllocatorHelper::OpenUnderlyingChunk()
+DChunk* LtkUtils::RUserAllocatorHelper::OpenUnderlyingChunk()
 	{
 	if (iAllocatorType != EUrelOldRHeap && iAllocatorType != EUdebOldRHeap && iAllocatorType != EUrelHybridHeap && iAllocatorType != EUdebHybridHeap) return NULL;
 	// Note RKernelSideAllocatorHelper doesn't use or access RAllocatorHelper::iChunk, because we figure out the chunk handle in a different way.