perfsrv/piprofiler/plugins/GeneralsPlugin/inc/IttSamplerImpl.h
author hgs
Tue, 26 Oct 2010 16:20:32 +0300
changeset 62 1c2bb2fc7c87
parent 51 98307c651589
permissions -rw-r--r--
201043

/*
* Copyright (c) 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:  
*
*/

#ifndef PROFILER_ITT_SAMPLER_H
#define PROFILER_ITT_SAMPLER_H

#include "GeneralsConfig.h"

#include <kern_priv.h>

#include <piprofiler/ProfilerGenericClassesKrn.h>
#include <piprofiler/ProfilerTraces.h>
#include "GppSamplerImpl.h"
#include "IttEventHandler.h"

// CONSTANTS
const TInt KITTSampleBufferSize = 256;

// flags
#define ITT_EVENT_HANDLER   // enable event based ITT sampling

/*
 *	
 *	ITT sampler definition
 *	
 */
class DIttEventHandler;

/*
 * User side ITT sampler
 */
class IttSamplerImpl
{
public:
	IttSamplerImpl();
	~IttSamplerImpl();

	TInt	SampleImpl(TUint32 pc,TUint32 sampleNum);
	TBool	SampleNeeded(TUint32 sampleNum);
	TInt 	CreateFirstSample();
	void	Reset();
	TInt    ProcessEvent();
	
	TInt   HandleLibs(TUint32 sampleNum);
	TInt   HandleSegs(TUint32 sampleNum);
	
	TUint8*         itt_sample;
	TInt            iIttSamplingPeriod;
	TInt            iIttSamplingPeriodDiv2;
	TBool           iTimeToSample;
#ifdef ITT_EVENT_HANDLER
    TBool           iEventReceived;
    TBool           iInitialLibsTaken;
    TBool           iInitialSegsTaken;
#endif
	
private:
    enum {
        KIttHandlingLibs=0,
        KIttHandlingCodeSegs    
    };
#ifdef ITT_EVENT_HANDLER    
    TInt            iCount;
#endif
    TInt            iCurrentLibCount;
    TInt            iLibsCount;
    TInt            iCodeSegsCount;
    TInt            currentProcCount;
    
	TUint8          sample[KITTSampleBufferSize ];
	TPtr8           sampleDescriptor;
		
	TBuf8<64>		iVersionData;
	SDblQue* 		codeSegList;
    TUint8          iInitState;
    SDblQueLink*    iLatestCodeseg;
};

/*
 * ITT sampler kernel part
 * 
 */
template <int BufferSize>
class DProfilerIttSampler : public DProfilerGenericSampler<BufferSize>
{
public:
	DProfilerIttSampler(struct TProfilerGppSamplerData* gppSamplerDataIn);
	~DProfilerIttSampler();

	void	Sample(TAny* aPtr);
	TInt	Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset);
	TInt	PostSample();
	TBool	PostSampleNeeded();

private:

#ifdef ITT_EVENT_HANDLER
    DIttEventHandler*               iEventHandler;
#endif
	IttSamplerImpl					ittSamplerImpl;
	struct TProfilerGppSamplerData*     gppSamplerData;
	TBool							sampleInProgress;
	TBool							sampleNeeded;
	TUint32                         iSyncOffset;
};

/*  
 *	ITT sampler implementation
 *	
 */ 
template <int BufferSize>
DProfilerIttSampler<BufferSize>::DProfilerIttSampler(struct TProfilerGppSamplerData* gppSamplerDataIn) :
	DProfilerGenericSampler<BufferSize>(PROFILER_ITT_SAMPLER_ID)
    {
	this->gppSamplerData = (struct TProfilerGppSamplerData*)gppSamplerDataIn;
	this->sampleInProgress = false;
	iSyncOffset = 0;
	LOGSTRING2("DProfilerIttSampler<%d>::DProfilerIttSampler",BufferSize);	
    }

/*
 *  DProfilerIttSampler::Reset()
 *  
 *  @param DProfilerSampleStream* sample stream
 *  @param TUint32 Offset 
 */
template <int BufferSize>
TInt DProfilerIttSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset)
    {
    iSyncOffset = aSyncOffset;
    // check if reset called in stop (by driver)
    if(iSyncOffset != KStateSamplingEnding)
        {
        DProfilerGenericSampler<BufferSize>::Reset(aStream);
#ifdef ITT_EVENT_HANDLER
        // Itt event handler
        if(iEventHandler)
            {
            // stop previous sampling if still running
            Kern::Printf("Stopping DIttEventHandler");
            iEventHandler->Stop();
            }
    
        iEventHandler = new DIttEventHandler(this->iSampleBuffer, this->gppSamplerData);
        if(iEventHandler)
            {
            TInt err(iEventHandler->Create());
            if(err != KErrNone)
                {
                Kern::Printf("Error in creation of DIttEventHandler, error %d", err);
                return err;
                }
            }
        else
            {
            Kern::Printf("Could not initiate DIttEventHandler");
            return KErrGeneral;
            }
    
        // set first sample at the 10 ms, should be enough
        this->ittSamplerImpl.iIttSamplingPeriod = 8;
#else
        this->ittSamplerImpl.iIttSamplingPeriod = this->iSamplingPeriod;
#endif
        this->ittSamplerImpl.iIttSamplingPeriodDiv2 = (TInt)(this->ittSamplerImpl.iIttSamplingPeriod / 2);
        LOGSTRING3("DProfilerIttSampler<%d>::Reset - set ITT sampling period to %d",
                                BufferSize,this->ittSamplerImpl.iIttSamplingPeriod);
        }
    else
        {
        LOGSTRING2("DProfilerIttSampler<%d>::Reset - reset in stop", BufferSize);
#ifdef ITT_EVENT_HANDLER
        // destroy memory event handler
        if(iEventHandler)
            {
            // stop previous sampling if still running
            iEventHandler->Stop();
            }
#endif
        return KErrNone;    // return if reset called in stop
        }

    TInt length(ittSamplerImpl.CreateFirstSample());
    this->iSampleBuffer->AddSample((TUint8*)&length,1);
    this->iSampleBuffer->AddSample(ittSamplerImpl.itt_sample, length);
    this->sampleInProgress = false;
    this->sampleNeeded = false;
    //LOGSTRING("DProfilerIttSampler::Reset - exit");
	this->ittSamplerImpl.Reset();
    return KErrNone;

    }

