コード例 #1
0
void DPriSamplerImpl::Reset()
    {
	/*
	 *
	 *	EKA-2 implementation of PRI trace
	 *
	 */

	LOGTEXT("PriSamplerImpl::Reset");
	iCountti = 50;	// sample threads 16 cycles before actual MEM and PRI sample time...
	this->iThreadCount = 0;
	this->iNewThreadCount = 0;
	this->iProcessing = ENothingToProcess;
	this->sampleDescriptor.Zero();


	// clear all thread tags
	NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
	DObjectCon* threads = Kern::Containers()[EThread];
	threads->Wait(); // Obtain the container mutex so the list does get changed under us

	TInt totalThreadCount = threads->Count();
	for(TInt i=0;i<totalThreadCount;i++)
	    {
		DThread* t = (DThread*)(*threads)[i];
		TAG(t) = (TAG(t) & 0xfffffffd);
	    }
	threads->Signal();
	NKern::ThreadLeaveCS();  // End of critical section
	}
コード例 #2
0
/**
 * Stop Mode routine to retrieve the process list and place it in the response buffer
 * @param aItem List item describing the list
 * @return One of the system wide error codes
 */
TInt StopModeDebug::GetProcessList(const TListItem* aItem, bool aCheckConsistent)
	{
	Kern::Printf("\nDumping the process list");

	if(aItem->iListScope != EScopeGlobal)
		{
		return KErrArgument; //No other scope makes sense for process list
		}

	//Check that the process obj con lock is ok if required
	DObjectCon* objCon = Kern::Containers()[EProcess];

	if(aCheckConsistent && objCon->Lock()->iHoldCount)
		{
		return KErrNotReady;
		}

	//Look at the buffer
	TUint8* buffer = (TUint8*)aItem->iBufferAddress;
	TUint8* bufferPos = Align4(buffer + sizeof(TListReturn));
	TUint8* bufferEnd = buffer + aItem->iBufferSize;

	TListReturn* listResp = (TListReturn*)buffer;	
	listResp->iReqNo = EProcess;
	listResp->iNumberItems = 0;
	listResp->iDataSize = 0;

	DProcess** firstProcess = (DProcess**)objCon->iObjects;

	TInt numProcesses = objCon->Count();
	for(TInt cnt = 0; cnt < numProcesses; cnt++)
		{
		//Get process and see if we want to list it
		DProcess* proc = firstProcess[cnt];
		if(proc && (proc->iId >= aItem->iStartElement) )
			{
			TUint32 sizeOfProc = 0;
			TInt err = AppendProcessToBuffer(proc, bufferPos, bufferEnd, sizeOfProc);
			if(KErrNone != err)
				{
				return err;
				}
			++(listResp->iNumberItems);
			listResp->iDataSize += sizeOfProc;
			bufferPos += sizeOfProc;
			}
		}

	return KErrNone;
	}
コード例 #3
0
// -----------------------------------------------------------------------------
// DIscDevice::InitializeLdd2LddInterface
// Function to connect to DataTransmission and Multiplexer ldds
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TInt DIscDevice::InitializeLdd2LddInterface()
    {
    C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface()" ) ) );
    
    // Find pointer to second level LDD.
    DObjectCon* lDevices = Kern::Containers()[ ELogicalDevice ];
    TKName driverName;
    ASSERT_RESET_ALWAYS( lDevices, "IscDriver", EIscLogicalDevicesNotFound );

    TInt err( KErrNone );
    //TInt driverHandle( KErrNone ); // API change in SOS9.2 WK08
	TFindHandle driverHandle;
    // Find pointer to ISC Multiplexer.
    err = lDevices->FindByName( driverHandle, KIscMultiplexerName, driverName );
    if( KErrNone != err )
        {
        C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface() ISC Multiplexer Not Found!" ) ) );
        ASSERT_RESET_ALWAYS( 0, "IscDriver" ,EIscMultiplexerNotFound );
        }
	
    iIscMultiplexerInterface = static_cast<DIscMultiplexerBase*>( lDevices->At( driverHandle ) );
    ASSERT_RESET_ALWAYS( iIscMultiplexerInterface, "IscDriver", EIscMultiplexerNotFound );

    //TInt secondDriverHandle( KErrNone );  // API change in SOS9.2 WK08
	TFindHandle secondDriverHandle;
    // Find pointer to Data Transmission Plugin.
    err = lDevices->FindByName( secondDriverHandle, KIscDataTransmissionDriverName, driverName );
    if( KErrNone != err )
        {
        C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface() Data Transmission Plug-In Not Found!" ) ) );
        ASSERT_RESET_ALWAYS( 0, "IscDriver", EIscDataTransmissionDriverNotFound );
        }

    iIscDataTransmissionInterface = static_cast<DIscDataTransmissionBase*>( lDevices->At( secondDriverHandle ) );
    ASSERT_RESET_ALWAYS( iIscDataTransmissionInterface, "IscDriver", EIscDataTransmissionDriverNotFound );
    
    iIscDataTransmissionInterface->Connect( this );
    iIscMultiplexerInterface->Connect( this );

    C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface - return 0x%x" ), err ) );
    return err;
    
    }
