perfsrv/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp
changeset 55 f2950aff7424
parent 48 516af714ebb4
equal deleted inserted replaced
48:516af714ebb4 55:f2950aff7424
    32 #include "MemSpyDriverDevice.h"
    32 #include "MemSpyDriverDevice.h"
    33 #include "MemSpyDriverOSAdaption.h"
    33 #include "MemSpyDriverOSAdaption.h"
    34 
    34 
    35 // Constants
    35 // Constants
    36 const TInt KMemSpyDriverLogChanHeapBaseXferBufferSize = 1024 * 16;
    36 const TInt KMemSpyDriverLogChanHeapBaseXferBufferSize = 1024 * 16;
    37 
       
    38 
       
    39 
    37 
    40 
    38 
    41 DMemSpyDriverLogChanHeapBase::DMemSpyDriverLogChanHeapBase( DMemSpyDriverDevice& aDevice, DThread& aThread )
    39 DMemSpyDriverLogChanHeapBase::DMemSpyDriverLogChanHeapBase( DMemSpyDriverDevice& aDevice, DThread& aThread )
    42 :	DMemSpyDriverLogChanBase( aDevice, aThread )
    40 :	DMemSpyDriverLogChanBase( aDevice, aThread )
    43     {
    41     {
   213     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - allocator address:              0x%08x", rHeapMetaData.iAllocatorAddress ) );
   211     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - allocator address:              0x%08x", rHeapMetaData.iAllocatorAddress ) );
   214     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - min heap size:                  %d", rHeapMetaData.iMinHeapSize ) );
   212     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - min heap size:                  %d", rHeapMetaData.iMinHeapSize ) );
   215     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - max heap size:                  %d", rHeapMetaData.iMaxHeapSize ) );
   213     TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - max heap size:                  %d", rHeapMetaData.iMaxHeapSize ) );
   216     }
   214     }
   217 
   215 
   218 TInt DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel(RMemSpyDriverRHeapBase& aHeap, TMemSpyHeapInfo* aHeapInfo, TDes8* aTransferBuffer )
   216 // TODO remove this? how is it actually being used?
   219     {
       
   220     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel() - START - aTransferBuffer: 0x%08x", aTransferBuffer ) );
       
   221 
       
   222     TInt r = KErrNone;
       
   223     NKern::ThreadEnterCS();
       
   224 
       
   225     // This object holds all of the info we will accumulate for the client.
       
   226     TMemSpyHeapInfo masterHeapInfo;
       
   227     masterHeapInfo.SetType(aHeap.GetTypeFromHelper());
       
   228     masterHeapInfo.SetTid( 2 );
       
   229     masterHeapInfo.SetPid( 1 );
       
   230 
       
   231     // This is the RHeap-specific object that contains all RHeap info
       
   232     TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap();
       
   233 
       
   234 
       
   235     // When walking the kernel heap we must keep track of the free cells
       
   236     // without allocating any more memory (on the kernel heap...)
       
   237     //
       
   238     // Therefore, we start a stream immediately, which is actually already
       
   239     // pre-allocated.
       
   240     //
       
   241     // Start stream and pad with zero count, which we'll repopulate later on
       
   242     // once we know the final score.
       
   243     RMemSpyMemStreamWriter stream;
       
   244     TInt32* pCount = NULL;
       
   245 
       
   246     // We must walk the client's heap in order to build statistics
       
   247     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - calling heap walker constructor..."));
       
   248     RMemSpyDriverHeapWalker heapWalker(aHeap);
       
   249     if  ( aTransferBuffer )
       
   250         {
       
   251         // This will allow us to identify that we're writing directly to the stream
       
   252         stream = OpenXferStream();
       
   253         iStackStream = &stream;
       
   254 
       
   255         // Writer marker value which we'll update after the traversal completes
       
   256         pCount = stream.WriteInt32( 0 );
       
   257 
       
   258         // Receive cell info as we walk the heap...
       
   259         heapWalker.SetObserver( this );
       
   260         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - collecting free cells - iStackStream: 0x%08x, isOpen: %d, pCount: 0x%08x", iStackStream, stream.IsOpen(), pCount ));
       
   261         }
       
   262     else
       
   263         {
       
   264         iStackStream = NULL;
       
   265         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - not collecting free cells"));
       
   266         }
       
   267 
       
   268     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - starting traversal..." ));
       
   269 
       
   270 #if defined( TRACE_TYPE_KERNELHEAP )
       
   271     heapWalker.SetPrintDebug();
       
   272 #endif
       
   273     r = heapWalker.Traverse();
       
   274 
       
   275     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - finished traversal - err: %d, iStackStream: 0x%08x, pCount: 0x%08x, isOpen: %d", 
       
   276                             r, iStackStream, pCount, ( iStackStream == NULL ? 0 : iStackStream->IsOpen() ) ));
       
   277 
       
   278     // Write free cells if requested
       
   279     if  ( r == KErrNone && iStackStream && iStackStream->IsOpen() && pCount )
       
   280         {
       
   281         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - final free cell count: %d", iFreeCellCount ));
       
   282         *pCount = iFreeCellCount;
       
   283         r = stream.WriteAndClose( aTransferBuffer );
       
   284         iStackStream = NULL;
       
   285         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - stream commit result: %d", r ));
       
   286         }
       
   287 
       
   288     TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics();
       
   289     heapWalker.CopyStatsTo( rHeapStats );
       
   290 
       
   291     // Get remaining meta data that isn't stored elsewhere
       
   292     TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData();
       
   293 	TFullName chunkName;
       
   294 	aHeap.Chunk().FullName(chunkName);
       
   295     rHeapMetaData.SetChunkName(chunkName);
       
   296     rHeapMetaData.SetChunkSize( (TUint) aHeap.Chunk().Size() );
       
   297     rHeapMetaData.SetChunkHandle( &aHeap.Chunk() );
       
   298     rHeapMetaData.SetChunkBaseAddress( OSAdaption().DChunk().GetBase(aHeap.Chunk()) );
       
   299     rHeapMetaData.SetDebugAllocator(aHeap.Helper()->AllocatorIsUdeb());
       
   300     rHeapMetaData.SetUserThread( EFalse );
       
   301     rHeapMetaData.SetSharedHeap( ETrue );
       
   302 	rHeapMetaData.iHeapSize = aHeap.Helper()->CommittedSize();
       
   303 	rHeapMetaData.iAllocatorAddress = (TAny*)aHeap.Helper()->AllocatorAddress();
       
   304 	rHeapMetaData.iMinHeapSize = aHeap.Helper()->MinCommittedSize();
       
   305 	rHeapMetaData.iMaxHeapSize = aHeap.Helper()->MaxCommittedSize();
       
   306 
       
   307     PrintHeapInfo( masterHeapInfo );
       
   308 
       
   309     // Update info ready for writing back to the user-side
       
   310     if  ( r == KErrNone )
       
   311         {
       
   312         // Write results back to user-side
       
   313         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - writing to user-side..."));
       
   314         r = Kern::ThreadRawWrite( &ClientThread(), aHeapInfo, &masterHeapInfo, sizeof( TMemSpyHeapInfo ) );
       
   315         }
       
   316 
       
   317     NKern::ThreadLeaveCS();
       
   318 
       
   319 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel() - END - ret: %d", r) );
       
   320     return r;
       
   321     }
       
   322 
       
   323 
       
   324 
       
   325 
       
   326 
       
   327 
       
   328 
       
   329 
       
   330 
       
   331 
       
   332     
       
   333 
       
   334 
       
   335 
       
   336 
       
   337 
       
   338 
       
   339 TBool DMemSpyDriverLogChanHeapBase::HandleHeapCell(TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/)
   217 TBool DMemSpyDriverLogChanHeapBase::HandleHeapCell(TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/)
   340     {
   218     {
   341     TInt error = KErrNone;
   219     TInt error = KErrNone;
   342     //
   220     //
   343     if  (aCellType & EMemSpyDriverFreeCellMask)
   221     if  (aCellType & EMemSpyDriverFreeCellMask)
   368 void DMemSpyDriverLogChanHeapBase::HandleHeapWalkInit()
   246 void DMemSpyDriverLogChanHeapBase::HandleHeapWalkInit()
   369 	{
   247 	{
   370 	iFreeCellCount = 0;
   248 	iFreeCellCount = 0;
   371 	}
   249 	}
   372 
   250 
   373 TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RHeapK*& aHeap, DChunk*& aChunk, TDes8* aClientHeapChunkName )
   251 
   374     {
   252 
   375     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap() - START") );
   253 
   376 
       
   377     // This is what we're searching for...
       
   378     RHeapK* kernelHeap = NULL;
       
   379     DChunk* kernelHeapChunk = NULL;
       
   380 
       
   381     // Find the SvHeap chunk....
       
   382     _LIT( KKernelServerHeapChunkName, "SvHeap" );
       
   383  	NKern::ThreadEnterCS();
       
   384    
       
   385     DObjectCon* chunkContainer = Kern::Containers()[EChunk];
       
   386     chunkContainer->Wait();
       
   387     NKern::LockSystem();
       
   388     const TInt chunkCount = chunkContainer->Count();
       
   389 
       
   390     for(TInt i=0; i<chunkCount; i++)
       
   391         {
       
   392         DChunk* chunk = (DChunk*) (*chunkContainer)[ i ];
       
   393         //
       
   394         if  ( chunk->NameBuf() )
       
   395             {
       
   396             const TInt findResult = chunk->NameBuf()->Find( KKernelServerHeapChunkName );
       
   397     	    TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - checking chunk: %O against %S => %d", chunk, &KKernelServerHeapChunkName, findResult ) );
       
   398             if  ( findResult != KErrNotFound )
       
   399                 {
       
   400                 // Found it.
       
   401                 kernelHeapChunk = chunk;
       
   402                 TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - found chunk with base: 0x%08x", chunk->iBase ) );
       
   403                 break;
       
   404                 }
       
   405             }
       
   406         }
       
   407 
       
   408     NKern::UnlockSystem();
       
   409     chunkContainer->Signal();
       
   410 
       
   411     TInt r = KErrNotFound;
       
   412     if  ( kernelHeapChunk != NULL )
       
   413         {
       
   414 #ifndef __WINS__
       
   415         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeapChunk: 0x%08x", kernelHeapChunk ) );
       
   416 
       
   417         const TRomHeader& romHdr = Epoc::RomHeader();
       
   418 	    const TRomEntry* primaryEntry = (const TRomEntry*) Kern::SuperPage().iPrimaryEntry;
       
   419         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - primaryEntry: 0x%08x, primaryEntry->iAddressLin: 0x%08x", primaryEntry, primaryEntry->iAddressLin ) );
       
   420 	    const TRomImageHeader* primaryImageHeader = (const TRomImageHeader*) primaryEntry->iAddressLin;
       
   421         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - primaryEntry: 0x%08x", primaryImageHeader ) );
       
   422 
       
   423         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iCodeSize:            0x%08x", primaryImageHeader->iCodeSize ) );
       
   424         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iTextSize:            0x%08x", primaryImageHeader->iTextSize ) );
       
   425         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iDataSize:            0x%08x", primaryImageHeader->iDataSize ) );
       
   426         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iBssSize:             0x%08x", primaryImageHeader->iBssSize ) );
       
   427         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iHeapSizeMin:         0x%08x", primaryImageHeader->iHeapSizeMin ) );
       
   428         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iHeapSizeMax:         0x%08x", primaryImageHeader->iHeapSizeMax ) );
       
   429         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iStackSize:           0x%08x", primaryImageHeader->iStackSize ) );
       
   430 
       
   431         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - romHdr.iKernDataAddress: 0x%08x", romHdr.iKernDataAddress ) );
       
   432         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - Kern::RoundToPageSize( romHdr.iTotalSvDataSize ): 0x%08x", Kern::RoundToPageSize( romHdr.iTotalSvDataSize ) ) );
       
   433         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - Kern::RoundToPageSize( kernelProcessCreateInfo.iStackSize ): 0x%08x", Kern::RoundToPageSize( primaryImageHeader->iStackSize ) ) );
       
   434 
       
   435         TAny* stack = (TAny*)( romHdr.iKernDataAddress + Kern::RoundToPageSize( romHdr.iTotalSvDataSize ));
       
   436         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - aStack: 0x%08x", stack ) );
       
   437         
       
   438         // NB: This is supposed to be Kern::RoundToPageSize( kernelProcessCreateInfo.iStackSize ) but that
       
   439         // sometimes returns very dodgy values on ARMv5 Multiple Memory Model when using MemSpy's driver
       
   440         // installed via a SIS file. No idea why. Cache problem? 
       
   441         TAny* heap = (TAny*)(TLinAddr( stack ) + Kern::RoundToPageSize( primaryImageHeader->iStackSize ));
       
   442         TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - aHeap: 0x%08x", heap ) );
       
   443 
       
   444         kernelHeap = (RHeapK*) heap;
       
   445 #else
       
   446         kernelHeap = (RHeapK*) kernelHeapChunk->Base();
       
   447 #endif
       
   448         // Finalise construction of heap 
       
   449         if  ( kernelHeap != NULL )
       
   450             {
       
   451             TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeapChunk->Base(): 0x%08x", kernelHeapChunk->Base() ) );
       
   452             aHeap = kernelHeap;
       
   453             aChunk = kernelHeapChunk;
       
   454 
       
   455             // Get the chunk name (if the caller asked for it)
       
   456             if  ( aClientHeapChunkName )
       
   457                 {
       
   458                 kernelHeapChunk->FullName( *aClientHeapChunkName );
       
   459                 }
       
   460 
       
   461             // Opened okay
       
   462             r = KErrNone;
       
   463             }
       
   464         else
       
   465             {
       
   466             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernel heap was NULL..."));
       
   467             }
       
   468         }
       
   469     else
       
   470         {
       
   471         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - couldnt find kernel chunk..."));
       
   472         r = KErrNotFound;
       
   473         }
       
   474 
       
   475  	NKern::ThreadLeaveCS();
       
   476 
       
   477 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap() - END - ret: %d", r ) );
       
   478     return r;
       
   479     }
       
   480 
       
   481 TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RMemSpyDriverRHeapKernelFromCopy& aHeap, TDes8* aClientHeapChunkName )
       
   482     {
       
   483     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - START") );
       
   484 
       
   485     RHeapK* heap = NULL;
       
   486     DChunk* chunk = NULL;
       
   487     TInt r = OpenKernelHeap( heap, chunk, aClientHeapChunkName );
       
   488 	
       
   489     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - open err: %d", r ) );
       
   490     if  ( r == KErrNone )
       
   491         {
       
   492 #ifdef __SYMBIAN_KERNEL_HYBRID_HEAP__
       
   493 		// RAllocator::Size() not exported on hybrid heap
       
   494 		const TInt heapSize = heap->DebugFunction(RAllocator::EGetSize);
       
   495 #else
       
   496         const TInt heapSize = heap->Size();
       
   497 #endif
       
   498         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - heapSize: %d, heap: 0x%08x, chunkBase: 0x%08x", heapSize, heap, chunk->Base() ) );
       
   499 
       
   500         // Make a new chunk that we can copy the kernel heap into. We cannot lock the system the entire time
       
   501         // we need to do this, therefore there is no guarantee that the chunk will be large enough to hold the
       
   502         // (current) heap data at the time we need to make the copy. We oversize the chunk by 1mb in the "hope"
       
   503         // that it will be enough... :(
       
   504         TChunkCreateInfo info;
       
   505         info.iType         = TChunkCreateInfo::ESharedKernelSingle;
       
   506         info.iMaxSize      = heapSize + ( 1024 * 1024 );
       
   507         info.iOwnsMemory   = ETrue; // Use memory from system's free pool
       
   508         info.iDestroyedDfc = NULL;
       
   509         #ifdef __EPOC32__
       
   510         info.iMapAttr      = (TInt)EMapAttrFullyBlocking; // Full caching
       
   511         #endif
       
   512 
       
   513         // Holds a copy of the client's heap chunk
       
   514         DChunk* heapCopyChunk;
       
   515         TLinAddr heapCopyChunkAddress;
       
   516         TUint32 heapCopyChunkMappingAttributes;
       
   517         r = Kern::ChunkCreate( info, heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes );
       
   518         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - creating chunk returned: %d", r));
       
   519 
       
   520         if  ( r == KErrNone )
       
   521             {
       
   522             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copy chunk base: 0x%08x, heapCopyChunkAddress: 0x%08x", heapCopyChunk->iBase, heapCopyChunkAddress));
       
   523 
       
   524             // Commit memory for entire buffer
       
   525             TUint32 physicalAddress = 0;
       
   526             r = Kern::ChunkCommitContiguous( heapCopyChunk, 0, heapSize, physicalAddress );
       
   527             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - commiting chunk returned: %d", r));
       
   528 
       
   529             if  ( r != KErrNone)
       
   530                 {
       
   531                 // On error, throw away the chunk we have created
       
   532                 Kern::ChunkClose( heapCopyChunk );
       
   533                 heapCopyChunk = NULL;
       
   534                 }
       
   535             else
       
   536                 {
       
   537                 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - heapCopyChunk->iSize: 0x%08x, heapCopyChunk->iBase: 0x%08x, heapCopyChunkAddress: 0x%08x, physicalAddress: 0x%08x", heapCopyChunk->iSize, heapCopyChunk->iBase, heapCopyChunkAddress, physicalAddress));
       
   538 
       
   539                 NKern::LockSystem();
       
   540                 const TUint32 copyLength = heapSize; // TODO Min( heap->Size(), heapSize );
       
   541 
       
   542                 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - trying to copy %d (vs orig estimate of %d) bytes from kernel allocator address: 0x%08x", copyLength, heapSize, heap));
       
   543                 memcpy( (TUint8*) heapCopyChunkAddress, heap, copyLength );
       
   544 
       
   545                 NKern::UnlockSystem();
       
   546 
       
   547                 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copied kernel heap data" ));
       
   548 
       
   549                 // Transfer ownership of the copy heap chunk to the heap object. This also calculates the delta
       
   550                 // beween the heap addresses in the client's address space and the kernel address space.
       
   551                 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - associate chunk and transfer ownership..." ));
       
   552                 aHeap.SetKernelHeap( *heap );
       
   553                 aHeap.AssociateWithKernelChunk( heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes );
       
   554                 }
       
   555             }
       
   556         else
       
   557             {
       
   558 	        TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copy chunk create error: %d", r ) );
       
   559             }
       
   560         }
       
   561 
       
   562 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - END - ret: %d", r ) );
       
   563     return r;
       
   564     }
       
   565 
       
   566 
       
   567