/*
 * DProfilerIttSampler::PostSample
 * 
 * Function for finishing sample
 */
template <int BufferSize> 
TInt DProfilerIttSampler<BufferSize>::PostSample()
    {
#ifdef ITT_EVENT_HANDLER
    if(!ittSamplerImpl.iInitialSegsTaken || !ittSamplerImpl.iInitialLibsTaken)   // if we haven't read the initial state
        {
#endif
        if(sampleNeeded)
            {
            this->sampleNeeded = false;
            LOGSTRING3("DProfilerIttSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus());
    
            TInt length = this->ittSamplerImpl.SampleImpl(this->gppSamplerData->lastPcValue,
                                                          this->gppSamplerData->sampleNumber);
            if(length != 0)
                {		
                LOGSTRING("ITT sampler PostSample - starting to sample");
                while(length > 0)
                    {
                    this->iSampleBuffer->AddSample(ittSamplerImpl.itt_sample,length);
                    length = this->ittSamplerImpl.SampleImpl( this->gppSamplerData->lastPcValue,
                                                          this->gppSamplerData->sampleNumber );	
                    if(length == 0) 
                        {
                        LOGSTRING("ITT sampler PostSample - done for this round!");
                        }
                    }
                LOGSTRING("ITT sampler PostSample - finished sampling");
                }
            this->sampleInProgress = false;
            }
#ifdef ITT_EVENT_HANDLER
        }
#endif
	
    LOGSTRING2("ITT sampler PostSample - finished sampling, time: %d", gppSamplerData->sampleNumber);
    
	// finally perform superclass postsample
	TInt i(this->DProfilerGenericSampler<BufferSize>::PostSample());
#ifdef ITT_EVENT_HANDLER	
	// notify event handler
	if(iEventHandler)
	    {
	    iEventHandler->SampleHandled();
	    }
#endif
	return i;
    }

/*
 *  DProfilerIttSampler::PostSampleNeeded()
 *  
 *  Function for deciding if sample handling is needed 
 */
template <int BufferSize> 
TBool DProfilerIttSampler<BufferSize>::PostSampleNeeded()
    {
	LOGSTRING3("DProfilerIttSampler<%d>::PostSampleNeeded - buffer status %d",BufferSize,this->iSampleBuffer->GetBufferStatus());

	TUint32 status(this->iSampleBuffer->GetBufferStatus());
#ifdef ITT_EVENT_HANDLER
    if(iEventHandler)
        {
        if(iEventHandler->Tracking())
            {
            this->sampleNeeded = iEventHandler->SampleNeeded();
            }
        }
#endif    
	if(status == DProfilerSampleBuffer::BufferCopyAsap || 
	        status == DProfilerSampleBuffer::BufferFull || 
	        this->sampleNeeded == true)
	    {
	    LOGSTRING2("DProfilerIttSampler<%d>::PostSampleNeeded - buffer needs emptying or sample is needed",BufferSize);
		return true;
	    }
	return false;
    }

/*
 * DProfilerIttSampler::Sample
 * 
 * Function for initiating sampling
 */
template <int BufferSize>
void DProfilerIttSampler<BufferSize>::Sample(TAny* aPtr)
    {
	LOGSTRING2("DProfilerIttSampler<%d>::Sample - entry",BufferSize);	
    if(iEventHandler)
        {
        if(!iEventHandler->Tracking())
            {
            if(ittSamplerImpl.SampleNeeded(this->gppSamplerData->sampleNumber) && this->sampleInProgress == false) 
                {
                this->sampleInProgress = true;
                this->sampleNeeded = true;
        
                LOGSTRING2("DProfilerIttSampler<%d>::Sample - sample needed 1",BufferSize);	
                }
            
            if(ittSamplerImpl.iInitialSegsTaken && ittSamplerImpl.iInitialLibsTaken) 
                {
                iEventHandler->Start();
                }
            }
        }
    else
        {
        if(ittSamplerImpl.SampleNeeded(this->gppSamplerData->sampleNumber) && this->sampleInProgress == false) 
            {
            this->sampleInProgress = true;
            this->sampleNeeded = true;
    
            LOGSTRING2("DProfilerIttSampler<%d>::Sample - sample needed 2",BufferSize);   
            }
        }

	LOGSTRING2("DProfilerIttSampler<%d>::Sample - exit",BufferSize);
	return;
    }

/*
 * Destructor
 */
template <int BufferSize>
DProfilerIttSampler<BufferSize>::~DProfilerIttSampler()
    {
	LOGSTRING2("DProfilerIttSampler<%d>::~DProfilerIttSampler",BufferSize);
#ifdef ITT_EVENT_HANDLER
     if(iEventHandler)
         {
         // stop previous sampling if still running
         iEventHandler->Stop();
         iEventHandler->Close();
         iEventHandler = NULL;
         }
#endif
    }
#endif
// end of file