--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/GeneralsPlugin/src/PriSamplerImpl.cpp Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,312 @@
+/*
+* 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:
+*
+*/
+
+
+#include <piprofiler/ProfilerVersion.h>
+#include <piprofiler/ProfilerTraces.h>
+
+#include <kern_priv.h>
+#include <plat_priv.h>
+
+#include "PriSamplerImpl.h"
+
+#if !defined(__NKERN_H__)
+#include <nkern.h>
+#endif
+
+#define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext))
+#define PROFILER_THREAD_MARK ((TUint32)0x00000002)
+
+
+DPriSamplerImpl::DPriSamplerImpl() :
+ sampleDescriptor(&(this->sample[1]),0,256)
+ {
+ LOGTEXT("PriSamplerImpl::PriSamplerImpl() - konstruktori");
+
+ iCountti = 50; // sample threads 16 cycles before actual MEM and PRI sample time...
+ iNewThreadCount = 0;
+ iThreadCount = 0;
+ iProcessing = ENothingToProcess;
+
+ for(TInt i=0;i<KProfilerMaxThreadAmount;i++)
+ {
+ this->threadsToSample[i] = 0;
+ this->threadNamesToReport[i] = 0;
+ }
+
+ }
+
+DPriSamplerImpl::~DPriSamplerImpl()
+ {
+
+ }
+
+TInt DPriSamplerImpl::CreateFirstSample()
+ {
+ LOGTEXT("PriSamplerImpl::CreateFirstSample - entry");
+
+ this->sampleDescriptor.Zero();
+ this->sampleDescriptor.Append(_L8("Bappea_V"));
+ this->sampleDescriptor.Append(PROFILER_PRI_SAMPLER_VERSION);
+ this->sampleDescriptor.Append(_L8("_PRI"));
+
+ sample[0] = this->sampleDescriptor.Size();
+
+ LOGTEXT("PriSamplerImpl::CreateFirstSample - exit");
+
+ return (TInt)(sample[0]+1);
+ }
+
+TBool DPriSamplerImpl::SampleNeeded()
+ {
+ iCountti++;
+ if(iCountti % (iPriSamplingPeriod) == 0)
+ {
+ LOGTEXT("PriSamplerImpl::SampleNeeded - true");
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+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];
+
+ // 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];
+ 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);
+ }
+
+ 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;
+ }
+ }
+
+inline TInt DPriSamplerImpl::ProcessChunks()
+ {
+ /*
+ *
+ * EKA-2 implementation of PRI trace
+ *
+ */
+
+ if(iNewThreadCount > 0)
+ {
+ if(this->iProcessing == EStartingToProcess)
+ {
+ // this is the first sample, encode a code for names
+ this->iProcessing = EProcessingNames;
+ return EncodeNameCode();
+ }
+
+ // there are new thread names to report
+ iNewThreadCount--;
+ DThread* t = this->threadNamesToReport[iNewThreadCount];
+ return EncodeChunkName(*t);
+ }
+ else if(iThreadCount > 0)
+ {
+ if(this->iProcessing == EProcessingNames || this->iProcessing == EStartingToProcess)
+ {
+ // this is the first data sample, encode a code for data
+ this->iProcessing = EProcessingData;
+ return EncodeDataCode();
+ }
+
+ // there are no new chunks to report
+ // thus generate the real report
+ iThreadCount--;
+ DThread* t = this->threadsToSample[iThreadCount];
+ LOGSTRING2("PriSamplerImpl::ProcessChunks - starting to process thread 0x%x",t);
+ return EncodeChunkData(*t);
+ }
+ else
+ {
+ // everything is processed
+ return 0;
+ }
+ }
+
+inline TInt DPriSamplerImpl::EncodeNameCode()
+ {
+ sample[0] = 1;
+ sample[1] = 0xbb; // pri trace name code
+ return 2;
+ }
+
+inline TInt DPriSamplerImpl::EncodeDataCode()
+ {
+ sample[0] = 1;
+ sample[1] = 0xee; // pri trace data code
+ return 2;
+ }
+
+
+inline TInt DPriSamplerImpl::EncodeChunkName(DThread& t)
+ {
+ // the size of the following name is in the first byte
+ TUint8* size = &sample[0];
+ *size = 0;
+ this->sampleDescriptor.Zero();
+
+ t.TraceAppendFullName(this->sampleDescriptor,false);
+ *size += this->sampleDescriptor.Size();
+
+ // copy the 4 bytes from the thread id field
+ this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
+ *size += sizeof(TUint);
+
+ // the size is the descriptor length + the size field
+ LOGSTRING2("Name size - %d",*size);
+ return ((TInt)(*size))+1;
+ }
+
+
+inline TInt DPriSamplerImpl::EncodeChunkData(DThread& t)
+ {
+ LOGTEXT("PriSamplerImpl::EncodeChunkData - entry");
+ LOGSTRING2("PriSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t);
+
+ // the size of the following name is in the first byte
+ TUint8* size = &sample[0];
+ *size = 0;
+ this->sampleDescriptor.Zero();
+
+ LOGTEXT("PriSamplerImpl::EncodeChunkData - cleared");
+
+ // append the thread id
+ this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
+ *size += sizeof(TUint);
+
+// NKern::LockSystem();
+// TInt priority(-1);
+// if(&t && t.Open()== KErrNone)
+// {
+// priority = t.iDefaultPriority;
+// }
+// NKern::UnlockSystem();
+
+ // append the priority of the nanokernel fast semaphore
+// this->sampleDescriptor.Append((TUint8*)&priority,sizeof(TUint8));
+ // append the priority of the nanokernel fast semaphore
+ this->sampleDescriptor.Append((TUint8*)&(t.iNThread.iPriority),sizeof(TUint8));
+ // add space because EKA-1 implementation needs it
+ this->sampleDescriptor.Append((TUint8)0x0);
+ *size += 2*sizeof(TUint8);
+
+ LOGTEXT("PriSamplerImpl::EncodeChunkData - appended priority");
+
+
+ LOGSTRING2("Data size - %d",*size);
+ return ((TInt)(*size))+1;
+ }
+
+
+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
+ DObjectCon* threads = Kern::Containers()[EThread];
+ TInt totalThreadCount = threads->Count();
+ for(TInt i=0;i<totalThreadCount;i++)
+ {
+ DThread* t = (DThread*)(*threads)[i];
+ TAG(t) = (TAG(t) & 0xfffffffd);
+ }
+ }
+