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