sysanadatacapture/piprofiler/piprofiler/plugins/GeneralsPlugin/src/PriSamplerImpl.cpp
changeset 1 3ff3fecb12fe
equal deleted inserted replaced
0:f0f2b8682603 1:3ff3fecb12fe
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <piprofiler/ProfilerVersion.h>
       
    20 #include <piprofiler/ProfilerTraces.h>
       
    21 
       
    22 #include <kern_priv.h>
       
    23 #include <plat_priv.h>
       
    24 
       
    25 #include "PriSamplerImpl.h"
       
    26 
       
    27 #if !defined(__NKERN_H__)
       
    28 #include <nkern.h>
       
    29 #endif 
       
    30 
       
    31 #define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext))
       
    32 #define PROFILER_THREAD_MARK		((TUint32)0x00000002)
       
    33 
       
    34 
       
    35 PriSamplerImpl::PriSamplerImpl() :
       
    36 	sampleDescriptor(&(this->sample[1]),0,256)
       
    37     {
       
    38 	LOGTEXT("PriSamplerImpl::PriSamplerImpl() - konstruktori");
       
    39 
       
    40 	iCountti = 50;	// sample threads 16 cycles before actual MEM and PRI sample time...
       
    41 	iNewThreadCount = 0;
       
    42 	iThreadCount = 0;
       
    43 	iProcessing = ENothingToProcess;
       
    44 	
       
    45 	for(TInt i=0;i<KProfilerMaxThreadAmount;i++)
       
    46 	    {
       
    47 		this->threadsToSample[i] = 0;
       
    48 		this->threadNamesToReport[i] = 0;
       
    49         }
       
    50 
       
    51     }
       
    52 
       
    53 PriSamplerImpl::~PriSamplerImpl()
       
    54     {
       
    55 	
       
    56     }
       
    57 
       
    58 TInt PriSamplerImpl::CreateFirstSample()
       
    59     {
       
    60 	LOGTEXT("PriSamplerImpl::CreateFirstSample - entry");
       
    61 	
       
    62 	this->sampleDescriptor.Zero();
       
    63 	this->sampleDescriptor.Append(_L8("Bappea_V"));
       
    64 	this->sampleDescriptor.Append(PROFILER_PRI_SAMPLER_VERSION);
       
    65 	this->sampleDescriptor.Append(_L8("_PRI"));
       
    66 
       
    67 	sample[0] = this->sampleDescriptor.Size();
       
    68 
       
    69 	LOGTEXT("PriSamplerImpl::CreateFirstSample - exit");
       
    70 
       
    71 	return (TInt)(sample[0]+1);
       
    72     }
       
    73 
       
    74 TBool PriSamplerImpl::SampleNeeded()
       
    75     {
       
    76 	iCountti++;
       
    77 	if(iCountti % (iPriSamplingPeriod) == 0) 
       
    78 	    {
       
    79 		LOGTEXT("PriSamplerImpl::SampleNeeded - true");
       
    80 		return true;
       
    81         }
       
    82 	else 
       
    83 	    {
       
    84 		return false;
       
    85         }
       
    86     }
       
    87 
       
    88 
       
    89 TInt PriSamplerImpl::SampleImpl()
       
    90     {
       
    91 	/*
       
    92 	 *
       
    93 	 *	EKA-2 implementation of PRI trace
       
    94 	 *
       
    95 	 */
       
    96 	if(this->iProcessing == ENothingToProcess)
       
    97 	    {
       
    98 	    if((iCountti % iPriSamplingPeriod) != 0 ) return 0;
       
    99 	    
       
   100         LOGTEXT("Processing threads...");
       
   101 
       
   102         DObjectCon& threads = *Kern::Containers()[EThread];
       
   103 
       
   104         // PRI trace variables
       
   105         this->iThreadCount = 0; 
       
   106         this->iNewThreadCount = 0;
       
   107         TInt totalThreadCount = threads.Count();
       
   108 
       
   109         for(TInt i=0;i<totalThreadCount;i++)
       
   110             {
       
   111             DThread* t = (DThread*)(threads)[i];
       
   112             LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t));
       
   113 
       
   114             if( (TAG(t) & PROFILER_THREAD_MARK) == 0)
       
   115                 {
       
   116                 LOGSTRING2("Marking thread %d",i);
       
   117                 // this thread's chunk has not been reported yet
       
   118                 this->threadNamesToReport[iNewThreadCount] = t;
       
   119                 iNewThreadCount++;
       
   120                 // tag the thread
       
   121                 TAG(t) |= PROFILER_THREAD_MARK;
       
   122                 LOGSTRING2("New Thread %d",i);
       
   123                 }
       
   124             else
       
   125                 {
       
   126                 LOGSTRING3("Thread %d marked already - 0x%x",i,TAG(t));
       
   127                 }
       
   128 
       
   129             // the thread has been tagged, add heap chunks to the list
       
   130             this->threadsToSample[this->iThreadCount] = t;
       
   131             this->iThreadCount++;
       
   132             LOGSTRING2("Added thread %d to threads to sample",i);
       
   133             }
       
   134 
       
   135         if(this->iThreadCount > 0 || this->iNewThreadCount > 0)
       
   136             {
       
   137             this->iProcessing = EStartingToProcess;
       
   138             
       
   139             // process the first sample
       
   140             TInt length = this->ProcessChunks();
       
   141             
       
   142             if(length == 0)
       
   143                 {
       
   144                 this->iProcessing = ENothingToProcess;
       
   145                 }
       
   146         
       
   147             return length;
       
   148             }
       
   149         else
       
   150             {
       
   151             // there were no threads, should not take place
       
   152             LOGTEXT("PriSamplerImpl::SampleImpl - Error, no threads"); 
       
   153             return 0;
       
   154             }
       
   155 	    }
       
   156 	else
       
   157 	    {
       
   158 		TInt length = this->ProcessChunks();
       
   159 		if(length == 0) 
       
   160 		    {
       
   161 			this->iProcessing = ENothingToProcess;
       
   162 		    }
       
   163 		return length;
       
   164 	    }
       
   165     }
       
   166 
       
   167 inline TInt PriSamplerImpl::ProcessChunks()
       
   168     {
       
   169 	/*
       
   170 	 *
       
   171 	 *	EKA-2 implementation of PRI trace
       
   172 	 *
       
   173 	 */
       
   174 
       
   175 	if(iNewThreadCount > 0)
       
   176 	    {
       
   177 		if(this->iProcessing == EStartingToProcess)
       
   178 		    {
       
   179 			// this is the first sample, encode a code for names
       
   180 			this->iProcessing = EProcessingNames;
       
   181 			return EncodeNameCode();
       
   182             }
       
   183 
       
   184 		// there are new thread names to report
       
   185 		iNewThreadCount--;
       
   186 		DThread* t = this->threadNamesToReport[iNewThreadCount];
       
   187 		return EncodeChunkName(*t);
       
   188         }
       
   189 	else if(iThreadCount > 0)
       
   190 	    {
       
   191 		if(this->iProcessing == EProcessingNames || this->iProcessing == EStartingToProcess)
       
   192 		    {
       
   193 			// this is the first data sample, encode a code for data
       
   194 			this->iProcessing = EProcessingData;
       
   195 			return EncodeDataCode();
       
   196             }
       
   197 
       
   198 		// there are no new chunks to report
       
   199 		// thus generate the real report
       
   200 		iThreadCount--;
       
   201 		DThread* t = this->threadsToSample[iThreadCount];
       
   202 		LOGSTRING2("PriSamplerImpl::ProcessChunks - starting to process thread 0x%x",t);
       
   203 		return EncodeChunkData(*t);
       
   204         }
       
   205 	else
       
   206 	    {
       
   207 		// everything is processed
       
   208 		return 0;
       
   209         }
       
   210     }
       
   211 
       
   212 inline TInt PriSamplerImpl::EncodeNameCode()
       
   213     {
       
   214 	sample[0] = 1;
       
   215 	sample[1] = 0xbb;	// pri trace name code
       
   216 	return 2;
       
   217     }
       
   218 
       
   219 inline TInt PriSamplerImpl::EncodeDataCode()
       
   220     {
       
   221 	sample[0] = 1;
       
   222 	sample[1] = 0xee;	// pri trace data code
       
   223 	return 2;
       
   224     }
       
   225 
       
   226 
       
   227 inline TInt PriSamplerImpl::EncodeChunkName(DThread& t)
       
   228     {		
       
   229 	// the size of the following name is in the first byte
       
   230 	TUint8* size = &sample[0];
       
   231 	*size = 0;
       
   232 	this->sampleDescriptor.Zero();
       
   233 	
       
   234 	t.TraceAppendFullName(this->sampleDescriptor,false);
       
   235 	*size += this->sampleDescriptor.Size();
       
   236 	
       
   237 	// copy the 4 bytes from the thread id field
       
   238 	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   239 	*size += sizeof(TUint);
       
   240 
       
   241 	// the size is the descriptor length + the size field
       
   242 	LOGSTRING2("Name size - %d",*size);
       
   243 	return ((TInt)(*size))+1;
       
   244     }
       
   245 
       
   246 
       
   247 inline TInt PriSamplerImpl::EncodeChunkData(DThread& t)
       
   248     {
       
   249 	LOGTEXT("PriSamplerImpl::EncodeChunkData - entry");
       
   250 	LOGSTRING2("PriSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t);
       
   251 		
       
   252 	// the size of the following name is in the first byte
       
   253 	TUint8* size = &sample[0];
       
   254 	*size = 0;
       
   255 	this->sampleDescriptor.Zero();
       
   256 
       
   257 	LOGTEXT("PriSamplerImpl::EncodeChunkData - cleared");
       
   258 
       
   259     // append the thread id
       
   260     this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   261     *size += sizeof(TUint);
       
   262     
       
   263 //    NKern::LockSystem();
       
   264 //    TInt priority(-1);
       
   265 //    if(&t && t.Open()== KErrNone)
       
   266 //        {
       
   267 //       priority = t.iDefaultPriority;
       
   268 //        }
       
   269 //    NKern::UnlockSystem();
       
   270     
       
   271     // append the priority of the nanokernel fast semaphore
       
   272 //    this->sampleDescriptor.Append((TUint8*)&priority,sizeof(TUint8));
       
   273     // append the priority of the nanokernel fast semaphore
       
   274     this->sampleDescriptor.Append((TUint8*)&(t.iNThread.iPriority),sizeof(TUint8));
       
   275     // add space because EKA-1 implementation needs it
       
   276     this->sampleDescriptor.Append((TUint8)0x0);
       
   277     *size += 2*sizeof(TUint8);
       
   278 
       
   279     LOGTEXT("PriSamplerImpl::EncodeChunkData - appended priority");
       
   280         
       
   281 
       
   282     LOGSTRING2("Data size - %d",*size);
       
   283     return ((TInt)(*size))+1;	
       
   284     }
       
   285 
       
   286 
       
   287 void PriSamplerImpl::Reset()
       
   288     {
       
   289 	/*
       
   290 	 *
       
   291 	 *	EKA-2 implementation of PRI trace
       
   292 	 *
       
   293 	 */
       
   294 
       
   295 	LOGTEXT("PriSamplerImpl::Reset");
       
   296 	iCountti = 50;	// sample threads 16 cycles before actual MEM and PRI sample time...
       
   297 	this->iThreadCount = 0;
       
   298 	this->iNewThreadCount = 0;
       
   299 	this->iProcessing = ENothingToProcess;
       
   300 	this->sampleDescriptor.Zero();
       
   301 
       
   302 
       
   303 	// clear all thread tags
       
   304 	DObjectCon* threads = Kern::Containers()[EThread];
       
   305 	TInt totalThreadCount = threads->Count();
       
   306 	for(TInt i=0;i<totalThreadCount;i++)
       
   307 	    {
       
   308 		DThread* t = (DThread*)(*threads)[i];
       
   309 		TAG(t) = (TAG(t) & 0xfffffffd);
       
   310 	    }
       
   311     }
       
   312