コード例 #4
0
ファイル: minkda.cpp プロジェクト: kuailexs/symbiandump-os1
TInt DKdaChannel::OpenTempObject(TUint aId, TObjectType aType)
	{
	__ASSERT_DEBUG(aType == EProcess || aType == EThread, Kern::Fault(KFault, __LINE__));
	__ASSERT_DEBUG(! iTempObj, Kern::Fault(KFault, __LINE__));

	DObjectCon* pC = Kern::Containers()[aType];
	NKern::ThreadEnterCS();
	pC->Wait();
	DObject* tempObj = (aType == EProcess) ? (DObject*)Kern::ProcessFromId(aId) : (DObject*)Kern::ThreadFromId(aId);
	NKern::LockSystem();
	iTempObj = tempObj;
	TInt r = KErrNotFound;
	if (iTempObj)
		r = iTempObj->Open();

	NKern::UnlockSystem();
	pC->Signal();
	NKern::ThreadLeaveCS();
	return r;
	}
コード例 #5
0
TInt DPriSamplerImpl::SampleImpl()
    {
	/*
	 *
	 *	EKA-2 implementation of PRI trace
	 *
	 */
	if(this->iProcessing == ENothingToProcess)
	    {
	    if((iCountti % iPriSamplingPeriod) != 0 ) return 0;
	    
        LOGTEXT("Processing threads...");

        DObjectCon* threads = Kern::Containers()[EThread];
        NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
        threads->Wait();

        // PRI trace variables
        this->iThreadCount = 0; 
        this->iNewThreadCount = 0;
        TInt totalThreadCount = threads->Count();

        for(TInt i=0;i<totalThreadCount;i++)
            {
            //DThread* t = (DThread*)(threads)[i];
            DObject* pO=(*threads)[i];
            DThread* t = (DThread*)pO;
            
            LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t));

            if( (TAG(t) & PROFILER_THREAD_MARK) == 0)
                {
                LOGSTRING2("Marking thread %d",i);
                // this thread's chunk has not been reported yet
                this->threadNamesToReport[iNewThreadCount] = t;
                iNewThreadCount++;
                // tag the thread
                TAG(t) |= PROFILER_THREAD_MARK;
                LOGSTRING2("New Thread %d",i);
                }
            else
                {
                LOGSTRING3("Thread %d marked already - 0x%x",i,TAG(t));
                }

            // the thread has been tagged, add heap chunks to the list
            this->threadsToSample[this->iThreadCount] = t;
            this->iThreadCount++;
            LOGSTRING2("Added thread %d to threads to sample",i);
            }

        threads->Signal();
        NKern::ThreadLeaveCS();  // End of critical section

        if(this->iThreadCount > 0 || this->iNewThreadCount > 0)
            {
            this->iProcessing = EStartingToProcess;
            
            // process the first sample
            TInt length = this->ProcessChunks();
            
            if(length == 0)
                {
                this->iProcessing = ENothingToProcess;
                }
            return length;
            }
        else
            {
            // there were no threads, should not take place
            LOGTEXT("PriSamplerImpl::SampleImpl - Error, no threads"); 
            return 0;
            }
	    }
	else
	    {
		TInt length = this->ProcessChunks();
		if(length == 0) 
		    {
			this->iProcessing = ENothingToProcess;
		    }
		return length;
	    }
    }
コード例 #6
0
/**
 * Generic method that looks at all kernel objects of aObjectType
 * @param aObjectType
 * @param aDumpScope - if you wish to dump for the the current process, current thread or entire system
 * @param aDataToDump - data you wish to dump
 * @param aSizeDumped - records how much was dumped
 * @return
 */
