sysanadatacapture/piprofiler/piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp
changeset 2 6a82cd05fb1e
parent 1 3ff3fecb12fe
equal deleted inserted replaced
1:3ff3fecb12fe 2:6a82cd05fb1e
     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 #include <kern_priv.h>
       
    22 
       
    23 #include "GppSamplerImpl.h"
       
    24 
       
    25 extern TUint*		IntStackPtr();
       
    26 #define	TAG(obj)	(*(TUint32*)&(obj.iAsyncDeleteNext))
       
    27 
       
    28 // properties for ISA task parsing
       
    29 const TUid KIsaPropertyCat={0x2001E5AD};
       
    30 enum TIsaPropertyKeys
       
    31 	{
       
    32 	EIsaPropertyIsaTaskParserStatus = 1,
       
    33 	EIsaPropertyIsaTaskAddressStart,
       
    34 	EIsaPropertyIsaTaskAddressEnd,
       
    35 	EIsaPropertyIsaTaskAddress,
       
    36 	EIsaPropertyIsaOsTaskRunningAddress,
       
    37 	EIsaPropertyIsaTaskParsedName
       
    38 	};
       
    39 
       
    40 
       
    41 GppSamplerImpl::GppSamplerImpl()
       
    42 	{
       
    43 	LOGTEXT("GppSamplerImpl::GppSamplerImpl");
       
    44 	iInterruptStack = (TUint*)IntStackPtr();
       
    45 
       
    46 	LOGTEXT("GppSamplerImpl::GppSamplerImpl - attaching to properties");
       
    47 
       
    48 	TInt err = iIsaStartAddr.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskAddressStart);
       
    49 	if(err != KErrNone)
       
    50 		LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskAddressStart not available"); 
       
    51 	err = iIsaEndAddr.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskAddressEnd);
       
    52 	if(err != KErrNone)
       
    53 		LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskAddressEnd not available"); 
       
    54 	err = iIsaPluginStatus.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskParserStatus);
       
    55 	if(err != KErrNone)
       
    56 		LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskParserStatus not available"); 
       
    57 	err = iIsaOsTaskRunning.Attach(KIsaPropertyCat, EIsaPropertyIsaOsTaskRunningAddress);
       
    58 	if(err != KErrNone)
       
    59 		LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaOsTaskRunningAddress not available"); 
       
    60 	
       
    61 	PROFILER_ISA_TASK_NAMES
       
    62 	
       
    63 	Reset();
       
    64 	}
       
    65 
       
    66 GppSamplerImpl::~GppSamplerImpl() 
       
    67 	{
       
    68 	iIsaStartAddr.Close();
       
    69 	iIsaEndAddr.Close();
       
    70 	iIsaPluginStatus.Close();
       
    71 	iIsaOsTaskRunning.Close();
       
    72 	}
       
    73 
       
    74 void GppSamplerImpl::Reset()
       
    75 	{
       
    76 	LOGTEXT("GppSamplerImpl::Reset");
       
    77 	iLastPc = 0;
       
    78 	iLastThread = 0;
       
    79 	iRepeat = 0;
       
    80 	iIsaStatus = 0;
       
    81 	iIsaStart = 0;
       
    82 	iIsaEnd = 0;
       
    83 //	isaOsTaskRunningAddr = 0;
       
    84 	iStartTime=( NKern::TickCount() & 0xfffffffc );
       
    85 	
       
    86 	TPropertyStatus status;
       
    87 	TInt osAddr = 0;
       
    88 	
       
    89 	LOGTEXT("GppSamplerImpl::Reset - getting status");
       
    90 	
       
    91 	// get status of ISA plug-in
       
    92 	if(iIsaPluginStatus.GetStatus(status))
       
    93 		{
       
    94 		iIsaPluginStatus.Get(iIsaStatus);
       
    95 		LOGSTRING2("GppSamplerImpl::Reset - ISA plug-in status %d", iIsaStatus);
       
    96 		}
       
    97 	
       
    98 	if(iIsaStatus > 0)
       
    99 		{
       
   100 		LOGTEXT("GppSamplerImpl::Reset - get isa start address");
       
   101 		iIsaStartAddr.Get(iIsaStart);
       
   102 		LOGTEXT("GppSamplerImpl::Reset - get isa end address");
       
   103 		iIsaEndAddr.Get(iIsaEnd);
       
   104 		LOGTEXT("GppSamplerImpl::Reset - get isa os_task_running address");
       
   105 		iIsaOsTaskRunning.Get(osAddr);
       
   106 		isaOsTaskRunningAddr = reinterpret_cast<TInt*>(osAddr);
       
   107 		LOGSTRING2("GppSamplerImpl::Reset - got isa os_task_running address 0x%X", osAddr);
       
   108 		}
       
   109 	
       
   110 	LOGTEXT("GppSamplerImpl::Reset - initializing isa task list");
       
   111 
       
   112 	iIsaSample = false;
       
   113 	
       
   114 	for(TInt i=0;i<256;i++)
       
   115 		knownIsaTasks[i] = -1;
       
   116 	
       
   117 	knownIsaTaskCount = 0;
       
   118 	
       
   119 	}
       
   120 
       
   121 TUint8* GppSamplerImpl::EncodeTag(TUint8* aPtr)
       
   122 //
       
   123 // Encode a tag and version to the trace data. This allows the offline analyser to 
       
   124 // identify the sample data.
       
   125 //
       
   126 {	
       
   127 	_LIT(KGppSamplerVersion,"Bappea_GPP_V");
       
   128 	_LIT(KProfilerVersion,"#Prof#");
       
   129 	_LIT(KSamplerVersion,"#Samp#");
       
   130 	
       
   131 	TBuf<64> buf;
       
   132 	buf.Zero();
       
   133 	buf.Append(KGppSamplerVersion);
       
   134 	buf.Append(PROFILER_GPP_SAMPLER_VERSION);
       
   135 	buf.Append(KProfilerVersion);
       
   136 	buf.Append(PROFILER_VERSION_SHORT);	
       
   137 	buf.Append(KSamplerVersion);
       
   138 	buf.Append(PROFILER_SAMPLER_VERSION);
       
   139 	aPtr = EncodeText(aPtr, buf);
       
   140 	return aPtr;
       
   141 }
       
   142 
       
   143 TUint8* GppSamplerImpl::EncodeInt(TUint8* aPtr,TInt aValue)
       
   144 {
       
   145 	LOGSTRING2("Encoding int 0x%x",aPtr);
       
   146 
       
   147 	LOGSTRING2("TIint = 0x%x",aValue);
       
   148 
       
   149 	TUint byte;
       
   150 	for (;;)
       
   151 		{
       
   152 		byte = aValue & 0x7f;
       
   153 		if ((aValue >> 6) == (aValue >> 7))
       
   154 			break;
       
   155 		aValue >>= 7;
       
   156 		*aPtr++ = byte;
       
   157 		}
       
   158 	*aPtr++ = byte | 0x80;
       
   159 
       
   160 	LOGSTRING2("Encoded int 0x%x",aPtr);
       
   161 
       
   162 	return aPtr;
       
   163 }
       
   164 
       
   165 TUint8* GppSamplerImpl::EncodeUint(TUint8* aPtr,TUint aValue)
       
   166 {
       
   167 	LOGSTRING2("Encoding Uint 0x%x",aPtr);
       
   168 
       
   169 	LOGSTRING2("TUint = 0x%x",aValue);
       
   170 
       
   171 
       
   172 	TUint byte;
       
   173 	for (;;)
       
   174 		{
       
   175 		byte = aValue & 0x7f;
       
   176 		aValue >>= 7;
       
   177 		if (aValue == 0)
       
   178 			break;
       
   179 		*aPtr++ = byte;
       
   180 		}
       
   181 	*aPtr++ = byte | 0x80;
       
   182 
       
   183 	LOGSTRING2("Encoded Uint 0x%x",aPtr);
       
   184 
       
   185 	return aPtr;
       
   186 }
       
   187 
       
   188 TUint8* GppSamplerImpl::EncodeText(TUint8* aPtr, const TDesC& aDes)
       
   189 //
       
   190 // Encode a descriptor into the data stream
       
   191 // This is currently limited to a descriptor that is up to 255 characters in length,
       
   192 // and Unicode characters are truncated to 8 bits
       
   193 //
       
   194 {
       
   195 	LOGSTRING2("Encoding text 0x%x",aPtr);
       
   196 	TInt len=aDes.Length();
       
   197 	*aPtr++ = TUint8(len);
       
   198 	const TText* p = aDes.Ptr();
       
   199 	while (--len >= 0)
       
   200 		{
       
   201 		*aPtr++ = TUint8(*p++);
       
   202 		}
       
   203 
       
   204 	LOGSTRING2("Encoded text 0x%x",aPtr);
       
   205 	return aPtr;
       
   206 }
       
   207 
       
   208 
       
   209 TUint8* GppSamplerImpl::EncodeName(TUint8* aPtr, DObject& aObject,TUint32 id)
       
   210 //
       
   211 // Encode the name of a kernel object
       
   212 //
       
   213 {
       
   214 	LOGSTRING2("Encoding name 0x%x",aPtr);
       
   215 	TBuf8<0x5f> name;
       
   216 	aObject.TraceAppendName(name,false);
       
   217 
       
   218 	if(id != 0xffffffff)
       
   219 	{
       
   220 		name.Append('[');
       
   221 		name.AppendNum(id,EHex);
       
   222 		name.Append(']');
       
   223 	}
       
   224 	else
       
   225 	{
       
   226 		name.Append('[');
       
   227 		name.AppendNum((TUint32)((void*)&(((DThread*)&aObject)->iNThread)),EHex);
       
   228 		name.Append(']');
       
   229 	}
       
   230 
       
   231 	aPtr = EncodeText(aPtr,name);
       
   232 	LOGSTRING2("Encoded name 0x%x",aPtr);
       
   233 	return aPtr;
       
   234 }
       
   235 
       
   236 TUint8* GppSamplerImpl::EncodeThread(TUint8* aPtr, DThread& aThread)
       
   237 //
       
   238 // Encode a thread name in the data stream.
       
   239 // The thread is identified by its name, and the identity of its owning process.
       
   240 // If the process has not been identified in the data stream already, it's name is
       
   241 // also encoded.
       
   242 //
       
   243 {
       
   244 	LOGSTRING2("Encoding thread 0x%x",aPtr);	
       
   245 
       
   246 	DProcess& p = *aThread.iOwningProcess;
       
   247 	
       
   248 	aPtr = EncodeUint(aPtr, p.iId);
       
   249 	if (TAG(p) != iStartTime)
       
   250 	{
       
   251 		TAG(p) = iStartTime;
       
   252 		// Provide the name matching this process ID
       
   253 		aPtr = EncodeName(aPtr, p, p.iId);
       
   254 	}
       
   255 	aPtr = EncodeName(aPtr, aThread,0xffffffff);
       
   256 	
       
   257 	LOGSTRING2("Encoded thread 0x%x",aPtr);	
       
   258 
       
   259 	return aPtr;
       
   260 }
       
   261 
       
   262 TUint8* GppSamplerImpl::EncodeRepeat(TUint8* aPtr)
       
   263 //
       
   264 // Encode a repeated sequence of samples
       
   265 //
       
   266 {
       
   267 	LOGSTRING2("Encoding repeat, 0x%x",iRepeat);	
       
   268 
       
   269 	aPtr = EncodeInt(aPtr, 0);
       
   270 	aPtr = EncodeUint(aPtr, iRepeat);
       
   271 	iRepeat = 0;
       
   272 
       
   273 	LOGSTRING2("Encoded repeat, 0x%x",iRepeat);	
       
   274 
       
   275 	return aPtr;
       
   276 }
       
   277 
       
   278 TInt GppSamplerImpl::CreateFirstSample()
       
   279 {
       
   280 	LOGTEXT("GppSamplerImpl::CreateFirstSample");
       
   281 	Reset();
       
   282 
       
   283 	TUint8* w = this->tempBuf;
       
   284 	w = EncodeTag(w);
       
   285 
       
   286 	TInt length = w-tempBuf;
       
   287 
       
   288 	LOGSTRING2("TAG encoded, length %d",length);
       
   289 	return length;
       
   290 }
       
   291 
       
   292 TBool GppSamplerImpl::IsaTaskKnown(TUint8 task)
       
   293 {
       
   294 	for(TInt i=0;i<256;i++)
       
   295 	{
       
   296 		if(knownIsaTasks[i] == -1)
       
   297 		{
       
   298 			knownIsaTasks[i] = task;
       
   299 			knownIsaTaskCount++;
       
   300 			return false;
       
   301 		}
       
   302 		else if(knownIsaTasks[i] == task)
       
   303 		{
       
   304 			return true;
       
   305 		}
       
   306 	}
       
   307 
       
   308 	return false;
       
   309 }
       
   310 
       
   311 TUint8* GppSamplerImpl::EncodeIsaTask(TUint8* aPtr, TUint task)
       
   312 
       
   313 {
       
   314 	LOGSTRING2("Encoding ISA task 0x%x",aPtr);	
       
   315 
       
   316 	aPtr = EncodeUint(aPtr,task);
       
   317 	// use the task name as the process name
       
   318 	aPtr = EncodeIsaName(aPtr,task,true);
       
   319 	// then encode the task name
       
   320 	aPtr = EncodeIsaName(aPtr,task,false);
       
   321 	
       
   322 	LOGSTRING2("Encoded ISA task 0x%x",aPtr);	
       
   323 
       
   324 	return aPtr;
       
   325 }
       
   326 
       
   327 TUint8* GppSamplerImpl::EncodeIsaName(TUint8* aPtr, TUint task,TBool process)
       
   328 //
       
   329 // Encode a descriptor into the data stream
       
   330 // This is currently limited to a descriptor that is up to 255 characters in length,
       
   331 // and Unicode characters are truncated to 8 bits
       
   332 //
       
   333 {
       
   334 	TBuf8<256> aDes;
       
   335 	
       
   336 //	#ifdef NCP_COMMON_PROFILER_ISA_TASKS 
       
   337 	if(iIsaStatus > 0)
       
   338 		{
       
   339 		// resolve the isa task name from the task name array
       
   340 		if((task-100000) < PROFILER_ISA_OS_TASK_AMOUNT && process == false)
       
   341 			{
       
   342 			aDes.Append(isaTaskNames[(task-100000)]);
       
   343 			}
       
   344 		else
       
   345 			{
       
   346 			aDes.Append(_L8("NativeOS_Task"));
       
   347 			}
       
   348 		}
       
   349 	else
       
   350 		{
       
   351 		aDes.Append(_L8("NativeOS_Task"));
       
   352 		}
       
   353 	
       
   354 	aDes.Append('[');
       
   355 	aDes.AppendNum((task-100000),EHex);
       
   356 	aDes.Append(']');
       
   357 
       
   358 	LOGSTRING2("Encoding ISA name 0x%x",aPtr);
       
   359 	TInt len=aDes.Length();
       
   360 	*aPtr++ = TUint8(len);
       
   361 	const TText* p = aDes.Ptr();
       
   362 	while (--len >= 0)
       
   363 		{
       
   364 		*aPtr++ = TUint8(*p++);
       
   365 		}
       
   366 
       
   367 	LOGSTRING2("Encoded ISA name 0x%x",aPtr);
       
   368 	return aPtr;
       
   369 }
       
   370 
       
   371 
       
   372 TInt GppSamplerImpl::SampleImpl()
       
   373 //
       
   374 // ISR for the profile timer
       
   375 // This extracts the thread and PC that was current when the interrupt went off and
       
   376 // encodes it into the sample data buffer. If enough data has been generated, the
       
   377 // DFC is triggered to complete a read request
       
   378 //
       
   379 {
       
   380 	TUint8* w = this->tempBuf;
       
   381 	
       
   382 	TUint32 pc = iInterruptStack[-1];
       
   383 	LOGSTRING3("pc value 0x%x sp 0x%x",pc,iInterruptStack);
       
   384 
       
   385 	// ignore the low bit being set for THUMB mode - we use for something else
       
   386 	pc &= ~1;			
       
   387 	TInt diff = pc - iLastPc;
       
   388 	iLastPc = pc;
       
   389 
       
   390 	if(iIsaStatus > 0)
       
   391 		{
       
   392 		if((TUint32)pc > (TUint32)iIsaStart && (TUint32)pc < (TUint32)iIsaEnd)
       
   393 			{
       
   394 			LOGSTRING2("Identified ISA execution at 0x%x",pc);
       
   395 			iIsaSample = true;
       
   396 			}
       
   397 		else
       
   398 			{
       
   399 			LOGSTRING2("Normal sample at 0x%x",pc);
       
   400 			iIsaSample = false;
       
   401 			}
       
   402 		}
       
   403 
       
   404 	DThread& t = Kern::CurrentThread();
       
   405 
       
   406 	TUint tid;
       
   407 	TUint8 isaTask = 0;
       
   408 	if(iIsaSample)
       
   409 	{
       
   410 		LOGSTRING2("Reading ISA task number from 0x%x",isaOsTaskRunningAddr);
       
   411 
       
   412 		// if we don't get reasonable ISA address to read, skip ISA task handling
       
   413 		if(isaOsTaskRunningAddr == 0)
       
   414 			{
       
   415 			tid = 100000; // to tell the difference from SOS threads
       
   416 			iIsaSample = false;
       
   417 			}
       
   418 		else	// normal ISA task parsing process
       
   419 			{
       
   420 			isaTask = *isaOsTaskRunningAddr;
       
   421 			LOGSTRING2("ISA task = %d",isaTask);
       
   422 			tid = isaTask;
       
   423 			// this will make sure we don't mix ISA tasks and normal tasks
       
   424 			tid += 100000;
       
   425 			}
       
   426 
       
   427 	}
       
   428 	else
       
   429 	{
       
   430 		tid = t.iId;
       
   431 	}
       
   432 
       
   433 	if (tid != iLastThread)
       
   434 	{
       
   435 		// Change of thread is marked in the low bit of the PC difference
       
   436 		diff |= 1;
       
   437 	}
       
   438 	TUint rp = iRepeat;
       
   439 	if (diff == 0)
       
   440 	{
       
   441 		// Identical sample, bump up the repeat count
       
   442 		iRepeat = rp + 1;
       
   443 	}
       
   444 	else
       
   445 	{
       
   446 		if (rp)
       
   447 		{
       
   448 			// Encode the repeat data
       
   449 			w = EncodeRepeat(w);
       
   450 		}
       
   451 		// Encode the PC difference
       
   452 		w = EncodeInt(w, diff);
       
   453 		if (diff & 1)
       
   454 		{
       
   455 			// Encode the new thread ID
       
   456 			if(iIsaSample)
       
   457 			{
       
   458 				iLastThread = tid;
       
   459 				w = EncodeUint(w,tid);
       
   460 
       
   461 				if(!this->IsaTaskKnown(isaTask))
       
   462 				{
       
   463 					w = EncodeIsaTask(w,iLastThread);
       
   464 				}
       
   465 				//LOGSTRING2("Sample total length: %d",w-tempBuf);
       
   466 				TInt length = w-tempBuf;
       
   467 				// encoded isa task, return here
       
   468 				return length;
       
   469 			}
       
   470 		
       
   471 			iLastThread = tid;
       
   472 			w = EncodeUint(w, tid);
       
   473 
       
   474 			if ((TAG(t) & 0xfffffffc) != iStartTime)
       
   475 			{
       
   476 			
       
   477 				TAG(t) = ((TAG(t) & 0x3) | iStartTime);
       
   478 				// The thread is 'unknown' to this sample, so encode the thread name
       
   479 				w = EncodeThread(w, t);		
       
   480 			}
       
   481 		}
       
   482 	}
       
   483 	LOGSTRING2("Sample total length: %d",w-tempBuf);
       
   484 	TInt length = w-tempBuf;
       
   485 
       
   486 	return length;
       
   487 }
       
   488