TInt SCMonitor::LogObjectContainers(TObjectType aObjectType, SCMDataSave::TDumpScope aDumpScope, const SCMDataSave::TDataToDump& aDataToDump, TUint& aSizeDumped) const
	{
	aSizeDumped = 0;
	
	if(aObjectType >= ENumObjectTypes)
		{
		return KErrArgument;
		}
	
	//Get the object container for the given object type
	DObjectCon* objectContainer = Kern::Containers()[aObjectType];
	if(objectContainer == NULL)
		{		
		CLTRACE("tFailed to get object container");
		return KErrNotFound;
		}
	
	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
	if(objectContainer->iMutex->iHoldCount)
		{
		CLTRACE("\tObject Container is in an inconsistant state");
		return KErrCorrupt;
		}
	
	TInt numObjects = objectContainer->Count();
	TInt err = KErrNone;	
	
	for(TInt cnt = 0; cnt< numObjects; cnt ++)
		{	
		DObject* object = (*objectContainer)[cnt];
		
		//Are we interested in the object? scope only relevant for thread and process objects, for others, the scope is implicit
		if(aObjectType == EThread)			
			{
			switch(aDumpScope)
				{
				case SCMDataSave::EThreadSpecific :
					{
					//if we are interested in the current thread and this is not it, continue
					if(((DThread*)object) != &Kern::CurrentThread())
						continue;
					break;
					}
				case SCMDataSave::EProcessSpecific :
					{
					//if we are interested in the current proc and this is not it, continue
					if(((DThread*)object)->iOwningProcess != &Kern::CurrentProcess())
						continue;					
					break;
					}
				case SCMDataSave::ESystemWide :
				default: 
					break;
				}
			}
		else if(aObjectType == EProcess)
			{
			switch(aDumpScope)
				{
				case SCMDataSave::EProcessSpecific :
					{
					if((DProcess*)object != &Kern::CurrentProcess())
						continue;
					break;
					}
				case SCMDataSave::EThreadSpecific :  //thread specific process doesnt make sense
					return KErrArgument;				
				case SCMDataSave::ESystemWide :
				default:
					break;
				}
			}
		
		//Now we look at the data we have been asked to dump
		if(aDataToDump.iMetaData)
			{
			TUint dumped = 0;
			err = HelpDumpMetaData(object, aObjectType, dumped);
			if(KErrNone != err)
				{
				CLTRACE1("Failed to meta data: [%d]", err);
				return err;
				}
			aSizeDumped += dumped;
			}
		
		if(aDataToDump.iCodeSegs)
			{
			if(aObjectType != EProcess)
				{
				return KErrArgument;
				}
			
			TUint dumped = 0;
			err = iDataSave->LogCodeSegments((DProcess*)object, dumped);
			if(KErrNone != err)
				{
				CLTRACE1("Failed to log code segments: [%d]", err);
				return err;
				}
			aSizeDumped += dumped;
			}
		
		if(aDataToDump.iStk != SCMDataSave::EStackTypeNone)
			{
			TUint dumped = 0;
			err = HelpDumpStacks(object, aObjectType, dumped, aDataToDump.iStk);
			if(KErrNone != err)
				{
				CLTRACE1("Failed to log stacks: [%d]", err);
				return err;
				}
			aSizeDumped += dumped;
			}
		
		if(aDataToDump.iReg != SCMDataSave::ERegSetNone)
			{			
			if(aObjectType != EThread)
				{
				return KErrArgument;
				}
			TUint dumped = 0;
			err = iDataSave->LogRegisters((DThread*)object, aDataToDump.iReg, dumped);	
			if(KErrNone != err && KErrNotSupported !=err)  //we expect to send down a KErrNotSupported when we ask for Full CPU set for the non crashed thread - thats fine
				{
				CLTRACE1("Failed to log registers: [%d]", err);
				return err;
				}
			aSizeDumped += dumped;
			}
		}
	
	return KErrNone;
	}
コード例 #7
0
void DMemSamplerImpl::Reset()
    {
	Kern::Printf("MemSamplerImpl::Reset");
	iCount = 0; // sample threads 1 cycle after actual MEM sample time...
    this->iTimeToSample = false;
    this->iChunkCount = 0;
	this->iNewChunkCount = 0;
	
	this->iTotalMemoryOk = false;
	this->iTotalMemoryNameOk = false;

	this->iChunksProcessing = ENothingToProcess;
    this->iThreadsProcessing = ENothingToProcess;
#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
    this->iLibrariesProcessing = ENothingToProcess;
    this->iSampleType = ESampleThreads;
#else
    this->iSampleThreads = true;
#endif
    
	this->sampleDescriptor.Zero();
	
	// clear all chunk tags
    NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
	DObjectCon* chunks = Kern::Containers()[EChunk];
    chunks->Wait(); // Obtain the container mutex so the list does get changed under us

	TInt totalChunkCount = chunks->Count();
	for(TInt i=0;i<totalChunkCount;i++)
	    {
		DChunk* c = (DChunk*)(*chunks)[i];
		TAG(c) = 0;
	    }
	chunks->Signal();  // Release the container mutex

	Kern::Printf("MemSamplerImpl::Reset");
	this->iThreadCount = 0;
	this->iNewThreadCount = 0;
	this->sampleDescriptor.Zero();

	// clear all chunk tags
	DObjectCon* threads = Kern::Containers()[EThread];
    threads->Wait(); // Obtain the container mutex so the list does get changed under us

	TInt totalThreadCount = threads->Count();
	for(TInt i=0;i<totalThreadCount;i++)
	    {
		DThread* t = (DThread*)(*threads)[i];
		TAG(t) = (TAG(t) & 0xfffffffe);
	    }
	threads->Signal();  // Release the container mutex
	
#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
	this->iLibraryCount = 0;
	this->iNewLibraryCount = 0;
	this->sampleDescriptor.Zero();

	// clear all library tags
	DObjectCon* libs = Kern::Containers()[ELibrary];
	libs->Wait(); // Obtain the container mutex so the list does get changed under us

	TInt totalLibraryCount = libs->Count();
	for(TInt i=0; i<totalLibraryCount; i++)
	    {
        DLibrary* l = (DLibrary*)(*libs)[i];
        TAG(l) = (TAG(l) & 0xefffffff);
	    }
	libs->Signal();  // Release the container mutex
#endif

    NKern::ThreadLeaveCS();  // End of critical section
    }
コード例 #8
0
TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams )
    {
	TMemSpyDriverInternalChunkInfoParams params;
    TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
    if  ( r != KErrNone )
        {
    	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r));
        return r;
        }

    TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle));
		
	DObjectCon* container = Kern::Containers()[EChunk];
	NKern::ThreadEnterCS();

    container->Wait();
    const TInt count = container->Count();

    DChunk* foundChunk = NULL;
    
    for(TInt i=0; i<count; i++)
        {
        DChunk* chunk = (DChunk*) (*container)[i];
        if  ( chunk == params.iHandle )
            {
            foundChunk = chunk;
            TRACE( PrintChunkInfo( *chunk ) );
			r = foundChunk->Open();
            break;
            }
        }

    container->Signal();

    if  ( foundChunk == NULL )
        {
    	Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk");
		NKern::ThreadLeaveCS();
        return KErrNotFound;
        }
	if (r)
		{
		Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - %d - Failed to open chunk", r);
		NKern::ThreadLeaveCS();
		return r;
		}

    // Prepare return data
    DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk();
    //
    params.iBaseAddress = chunkAdaption.GetBase( *foundChunk );
    params.iSize = chunkAdaption.GetSize( *foundChunk );
    params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk );
    foundChunk->FullName( params.iName );

    // Mirror the process memory tracker
    DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk );
    if  ( owner )
        {
        params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
        }
    else
        {
        owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) );
        if  ( owner )
            {
            params.iOwnerId = OSAdaption().DProcess().GetId( *owner );
            }
        else
            {
            params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk );
            }
        }

    // Get type & attribs
    params.iType = IdentifyChunkType( *foundChunk );
    params.iAttributes = chunkAdaption.GetAttributes( *foundChunk );

	// Finished with foundChunk
	foundChunk->Close(NULL);
	NKern::ThreadLeaveCS();
    
    // Write back to client
    r = Kern::ThreadRawWrite( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkInfoParams) );
	if  ( r == KErrBadDescriptor )
        {
        MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
        }

	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r ));
    return r;
    }
コード例 #9
0
TInt DMemSpyDriverLogChanChunks::GetChunkHandles( TMemSpyDriverInternalChunkHandleParams* aParams )
    {
	TMemSpyDriverInternalChunkHandleParams params;
    TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &params, sizeof(TMemSpyDriverInternalChunkHandleParams) );
    if  ( r != KErrNone )
        {
    	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - params read error: %d", r));
        return r;
        }

	const TInt maxCount = params.iMaxCount;
	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - START - id: %d,  maxCount: %d, type: %d", params.iId, maxCount, params.iType));
    
    DMemSpyDriverOSAdaptionDThread& threadAdaption = OSAdaption().DThread();
    DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess();


    // This variable holds the number of handles that we have already
    // written to the client-side.
    TInt currentWriteIndex = 0;
	
    if  ( params.iType == EMemSpyDriverPrivateObjectTypeProcess || params.iType == EMemSpyDriverPrivateObjectTypeThread )
        {
        if  ( params.iType == EMemSpyDriverPrivateObjectTypeThread )
    	    {
	        r = OpenTempObject( params.iId, EThread );
            if  ( r == KErrNone )
                {
                // Open the owning process instead, so that we can see which chunks are mapped
                // into the thread.
                DThread* thread = (DThread*) TempObject();
                DProcess* process = threadAdaption.GetOwningProcess( *thread );
                if  ( process )
                    {
                    const TUint parentProcessId = processAdaption.GetId( *process );
                    CloseTempObject();
                    r = OpenTempObject( parentProcessId, EProcess );
                    }
                else
                    {
                    CloseTempObject();
                    r = KErrNotFound;
                    }
                }
       	    }
        else
            {
	        r = OpenTempObject( params.iId, EProcess );
            }

        // Handle error opening correct process
        if (r != KErrNone)
    	    {
    	    Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - parent process not found");
    	    return r;
    	    }
   
        DProcess* process = (DProcess*) TempObject();
	    NKern::ThreadEnterCS();

	    // Iterate through each handle in the process
	    MemSpyObjectIx* processHandles = processAdaption.GetHandles( *process );
		MemSpyObjectIx_HandleLookupLock();
        const TInt processHandleCount = processHandles->Count();
		MemSpyObjectIx_HandleLookupUnlock();

	    for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ )
    	    {
    	    // Get a handle from the process container...
            MemSpyObjectIx_HandleLookupLock();
			if (processHandleIndex >= processHandles->Count()) break; // Count may have changed in the meantime
    	    DObject* object = (*processHandles)[ processHandleIndex ];
			if (object && object->Open() != KErrNone) object = NULL;
			MemSpyObjectIx_HandleLookupUnlock();
            
            if  ( object )
                {
                const TObjectType objectType = processAdaption.GetObjectType( *object );
                if ( objectType == EChunk )
                    {
                    DChunk* chunk = (DChunk*) object;
                    TAny* handle = (TAny*) chunk;
                    r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) );
                    if  ( r == KErrNone )
                        {
                        ++currentWriteIndex;
                        }
                    }
				object->Close(NULL);
                }
    	    }

        // If we were asked for process-related chunks, also check the chunk container
        // for entries which we don't have handles to, but do refer to our process
        // Need a listing of all chunks in the system. Let client filter duplicates.
        DObjectCon* container = Kern::Containers()[ EChunk ];
        container->Wait();
        //
        const TInt count = container->Count();
        for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
            {
            DChunk* chunk= (DChunk*) (*container)[ i ];
            //
            const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() );
            if  ( isRelated )
                {
                r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
                if  ( r == KErrNone )
                    {
                    ++currentWriteIndex;
                    }
                }
            }
        //
        container->Signal();
        NKern::ThreadLeaveCS();

        CloseTempObject();
        }
    else
        {
        // Need a listing of all chunks in the system. Let client filter duplicates.
        DObjectCon* container = Kern::Containers()[ EChunk ];
        NKern::ThreadEnterCS();
        container->Wait();
        //
        const TInt count = container->Count();
        for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
            {
            DChunk* chunk= (DChunk*) (*container)[ i ];
            //
            r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
            if  (r == KErrNone)
                {
                ++currentWriteIndex;
                }
            }
        //
        container->Signal();
        NKern::ThreadLeaveCS();
        }
	
	if  ( r == KErrBadDescriptor )
        {
        MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
        }
    else
        {
        const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, &currentWriteIndex, sizeof(TInt) );
        if  ( r == KErrNone )
            {
            r = finalWrite;
            }
        }

	TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r));
	return r;
    }