os/kernelhwsrv/kerneltest/e32utils/trace/btrace_analyse.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32utils/trace/btrace_analyse.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,3110 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#if defined(__EPOC32__) || defined(__WINS__)
    1.20 +// compiling for Symbian OS...
    1.21 +#include <e32std.h>
    1.22 +#include <e32std_private.h>
    1.23 +#include <e32svr.h>
    1.24 +#include <e32def.h>
    1.25 +#include <e32def_private.h>
    1.26 +#include <d32btrace.h>
    1.27 +#include "e32btrace.h"
    1.28 +
    1.29 +inline void* malloc(TInt aSize) { return User::Alloc(aSize); }
    1.30 +inline void* realloc(void* aPtr,TInt aSize) { return User::ReAlloc(aPtr,aSize); }
    1.31 +inline void free(void* aPtr) { User::Free(aPtr); }
    1.32 +
    1.33 +TUint8 PrintfBuffer[256];
    1.34 +TUint PrintfBufferWidth = 0;
    1.35 +
    1.36 +static void printf(const char* aFormat,...)
    1.37 +	{
    1.38 +	VA_LIST list;
    1.39 +	VA_START(list,aFormat);
    1.40 +	TPtrC8 format((const TUint8*)aFormat);
    1.41 +	TPtr8 buf(PrintfBuffer+PrintfBufferWidth,sizeof(PrintfBuffer)-PrintfBufferWidth);
    1.42 +	buf.AppendFormatList(format,list);
    1.43 +	PrintfBufferWidth += buf.Size();
    1.44 +	for(;;)
    1.45 +		{
    1.46 +		TUint width = 0;
    1.47 +		for(;;)
    1.48 +			{
    1.49 +			if(width>=PrintfBufferWidth)
    1.50 +				return;
    1.51 +			if(PrintfBuffer[width]=='\n')
    1.52 +				break;
    1.53 +			++width;
    1.54 +			}
    1.55 +		TPtrC8 line(PrintfBuffer,width);
    1.56 +		++width;
    1.57 +		RDebug::RawPrint(line);
    1.58 +		_LIT(KLineEnd,"\r\n");
    1.59 +		RDebug::RawPrint(KLineEnd);
    1.60 +		memcpy(PrintfBuffer,PrintfBuffer+width,PrintfBufferWidth-width);
    1.61 +		PrintfBufferWidth -= width;
    1.62 +		}
    1.63 +	}
    1.64 +
    1.65 +typedef TUint uintptr_t;
    1.66 +
    1.67 +#ifndef ASSERT
    1.68 +#define ASSERT(c) (void)((c)||(AssertFailed(__LINE__)))
    1.69 +TInt AssertFailed(TInt aLine)
    1.70 +	{
    1.71 +	_LIT(KPanicCategory,"BTRACE-ANALYSE");
    1.72 +	User::Panic(KPanicCategory,aLine);
    1.73 +	return 0;
    1.74 +	}
    1.75 +#endif // ASSERT
    1.76 +
    1.77 +
    1.78 +//
    1.79 +//	Trace buffer helper functions - for use on target only
    1.80 +//
    1.81 +RBTrace Trace;
    1.82 +TUint8* AnalyseData;
    1.83 +TUint AnalyseDataRemain = 0;
    1.84 +
    1.85 +void RePrime()
    1.86 +	{
    1.87 +	for(TInt i=0; i<256; ++i)
    1.88 +		{
    1.89 +		if(Trace.Filter(i))
    1.90 +			{
    1.91 +			// toggle filter to force a prime
    1.92 +			Trace.SetFilter(i,0);
    1.93 +			Trace.SetFilter(i,1);
    1.94 +			}
    1.95 +		}
    1.96 +	}
    1.97 +
    1.98 +TUint AnalyseStream(TAny* aBuffer, TUint aMaxSize)
    1.99 +	{
   1.100 +	TUint size = AnalyseDataRemain;
   1.101 +	if(!size)
   1.102 +		{
   1.103 +		Trace.DataUsed();
   1.104 +		AnalyseDataRemain = Trace.GetData(AnalyseData);
   1.105 +		size = AnalyseDataRemain;
   1.106 +		}
   1.107 +	if(size>aMaxSize)
   1.108 +		size = aMaxSize;
   1.109 +	memcpy(aBuffer,AnalyseData,size);
   1.110 +	AnalyseData += size;
   1.111 +	AnalyseDataRemain -= size;
   1.112 +	return size;
   1.113 +	}
   1.114 +
   1.115 +void ProcessAllTrace(TUint (*aInput)(TAny* aBuffer, TUint aMaxSize),TInt aReportLevel);
   1.116 +
   1.117 +void DoAnalyse(TInt aAnalysisLevel)
   1.118 +	{
   1.119 +	AnalyseDataRemain = 0;
   1.120 +	TUint oldMode = Trace.Mode();
   1.121 +	Trace.SetMode(0); // turn off trace capture while we dump
   1.122 +	ProcessAllTrace(AnalyseStream, aAnalysisLevel);
   1.123 +	Trace.SetMode(oldMode);
   1.124 +	RePrime();
   1.125 +	}
   1.126 +
   1.127 +TInt BTraceAnalyseSetup()
   1.128 +	{
   1.129 +	TInt r = Trace.Open();
   1.130 +	if (r != KErrNone)
   1.131 +		{
   1.132 +		return r;
   1.133 +		}
   1.134 +	// Stop tracing
   1.135 +	TUint oldMode = Trace.Mode();
   1.136 +	Trace.SetMode(0);
   1.137 +
   1.138 +	// empty btrace buffer and reprime it
   1.139 +	Trace.Empty();
   1.140 +	Trace.SetMode(oldMode);
   1.141 +	RePrime();
   1.142 +	return KErrNone;
   1.143 +	}
   1.144 +
   1.145 +void BTraceAnalyseEnd()
   1.146 +	{
   1.147 +	Trace.Close();
   1.148 +	}
   1.149 +
   1.150 +void BTraceAnalyse(TInt aAnalysisLevel)
   1.151 +	{
   1.152 +	// Stop tracing
   1.153 +	TUint oldMode = Trace.Mode();
   1.154 +	Trace.SetMode(0);
   1.155 +
   1.156 +	AnalyseDataRemain = 0;
   1.157 +	ProcessAllTrace(AnalyseStream, aAnalysisLevel);
   1.158 +
   1.159 +	// empty btrace buffer and reprime it
   1.160 +	Trace.Empty();
   1.161 +	Trace.SetMode(oldMode);
   1.162 +	RePrime();
   1.163 +	}
   1.164 +
   1.165 +#else
   1.166 +// compiling for host...
   1.167 +
   1.168 +#include <stdio.h>
   1.169 +#include <string.h>
   1.170 +#include <malloc.h>
   1.171 +
   1.172 +#if defined(_MSC_VER)
   1.173 +typedef __int64 longlong;
   1.174 +typedef unsigned __int64 ulonglong;
   1.175 +#define BREAKPOINT { _asm int 3 }			/**< Invoke debugger */
   1.176 +#else
   1.177 +typedef long long longlong;
   1.178 +typedef long long ulonglong;
   1.179 +#define BREAKPOINT
   1.180 +#endif
   1.181 +
   1.182 +typedef signed char			TInt8;
   1.183 +typedef unsigned char		TUint8;
   1.184 +typedef unsigned short		TUint16;
   1.185 +typedef unsigned int		TUint32;
   1.186 +typedef ulonglong			TUint64;
   1.187 +typedef unsigned int		uintptr_t;
   1.188 +typedef int					TInt;
   1.189 +typedef unsigned			TUint;
   1.190 +typedef int					TBool;
   1.191 +typedef void				TAny;
   1.192 +typedef float				TReal;
   1.193 +#define IMPORT_C
   1.194 +#include "e32btrace.h"
   1.195 +
   1.196 +#define ASSERT(c) (void)((c)||(AssertFailed(__LINE__)))
   1.197 +extern "C" void exit(int);
   1.198 +TInt AssertFailed(TInt aLine)
   1.199 +	{
   1.200 +	fprintf(stderr,"Panic: BTRACE-ANALYSE %d",aLine);
   1.201 +	BREAKPOINT;
   1.202 +	exit(2);
   1.203 +	return 0;
   1.204 +	}
   1.205 +
   1.206 +#define __UHEAP_MARK
   1.207 +#define __UHEAP_MARKEND
   1.208 +
   1.209 +TAny* operator new(size_t, TAny* p) {return p;}
   1.210 +
   1.211 +#endif // SYMBIAN_OS
   1.212 +
   1.213 +
   1.214 +
   1.215 +//
   1.216 +// Global data
   1.217 +//
   1.218 +
   1.219 +TInt ReportLevel = 0;
   1.220 +TUint8 TraceBuffer[0x10000];
   1.221 +TUint TraceBufferSize = 0;
   1.222 +TUint64	Timestamp = 0;
   1.223 +TUint64	TimestampBase = 0;
   1.224 +TUint32	TraceRecordId = 0;
   1.225 +TUint32	TimestampPeriod = 0;
   1.226 +TUint32	Timestamp2Period = 0;
   1.227 +TBool Timestamp64Bit = 0;
   1.228 +TUint TraceFormatErrors = 0;
   1.229 +TBool TraceBufferFilled = false;
   1.230 +TBool SMP = true;
   1.231 +TBool ErrorOnThisTrace = false;
   1.232 +
   1.233 +const TUint8 KJunkTraceSubcategory = 255; // Dummy sub-category for EMetaTrace
   1.234 +
   1.235 +const TInt KMaxCpus = 8;
   1.236 +
   1.237 +//
   1.238 +// Utilities
   1.239 +//
   1.240 +
   1.241 +void ToHex(TUint8* aString,TUint32 aValue)
   1.242 +	{
   1.243 +	TUint i=32;
   1.244 +	do
   1.245 +		{
   1.246 +		i -= 4;
   1.247 +		TUint8 c = (TUint8)((aValue>>i)&0xf);
   1.248 +		if(c>=10)
   1.249 +			c += 'a'-10;
   1.250 +		else
   1.251 +			c += '0';
   1.252 +		*aString++ = c;
   1.253 +		}
   1.254 +	while(i);
   1.255 +	}
   1.256 +
   1.257 +
   1.258 +TUint MakeName(TUint8* aString,const char* aName,TUint32 aHexValue)
   1.259 +	{
   1.260 +	TUint8* start = aString;
   1.261 +	for(;;)
   1.262 +		{
   1.263 +		TUint8 c = *aName++;
   1.264 +		if(!c)
   1.265 +			break;
   1.266 +		*aString++ = c;
   1.267 +		}
   1.268 +	ToHex(aString,aHexValue);
   1.269 +	aString[8] = 0;
   1.270 +	return aString-start+8;
   1.271 +	}
   1.272 +
   1.273 +
   1.274 +/**
   1.275 +Convert a timestamp into real time units (micro-seconds)
   1.276 +*/
   1.277 +TUint32 Time(TUint64 aTimestamp)
   1.278 +	{
   1.279 +	if(!TimestampPeriod)
   1.280 +		return (TUint32)aTimestamp;
   1.281 +	TInt exponent = (TInt8)(TimestampPeriod>>24);
   1.282 +	TUint64 mantissa = TimestampPeriod&0xffffff;
   1.283 +	aTimestamp *= mantissa;
   1.284 +	exponent += 32;
   1.285 +	if(exponent<0)
   1.286 +		aTimestamp >>= -exponent;
   1.287 +	else
   1.288 +		aTimestamp <<= exponent;
   1.289 +	TUint64 timeLo = (aTimestamp&0xffffffffu)*1000000;
   1.290 +	TUint64 timeHi = (aTimestamp>>32)*1000000;
   1.291 +	TUint64 us = timeHi+(timeLo>>32)+((timeLo>>31)&1);
   1.292 +	return TUint32(us);
   1.293 +	}
   1.294 +
   1.295 +
   1.296 +void ReportTimeUnits()
   1.297 +	{
   1.298 +	if(!TimestampPeriod)
   1.299 +		printf("\nAll times are given in BTrace Timestamp1 units.\n\n");
   1.300 +	else
   1.301 +		{
   1.302 +		TInt exponent = (TInt8)(TimestampPeriod>>24);
   1.303 +		TUint64 mantissa = TimestampPeriod&0xffffff;
   1.304 +		TUint64 period = 1000000;
   1.305 +		period *= mantissa;
   1.306 +		exponent += 32;
   1.307 +		if(exponent<0)
   1.308 +			period >>= -exponent;
   1.309 +		else
   1.310 +			period <<= exponent;
   1.311 +		printf("\nAll times are given in microseconds, resolution %d.%03dus\n\n",(int)TUint32(period>>32),(int)TUint32((((period&0xffffffffu)*1000)+0x80000000u)>>32));
   1.312 +		}
   1.313 +	}
   1.314 +
   1.315 +
   1.316 +TUint SetBits(TUint8* aData, TUint aOffset, TUint aSize)
   1.317 +	{
   1.318 +	TUint mask = 1<<(aOffset&7);
   1.319 +	TUint8* data = aData+(aOffset>>3);
   1.320 +	TUint errors = 0;
   1.321 +	while(aSize)
   1.322 +		{
   1.323 +		if(*data&mask)
   1.324 +			++errors;
   1.325 +		*data |= (TUint8)mask;
   1.326 +		mask <<= 1;
   1.327 +		if(mask>0xFF)
   1.328 +			{
   1.329 +			mask = 0x01;
   1.330 +			++data;
   1.331 +			}
   1.332 +		--aSize;
   1.333 +		}
   1.334 +	return errors;
   1.335 +	}
   1.336 +
   1.337 +
   1.338 +TUint ClearBits(TUint8* aData, TUint aOffset, TUint aSize)
   1.339 +	{
   1.340 +	TUint mask = 1<<(aOffset&7);
   1.341 +	TUint8* data = aData+(aOffset>>3);
   1.342 +	TUint errors = 0;
   1.343 +	while(aSize)
   1.344 +		{
   1.345 +		if(!(*data&mask))
   1.346 +			++errors;
   1.347 +		*data &= (TUint8)~mask;
   1.348 +		mask <<= 1;
   1.349 +		if(mask>0xFF)
   1.350 +			{
   1.351 +			mask = 0x01;
   1.352 +			++data;
   1.353 +			}
   1.354 +		--aSize;
   1.355 +		}
   1.356 +	return errors;
   1.357 +	}
   1.358 +
   1.359 +
   1.360 +void WarnIfError(TUint aErrorCount)
   1.361 +	{
   1.362 +	if (TraceBufferFilled)
   1.363 +		printf("WARNING - BTRACE BUFFER IS FULL SO TRACE DATA MAY BE INCOMPLETE\n");
   1.364 +
   1.365 +	if(aErrorCount==0 && TraceFormatErrors==0)
   1.366 +		return;
   1.367 +	printf("CONSISTENCY ERRORS FOUND DURING TRACE ANALYSIS, RESULTS ARE UNRELIABLE!\n");
   1.368 +	}
   1.369 +
   1.370 +
   1.371 +#define CHECK_TRACE_DATA_WORDS(numWords)	\
   1.372 +	if(aTrace.iDataSize<numWords*4 && ++TraceFormatErrors) return
   1.373 +
   1.374 +
   1.375 +//
   1.376 +// Category naming
   1.377 +//
   1.378 +
   1.379 +const char* const UnknownNames[256] =
   1.380 +	{
   1.381 +	"?00","?01","?02","?03","?04","?05","?06","?07","?08","?09",
   1.382 +	"?10","?11","?12","?13","?14","?15","?16","?17","?18","?19",
   1.383 +	"?20","?21","?22","?23","?24","?25","?26","?27","?28","?29",
   1.384 +	"?30","?31","?32","?33","?34","?35","?36","?37","?38","?39",
   1.385 +	"?40","?41","?42","?43","?44","?45","?46","?47","?48","?49",
   1.386 +	"?50","?51","?52","?53","?54","?55","?56","?57","?58","?59",
   1.387 +	"?60","?61","?62","?63","?64","?65","?66","?67","?68","?69",
   1.388 +	"?70","?71","?72","?73","?74","?75","?76","?77","?78","?79",
   1.389 +	"?80","?81","?82","?83","?84","?85","?86","?87","?88","?89",
   1.390 +	"?90","?91","?92","?93","?94","?95","?96","?97","?98","?99",
   1.391 +	"?100","?101","?102","?103","?104","?105","?106","?107","?108","?109",
   1.392 +	"?110","?111","?112","?113","?114","?115","?116","?117","?118","?119",
   1.393 +	"?120","?121","?122","?123","?124","?125","?126","?127","?128","?129",
   1.394 +	"?130","?131","?132","?133","?134","?135","?136","?137","?138","?139",
   1.395 +	"?140","?141","?142","?143","?144","?145","?146","?147","?148","?149",
   1.396 +	"?150","?151","?152","?153","?154","?155","?156","?157","?158","?159",
   1.397 +	"?160","?161","?162","?163","?164","?165","?166","?167","?168","?169",
   1.398 +	"?170","?171","?172","?173","?174","?175","?176","?177","?178","?179",
   1.399 +	"?180","?181","?182","?183","?184","?185","?186","?187","?188","?189",
   1.400 +	"?190","?191","?192","?193","?194","?195","?196","?197","?198","?199",
   1.401 +	"?200","?201","?202","?203","?204","?205","?206","?207","?208","?209",
   1.402 +	"?210","?211","?212","?213","?214","?215","?216","?217","?218","?219",
   1.403 +	"?220","?221","?222","?223","?224","?225","?226","?227","?228","?229",
   1.404 +	"?230","?231","?232","?233","?234","?235","?236","?237","?238","?239",
   1.405 +	"?240","?241","?242","?243","?244","?245","?246","?247","?248","?249",
   1.406 +	"?250","?251","?252","?253","?254","?255"
   1.407 +	};
   1.408 +
   1.409 +
   1.410 +#define STRINGIFY2(a) #a						/**< Helper for #STRINGIFY */
   1.411 +#define STRINGIFY(a) STRINGIFY2(a)				/**< Convert \a a into a quoted string */
   1.412 +#define CASE_CAT_NAME(name) case BTrace::name: return STRINGIFY(name)
   1.413 +
   1.414 +const char* CategoryName(TUint8 aCategory)
   1.415 +	{
   1.416 +	switch((BTrace::TCategory)aCategory)
   1.417 +		{
   1.418 +		CASE_CAT_NAME(ERDebugPrintf);
   1.419 +		CASE_CAT_NAME(EKernPrintf);
   1.420 +		CASE_CAT_NAME(EPlatsecPrintf);
   1.421 +		case BTrace::EThreadIdentification: return "EThreadId"; //	CASE_CAT_NAME(EThreadIdentification)
   1.422 +		CASE_CAT_NAME(ECpuUsage);
   1.423 +    	CASE_CAT_NAME(EKernPerfLog);
   1.424 +    	CASE_CAT_NAME(EClientServer);
   1.425 +    	CASE_CAT_NAME(ERequests);
   1.426 +    	CASE_CAT_NAME(EChunks);
   1.427 +    	CASE_CAT_NAME(ECodeSegs);
   1.428 +		CASE_CAT_NAME(EPaging);
   1.429 +		CASE_CAT_NAME(EThreadPriority);
   1.430 +		CASE_CAT_NAME(EPagingMedia);
   1.431 +		CASE_CAT_NAME(EKernelMemory);
   1.432 +		CASE_CAT_NAME(EHeap);
   1.433 +		CASE_CAT_NAME(EMetaTrace);
   1.434 +
   1.435 +		CASE_CAT_NAME(EFastMutex);
   1.436 +		CASE_CAT_NAME(EProfiling);
   1.437 +		CASE_CAT_NAME(ESymbianKernelSync);
   1.438 +		CASE_CAT_NAME(EFlexibleMemModel);
   1.439 +		CASE_CAT_NAME(ETest1);
   1.440 +		CASE_CAT_NAME(ETest2);
   1.441 +		default:
   1.442 +			break;
   1.443 +		}
   1.444 +	return UnknownNames[aCategory];
   1.445 +	}
   1.446 +
   1.447 +const char* SubCategoryName(TUint8 aCategory, TUint8 aSubCategory)
   1.448 +	{
   1.449 +	switch(aCategory)
   1.450 +		{
   1.451 +	case BTrace::ERDebugPrintf:
   1.452 +	case BTrace::EKernPrintf:
   1.453 +	case BTrace::EPlatsecPrintf:
   1.454 +		return ""; // no subcategories for these
   1.455 +
   1.456 +	case BTrace::EThreadIdentification:
   1.457 +		switch((BTrace::TThreadIdentification)aSubCategory)
   1.458 +			{
   1.459 +		CASE_CAT_NAME(ENanoThreadCreate);
   1.460 +		CASE_CAT_NAME(ENanoThreadDestroy);
   1.461 +		CASE_CAT_NAME(EThreadCreate);
   1.462 +		CASE_CAT_NAME(EThreadDestroy);
   1.463 +		CASE_CAT_NAME(EThreadName);
   1.464 +		CASE_CAT_NAME(EProcessName);
   1.465 +		CASE_CAT_NAME(EThreadId);
   1.466 +		CASE_CAT_NAME(EProcessCreate);
   1.467 +		CASE_CAT_NAME(EProcessDestroy);
   1.468 +			}
   1.469 +		break;
   1.470 +
   1.471 +	case BTrace::ECpuUsage:
   1.472 +		switch((BTrace::TCpuUsage)aSubCategory)
   1.473 +			{
   1.474 +		CASE_CAT_NAME(EIrqStart);
   1.475 +		CASE_CAT_NAME(EIrqEnd);
   1.476 +		CASE_CAT_NAME(EFiqStart);
   1.477 +		CASE_CAT_NAME(EFiqEnd);
   1.478 +		CASE_CAT_NAME(EIDFCStart);
   1.479 +		CASE_CAT_NAME(EIDFCEnd);
   1.480 +		CASE_CAT_NAME(ENewThreadContext);
   1.481 +			}
   1.482 +		break;
   1.483 +
   1.484 +	case BTrace::EChunks:
   1.485 +		switch((BTrace::TChunks)aSubCategory)
   1.486 +			{
   1.487 +		CASE_CAT_NAME(EChunkCreated);
   1.488 +		CASE_CAT_NAME(EChunkInfo);
   1.489 +		CASE_CAT_NAME(EChunkDestroyed);
   1.490 +		CASE_CAT_NAME(EChunkMemoryAllocated);
   1.491 +		CASE_CAT_NAME(EChunkMemoryDeallocated);
   1.492 +		CASE_CAT_NAME(EChunkMemoryAdded);
   1.493 +		CASE_CAT_NAME(EChunkMemoryRemoved);
   1.494 +		CASE_CAT_NAME(EChunkOwner);
   1.495 +			}
   1.496 +		break;
   1.497 +
   1.498 +	case BTrace::ECodeSegs:
   1.499 +		switch((BTrace::TCodeSegs)aSubCategory)
   1.500 +			{
   1.501 +		CASE_CAT_NAME(ECodeSegCreated);
   1.502 +		CASE_CAT_NAME(ECodeSegInfo);
   1.503 +		CASE_CAT_NAME(ECodeSegDestroyed);
   1.504 +		CASE_CAT_NAME(ECodeSegMapped);
   1.505 +		CASE_CAT_NAME(ECodeSegUnmapped);
   1.506 +		CASE_CAT_NAME(ECodeSegMemoryAllocated);
   1.507 +		CASE_CAT_NAME(ECodeSegMemoryDeallocated);
   1.508 +			}
   1.509 +		break;
   1.510 +		
   1.511 +	case BTrace::EPaging:
   1.512 +		switch((BTrace::TPaging)aSubCategory)
   1.513 +			{
   1.514 +		CASE_CAT_NAME(EPagingPageInBegin);
   1.515 +		CASE_CAT_NAME(EPagingPageInUnneeded);
   1.516 +		CASE_CAT_NAME(EPagingPageInROM);
   1.517 +		CASE_CAT_NAME(EPagingPageOutROM);
   1.518 +		CASE_CAT_NAME(EPagingPageInFree);
   1.519 +		CASE_CAT_NAME(EPagingPageOutFree);
   1.520 +		CASE_CAT_NAME(EPagingRejuvenate);
   1.521 +		CASE_CAT_NAME(EPagingPageNop);
   1.522 +		CASE_CAT_NAME(EPagingPageLock);
   1.523 +		CASE_CAT_NAME(EPagingPageUnlock);
   1.524 +		CASE_CAT_NAME(EPagingPageOutCache);
   1.525 +		CASE_CAT_NAME(EPagingPageInCode);
   1.526 +		CASE_CAT_NAME(EPagingPageOutCode);
   1.527 +		CASE_CAT_NAME(EPagingMapCode);
   1.528 +		CASE_CAT_NAME(EPagingAged);
   1.529 +		CASE_CAT_NAME(EPagingDecompressStart);
   1.530 +		CASE_CAT_NAME(EPagingDecompressEnd);
   1.531 +		CASE_CAT_NAME(EPagingMemoryModel);
   1.532 +		CASE_CAT_NAME(EPagingChunkDonatePage);
   1.533 +		CASE_CAT_NAME(EPagingChunkReclaimPage);
   1.534 +		CASE_CAT_NAME(EPagingPageIn);
   1.535 +		CASE_CAT_NAME(EPagingPageOut);
   1.536 +		CASE_CAT_NAME(EPagingMapPage);
   1.537 +		CASE_CAT_NAME(EPagingDonatePage);
   1.538 +		CASE_CAT_NAME(EPagingReclaimPage);
   1.539 +		CASE_CAT_NAME(EPagingAgedClean);
   1.540 +		CASE_CAT_NAME(EPagingAgedDirty);
   1.541 +		CASE_CAT_NAME(EPagingPageTableAlloc);
   1.542 +			}
   1.543 +		break;
   1.544 +
   1.545 +	case BTrace::EKernelMemory:
   1.546 +		switch((BTrace::TKernelMemory)aSubCategory)
   1.547 +			{
   1.548 +		CASE_CAT_NAME(EKernelMemoryInitialFree);
   1.549 +		CASE_CAT_NAME(EKernelMemoryCurrentFree);
   1.550 +		CASE_CAT_NAME(EKernelMemoryMiscAlloc);
   1.551 +		CASE_CAT_NAME(EKernelMemoryMiscFree);
   1.552 +		CASE_CAT_NAME(EKernelMemoryDemandPagingCache);
   1.553 +		CASE_CAT_NAME(EKernelMemoryDrvPhysAlloc);
   1.554 +		CASE_CAT_NAME(EKernelMemoryDrvPhysFree);
   1.555 +			}
   1.556 +		break;
   1.557 +
   1.558 +	case BTrace::EMetaTrace:
   1.559 +		{
   1.560 +		if(aSubCategory==KJunkTraceSubcategory)
   1.561 +			return "*JUNK*";
   1.562 +		else
   1.563 +			{
   1.564 +			switch((BTrace::TMetaTrace)aSubCategory)
   1.565 +				{
   1.566 +			CASE_CAT_NAME(EMetaTraceTimestampsInfo);
   1.567 +			CASE_CAT_NAME(EMetaTraceMeasurementStart);
   1.568 +			CASE_CAT_NAME(EMetaTraceMeasurementEnd);
   1.569 +			CASE_CAT_NAME(EMetaTraceFilterChange);
   1.570 +				}
   1.571 +			}
   1.572 +		}
   1.573 +		break;
   1.574 +
   1.575 +	case BTrace::EFastMutex:
   1.576 +		switch((BTrace::TFastMutex)aSubCategory)
   1.577 +			{
   1.578 +		CASE_CAT_NAME(EFastMutexWait);
   1.579 +		CASE_CAT_NAME(EFastMutexSignal);
   1.580 +		CASE_CAT_NAME(EFastMutexFlash);
   1.581 +		CASE_CAT_NAME(EFastMutexName);
   1.582 +		CASE_CAT_NAME(EFastMutexBlock);
   1.583 +			}
   1.584 +		break;
   1.585 +
   1.586 +	case BTrace::EProfiling:
   1.587 +		switch((BTrace::TProfiling)aSubCategory)
   1.588 +			{
   1.589 +		CASE_CAT_NAME(ECpuFullSample);
   1.590 +		CASE_CAT_NAME(ECpuOptimisedSample);
   1.591 +		CASE_CAT_NAME(ECpuIdfcSample);
   1.592 +		CASE_CAT_NAME(ECpuNonSymbianThreadSample);
   1.593 +			}
   1.594 +		break;
   1.595 +
   1.596 +	case BTrace::ESymbianKernelSync:
   1.597 +		switch((BTrace::TSymbianKernelSync)aSubCategory)
   1.598 +			{
   1.599 +		CASE_CAT_NAME(ESemaphoreCreate);
   1.600 +		CASE_CAT_NAME(ESemaphoreDestroy);
   1.601 +		CASE_CAT_NAME(ESemaphoreAcquire);
   1.602 +		CASE_CAT_NAME(ESemaphoreRelease);
   1.603 +		CASE_CAT_NAME(ESemaphoreBlock);
   1.604 +		CASE_CAT_NAME(EMutexCreate);
   1.605 +		CASE_CAT_NAME(EMutexDestroy);
   1.606 +		CASE_CAT_NAME(EMutexAcquire);
   1.607 +		CASE_CAT_NAME(EMutexRelease);
   1.608 +		CASE_CAT_NAME(EMutexBlock);
   1.609 +		CASE_CAT_NAME(ECondVarCreate);
   1.610 +		CASE_CAT_NAME(ECondVarDestroy);
   1.611 +		CASE_CAT_NAME(ECondVarBlock);
   1.612 +		CASE_CAT_NAME(ECondVarWakeUp);
   1.613 +		CASE_CAT_NAME(ECondVarSignal);
   1.614 +		CASE_CAT_NAME(ECondVarBroadcast);
   1.615 +			}
   1.616 +		break;
   1.617 +
   1.618 +	case BTrace::EFlexibleMemModel:
   1.619 +		switch((BTrace::TFlexibleMemModel)aSubCategory)
   1.620 +			{
   1.621 +		CASE_CAT_NAME(EMemoryObjectCreate);
   1.622 +		CASE_CAT_NAME(EMemoryObjectDestroy);
   1.623 +		CASE_CAT_NAME(EMemoryMappingCreate);
   1.624 +		CASE_CAT_NAME(EMemoryMappingDestroy);
   1.625 +		CASE_CAT_NAME(EMemoryObjectIsChunk);
   1.626 +		CASE_CAT_NAME(EMemoryObjectIsCodeSeg);
   1.627 +		CASE_CAT_NAME(EMemoryObjectIsProcessStaticData);
   1.628 +		CASE_CAT_NAME(EMemoryObjectIsDllStaticData);
   1.629 +		CASE_CAT_NAME(EMemoryObjectIsSupervisorStack);
   1.630 +		CASE_CAT_NAME(EMemoryObjectIsUserStack);
   1.631 +		CASE_CAT_NAME(EAddressSpaceId);
   1.632 +			}
   1.633 +		break;
   1.634 +
   1.635 +		}
   1.636 +	return UnknownNames[aSubCategory];
   1.637 +	}
   1.638 +
   1.639 +
   1.640 +
   1.641 +//
   1.642 +// Data structures
   1.643 +//
   1.644 +
   1.645 +enum TDataType
   1.646 +	{
   1.647 +	EDataTypeNone = 0,
   1.648 +	EDataTypeText,
   1.649 +	EDataTypeObject,
   1.650 +	};
   1.651 +
   1.652 +class Thread;
   1.653 +class Cpu;
   1.654 +
   1.655 +struct TraceHeader
   1.656 +	{
   1.657 +	TUint8	iCpuNum;
   1.658 +	TUint8	iCategory;
   1.659 +	TUint8	iSubCategory;
   1.660 +	TUint8	iFlags;
   1.661 +	TUint32	iHeader2;
   1.662 +	TUint64	iTimestamp;
   1.663 +	TUint32	iTimestamp2;
   1.664 +	Thread*	iContextID;
   1.665 +	TUint32	iPC;
   1.666 +	TUint32	iExtra;
   1.667 +	TUint8	iDataTypes[4];
   1.668 +	TUint32	iCalculatedData[2];
   1.669 +	TUint	iDataSize;
   1.670 +	Cpu*	iCpu;
   1.671 +	TUint32	iError;
   1.672 +	};
   1.673 +
   1.674 +
   1.675 +struct TraceRecord : public TraceHeader
   1.676 +	{
   1.677 +	TUint32 iData[(8+KMaxBTraceDataArray)/4];
   1.678 +	};
   1.679 +
   1.680 +
   1.681 +
   1.682 +//
   1.683 +// ECpuUsage traces
   1.684 +//
   1.685 +
   1.686 +enum TContext
   1.687 +	{
   1.688 +	EContextThread,
   1.689 +	EContextFiq,
   1.690 +	EContextIrq,
   1.691 +	EContextIDFC,
   1.692 +	EContextUnknown
   1.693 +	};
   1.694 +
   1.695 +class Cpu
   1.696 +	{
   1.697 +public:
   1.698 +	Cpu();
   1.699 +	void ChangeContext(TContext aType, Thread* aThread=0);
   1.700 +	void Reset();
   1.701 +
   1.702 +	TContext	iCurrentContext;
   1.703 +	TInt		iFiqNest;
   1.704 +	TInt		iIrqNest;
   1.705 +	TInt		iIDFCNest;
   1.706 +	TUint64		iFiqTime;
   1.707 +	TUint64		iIrqTime;
   1.708 +	TUint64		iIDFCTime;
   1.709 +	Thread*		iCurrentThread;
   1.710 +	TUint64		iBaseTimestamp;
   1.711 +	};
   1.712 +
   1.713 +//
   1.714 +// Objects
   1.715 +//
   1.716 +
   1.717 +const TUint KMaxTraceNameLength = 10;
   1.718 +
   1.719 +class Object
   1.720 +	{
   1.721 +public:
   1.722 +	Object(TUint32 aTraceId, const char* aTraceNamePrefix)
   1.723 +		: iTraceId(aTraceId), iIndex(~0u), iOwner(0), iOwnerTraceId(0), iAlive(1), iNameSet(false), iNameLength(0),
   1.724 +		  iTraceNamePrefix(aTraceNamePrefix)
   1.725 +		{
   1.726 +		iName[0] = 0;
   1.727 +		}
   1.728 +
   1.729 +	void Destroy()
   1.730 +		{
   1.731 +		if(iAlive)
   1.732 +			--iAlive;
   1.733 +		if(iOwnerTraceId && !iOwner)
   1.734 +			--UnknownOwners;
   1.735 +		}
   1.736 +
   1.737 +	virtual ~Object()
   1.738 +		{}
   1.739 +
   1.740 +	void SetName(void* aName, TUint aLength)
   1.741 +		{
   1.742 +		ASSERT(aLength<sizeof(iName));
   1.743 +		iNameLength = (TUint8)aLength;
   1.744 +		memcpy(iName,aName,aLength);
   1.745 +		iName[aLength] = 0;
   1.746 +		iNameSet = true;
   1.747 +		}
   1.748 +
   1.749 +	void SetName(TraceRecord& aTrace, TUint aIndex)
   1.750 +		{
   1.751 +		SetName(aTrace.iData+aIndex,aTrace.iDataSize-aIndex*4);
   1.752 +		aTrace.iDataTypes[aIndex] = EDataTypeText;
   1.753 +		}
   1.754 +
   1.755 +	TBool IsName(void* aName, TUint aLength)
   1.756 +		{
   1.757 +		if(aLength!=iNameLength)
   1.758 +			return false;
   1.759 +		while(aLength--)
   1.760 +			if(iName[aLength]!=((TUint8*)aName)[aLength])
   1.761 +				return false;
   1.762 +		return true;
   1.763 +		}
   1.764 +
   1.765 +	typedef TUint8 TraceNameBuf[KMaxTraceNameLength+1];
   1.766 +	typedef TUint8 FullNameBuf[KMaxBTraceDataArray+2+KMaxBTraceDataArray+2+KMaxBTraceDataArray+1]; // space for name1::name2::name3[tracename]
   1.767 +	typedef TUint8 FullTraceNameBuf[KMaxBTraceDataArray+1+KMaxBTraceDataArray+2+KMaxBTraceDataArray+KMaxTraceNameLength+1+1]; // space for [tracename]'name1::name2::name3'
   1.768 +
   1.769 +	TUint FullName(FullNameBuf& aName)
   1.770 +		{
   1.771 +		TUint length = 0;
   1.772 +		if(iOwner)
   1.773 +			{
   1.774 +			if(iOwner->iOwner)
   1.775 +				{
   1.776 +				memcpy(aName+length,iOwner->iOwner->iName,iOwner->iOwner->iNameLength);
   1.777 +				length += iOwner->iOwner->iNameLength;
   1.778 +				aName[length++] = ':';
   1.779 +				aName[length++] = ':';
   1.780 +				}
   1.781 +			memcpy(aName+length,iOwner->iName,iOwner->iNameLength);
   1.782 +			length += iOwner->iNameLength;
   1.783 +			aName[length++] = ':';
   1.784 +			aName[length++] = ':';
   1.785 +			}
   1.786 +		memcpy(aName+length,iName,iNameLength);
   1.787 +		length += iNameLength;
   1.788 +		aName[length] = 0;
   1.789 +		return length;
   1.790 +		}
   1.791 +
   1.792 +	TUint TraceName(TraceNameBuf& aName)
   1.793 +		{
   1.794 +		TInt i = 0;
   1.795 +		const TUint KNumDigits = KMaxTraceNameLength-4;
   1.796 +		aName[i++] = '<';
   1.797 +		const char* prefix = iTraceNamePrefix;
   1.798 +		if(prefix[0])
   1.799 +			aName[i++] = *prefix++;
   1.800 +		if(prefix[0])
   1.801 +			aName[i++] = *prefix++;
   1.802 +		TUint n = iIndex;
   1.803 +		for(TUint d=KNumDigits; d>0; --d)
   1.804 +			{
   1.805 +			aName[i+d-1] = TUint8('0'+(n%10));
   1.806 +			n /= 10;
   1.807 +			}
   1.808 +		i += KNumDigits;
   1.809 +		aName[i++] = '>';
   1.810 +		aName[i] = 0;
   1.811 +		return i;
   1.812 +		}
   1.813 +
   1.814 +	TUint FullTraceName(FullTraceNameBuf& aName)
   1.815 +		{
   1.816 +		TUint l1 = TraceName(*(TraceNameBuf*)aName);
   1.817 +		aName[l1++] = '\'';
   1.818 +		TUint l2 = FullName(*(FullNameBuf*)(aName+l1));
   1.819 +		aName[l1+l2++] = '\'';
   1.820 +		aName[l1+l2] = 0;
   1.821 +		return l1+l2;
   1.822 +		}
   1.823 +
   1.824 +public:
   1.825 +	TUint32 iTraceId;					///< ID for object as found in raw trace data.
   1.826 +	TUint iIndex;						///< Index into container for this object.
   1.827 +	Object* iOwner;						///< Object which 'owns' this one, e.g. process which owns a thread.
   1.828 +	TUint32 iOwnerTraceId;				///< Trace ID for owner if owner object as yet unknown
   1.829 +	TUint8 iAlive;						///< True if object destroyed trace not yet parsed.
   1.830 +	TUint8 iNameSet;					///< True if name has been set.
   1.831 +	TUint8 iNameLength;				
   1.832 +	TUint8 iName[KMaxBTraceDataArray+1];	
   1.833 +	const char* iTraceNamePrefix;
   1.834 +public:
   1.835 +	static TUint32 UnknownOwners;
   1.836 +	};
   1.837 +TUint32 Object::UnknownOwners = 0;
   1.838 +
   1.839 +
   1.840 +class ObjectContainer
   1.841 +	{
   1.842 +public:
   1.843 +	ObjectContainer()
   1.844 +		: iNumEntries(0), iEntriesLength(0) , iEntries(0)
   1.845 +		{
   1.846 +		iLink = iAllContainers;
   1.847 +		iAllContainers = this;
   1.848 +		}
   1.849 +
   1.850 +	static void Reset()
   1.851 +		{
   1.852 +		ObjectContainer* container = iAllContainers;
   1.853 +		while(container)
   1.854 +			{
   1.855 +			TUint i = container->iNumEntries;
   1.856 +			while(i--)
   1.857 +				free(container->iEntries[i].iItem);
   1.858 +			free(container->iEntries);
   1.859 +			container->iEntries = 0;
   1.860 +			container->iNumEntries = 0;
   1.861 +			container->iEntriesLength = 0;
   1.862 +			container = container->iLink;
   1.863 +			}
   1.864 +		}
   1.865 +
   1.866 +	void Add(Object* aObject)
   1.867 +		{
   1.868 +		if(iNumEntries>=iEntriesLength)
   1.869 +			{
   1.870 +			iEntriesLength += 128;
   1.871 +			iEntries = (Entry*)realloc(iEntries,iEntriesLength*sizeof(Entry));
   1.872 +			ASSERT(iEntries);
   1.873 +			}
   1.874 +		aObject->iIndex = iNumEntries;
   1.875 +		Entry& entry = iEntries[iNumEntries++];
   1.876 +		entry.iTraceId = aObject->iTraceId;
   1.877 +		entry.iItem = aObject;
   1.878 +		}
   1.879 +
   1.880 +	TUint Count()
   1.881 +		{
   1.882 +		return iNumEntries;
   1.883 +		}
   1.884 +
   1.885 +	Object* operator[](TInt aIndex)
   1.886 +		{
   1.887 +		if(TUint(aIndex)<iNumEntries)
   1.888 +			return iEntries[aIndex].iItem;
   1.889 +		ASSERT(0);
   1.890 +		return 0;
   1.891 +		}
   1.892 +
   1.893 +	Object* Find(TUint32 aTraceId)
   1.894 +		{
   1.895 +		Entry* ptr = iEntries+iNumEntries;
   1.896 +		Entry* end = iEntries;
   1.897 +		while(ptr>end)
   1.898 +			{
   1.899 +			--ptr;
   1.900 +			if(ptr->iTraceId==aTraceId)
   1.901 +				{
   1.902 +				if(ptr->iItem->iAlive)
   1.903 +					return ptr->iItem;
   1.904 +				else
   1.905 +					break;
   1.906 +				}
   1.907 +			}
   1.908 +		return 0;
   1.909 +		}
   1.910 +private:
   1.911 +	struct Entry
   1.912 +		{
   1.913 +		TUint32 iTraceId;
   1.914 +		Object* iItem;
   1.915 +		};
   1.916 +	TUint iNumEntries;
   1.917 +	TUint iEntriesLength;
   1.918 +	Entry* iEntries;
   1.919 +	ObjectContainer* iLink;
   1.920 +
   1.921 +	static ObjectContainer* iAllContainers;
   1.922 +	};
   1.923 +ObjectContainer* ObjectContainer::iAllContainers = 0;
   1.924 +
   1.925 +
   1.926 +#define GENERIC_OBJECT_DEFINITIONS(C)							\
   1.927 +																\
   1.928 +	static C* Find(TUint32 aTraceId)							\
   1.929 +		{														\
   1.930 +		return (C*)iContainer.Find(aTraceId);					\
   1.931 +		}														\
   1.932 +																\
   1.933 +	static C* Create(TraceRecord& aTrace, TUint aIndex)			\
   1.934 +		{														\
   1.935 +		TUint32 traceId = aTrace.iData[aIndex];					\
   1.936 +		C* object = new C(traceId);								\
   1.937 +		aTrace.iDataTypes[aIndex] = EDataTypeObject;			\
   1.938 +		aTrace.iData[aIndex] = (uintptr_t)object;				\
   1.939 +		return object;											\
   1.940 +		}														\
   1.941 +																\
   1.942 +	static C* Find(TraceRecord& aTrace, TUint aIndex)			\
   1.943 +		{														\
   1.944 +		TUint32 traceId = aTrace.iData[aIndex];					\
   1.945 +		C* object = Find(traceId);								\
   1.946 +		if(!object)												\
   1.947 +			return 0;											\
   1.948 +		aTrace.iDataTypes[aIndex] = EDataTypeObject;			\
   1.949 +		aTrace.iData[aIndex] = (uintptr_t)object;				\
   1.950 +		return object;											\
   1.951 +		}														\
   1.952 +																\
   1.953 +	static C* FindOrCreate(TraceRecord& aTrace, TUint aIndex)	\
   1.954 +		{														\
   1.955 +		C* object = Find(aTrace,aIndex);						\
   1.956 +		if(!object)												\
   1.957 +			object = Create(aTrace,aIndex);						\
   1.958 +		return object;											\
   1.959 +		}
   1.960 +
   1.961 +
   1.962 +
   1.963 +//
   1.964 +// Process
   1.965 +//
   1.966 +
   1.967 +class Process : public Object
   1.968 +	{
   1.969 +public:
   1.970 +	Process(TUint32 aTraceId)
   1.971 +		: Object(aTraceId,"P"), iThreadCount(0), iMaxThreadCount(0)
   1.972 +		{
   1.973 +		iContainer.Add(this);
   1.974 +		}
   1.975 +
   1.976 +	GENERIC_OBJECT_DEFINITIONS(Process);
   1.977 +
   1.978 +public:
   1.979 +	TUint iThreadCount;
   1.980 +	TUint iMaxThreadCount;
   1.981 +
   1.982 +	static ObjectContainer iContainer;
   1.983 +	};
   1.984 +ObjectContainer Process::iContainer;
   1.985 +
   1.986 +
   1.987 +
   1.988 +//
   1.989 +// Thread
   1.990 +//
   1.991 +class FastMutex;
   1.992 +class Thread : public Object
   1.993 +	{
   1.994 +public:
   1.995 +	Thread(TUint32 aTraceId)
   1.996 +		: Object(aTraceId,"T"), iId(~0u), iCpuTime(0), iSamples(0)
   1.997 +		{
   1.998 +		iContainer.Add(this);
   1.999 +		iNameLength = (TUint8)MakeName(iName,"NThread-",aTraceId);
  1.1000 +		}
  1.1001 +
  1.1002 +	TUint64 CpuTime()
  1.1003 +		{
  1.1004 +		if(!iLastCpu || !iLastCpu->iBaseTimestamp)
  1.1005 +			return 0;
  1.1006 +		if(iLastCpu->iCurrentThread==this)
  1.1007 +			return iCpuTime + Timestamp - iLastCpu->iBaseTimestamp;
  1.1008 +		return iCpuTime;
  1.1009 +		}
  1.1010 +
  1.1011 +	void Sampled()
  1.1012 +		{
  1.1013 +		if( iSamples+1 != 0xFFFFFFFF)
  1.1014 +			{
  1.1015 +			iSamples++;
  1.1016 +			}
  1.1017 +		}
  1.1018 +
  1.1019 +	GENERIC_OBJECT_DEFINITIONS(Thread);
  1.1020 +
  1.1021 +	static Object* FindThreadOrProcess(TraceRecord& aTrace, TUint aIndex)
  1.1022 +		{
  1.1023 +		if (!aTrace.iData[aIndex])
  1.1024 +			return 0;
  1.1025 +		Object* p = Find(aTrace, aIndex);
  1.1026 +		if (!p)
  1.1027 +			p = Process::Find(aTrace, aIndex);
  1.1028 +		return p;
  1.1029 +		}
  1.1030 +public:
  1.1031 +	TUint32 iId;
  1.1032 +	Cpu* iLastCpu;
  1.1033 +	TUint64 iCpuTime;
  1.1034 +	TUint64 iFMBlockStartTime;
  1.1035 +	FastMutex* iWaitFastMutex;
  1.1036 +
  1.1037 +	// Number of profiling samples
  1.1038 +	TUint32 iSamples;
  1.1039 +
  1.1040 +	static ObjectContainer iContainer;
  1.1041 +	};
  1.1042 +
  1.1043 +ObjectContainer Thread::iContainer;
  1.1044 +
  1.1045 +
  1.1046 +
  1.1047 +//
  1.1048 +// Chunk
  1.1049 +//
  1.1050 +
  1.1051 +TUint ChunkErrors = 0;
  1.1052 +
  1.1053 +const TUint KPageShift = 12; // chunk memory is allocated in 4kB pages
  1.1054 +
  1.1055 +class Chunk : public Object
  1.1056 +	{
  1.1057 +public:
  1.1058 +	Chunk(TUint32 aTraceId)
  1.1059 +		: Object(aTraceId,"C"), iCurrentSize(0), iPeakSize(0), iMaxSize(0), iPageMap(0), iTraceErrors(0)
  1.1060 +		{
  1.1061 +		iContainer.Add(this);
  1.1062 +		}
  1.1063 +
  1.1064 +	~Chunk()
  1.1065 +		{
  1.1066 +		free(iPageMap);
  1.1067 +		}
  1.1068 +
  1.1069 +	void SetMaxSize(TUint32 aMaxSize)
  1.1070 +		{
  1.1071 +		ASSERT(!iMaxSize);
  1.1072 +		iMaxSize = aMaxSize;
  1.1073 +		TUint mapSize = ((aMaxSize>>KPageShift)+7)>>3;
  1.1074 +		iPageMap = (TUint8*)malloc(mapSize);
  1.1075 +		ASSERT(iPageMap);
  1.1076 +		memset(iPageMap,0,mapSize);
  1.1077 +		iCurrentSize = 0;
  1.1078 +		}
  1.1079 +
  1.1080 +	void Commit(TUint32 aStart,TUint32 aSize)
  1.1081 +		{
  1.1082 +		if(!iPageMap) // we havent been intialised yet
  1.1083 +			return;
  1.1084 +
  1.1085 +		if(aStart+aSize<aStart || aStart+aSize>iMaxSize)
  1.1086 +			{
  1.1087 +			++iTraceErrors;
  1.1088 +			++ChunkErrors;
  1.1089 +			return;
  1.1090 +			}
  1.1091 +		if(SetBits(iPageMap,aStart>>KPageShift,aSize>>KPageShift))
  1.1092 +			{
  1.1093 +			++iTraceErrors;
  1.1094 +			++ChunkErrors;
  1.1095 +			ErrorOnThisTrace = true;
  1.1096 +			}
  1.1097 +		}
  1.1098 +
  1.1099 +	void Decommit(TUint32 aStart,TUint32 aSize)
  1.1100 +		{
  1.1101 +		if(!iPageMap) // we havent been intialised yet
  1.1102 +			return;
  1.1103 +
  1.1104 +		// Decommit is complicated by the fact that aSize is the number of pages
  1.1105 +		// actually decommited, which may be less than the region of the original
  1.1106 +		// chunk decommit operation. E.g. if pages 1 and 3 were originally decommited
  1.1107 +		// and the decommit operation was for pages 0-3, then the trace has a size of
  1.1108 +		// 2 pages, even though the operation was on 4 pages.
  1.1109 +		// We handle this, repeatedly decommiting from our iPageMap, until we have
  1.1110 +		// freed aSize bytes worth of pages...
  1.1111 +		while(aSize)
  1.1112 +			{
  1.1113 +			if(aStart+aSize<aStart || aStart+aSize>iMaxSize)
  1.1114 +				{
  1.1115 +				// we haven't found enough memory to decommit
  1.1116 +				++iTraceErrors;
  1.1117 +				++ChunkErrors;
  1.1118 +				ErrorOnThisTrace = true;
  1.1119 +				return;
  1.1120 +				}
  1.1121 +			TUint notDecommitted = ClearBits(iPageMap,aStart>>KPageShift,aSize>>KPageShift);
  1.1122 +			aStart += aSize;
  1.1123 +			aSize = notDecommitted<<KPageShift;
  1.1124 +			}
  1.1125 +		}
  1.1126 +
  1.1127 +	void ResetMemory()
  1.1128 +		{
  1.1129 +		}
  1.1130 +
  1.1131 +	GENERIC_OBJECT_DEFINITIONS(Chunk);
  1.1132 +
  1.1133 +public:
  1.1134 +	TUint32 iCurrentSize;
  1.1135 +	TUint32 iPeakSize;
  1.1136 +	TUint32 iMaxSize;
  1.1137 +	TUint8* iPageMap;
  1.1138 +	TUint iTraceErrors;
  1.1139 +
  1.1140 +	static ObjectContainer iContainer;
  1.1141 +	};
  1.1142 +ObjectContainer Chunk::iContainer;
  1.1143 +
  1.1144 +
  1.1145 +
  1.1146 +//
  1.1147 +// Semaphore, Mutex, CondVar
  1.1148 +//
  1.1149 +class Semaphore : public Object
  1.1150 +	{
  1.1151 +public:
  1.1152 +	Semaphore(TUint32 aTraceId)
  1.1153 +		: Object(aTraceId,"S")
  1.1154 +		{
  1.1155 +		iContainer.Add(this);
  1.1156 +		}
  1.1157 +
  1.1158 +	~Semaphore()
  1.1159 +		{
  1.1160 +		}
  1.1161 +
  1.1162 +	GENERIC_OBJECT_DEFINITIONS(Semaphore);
  1.1163 +public:
  1.1164 +
  1.1165 +	static ObjectContainer iContainer;
  1.1166 +	};
  1.1167 +ObjectContainer Semaphore::iContainer;
  1.1168 +
  1.1169 +
  1.1170 +class Mutex : public Object
  1.1171 +	{
  1.1172 +public:
  1.1173 +	Mutex(TUint32 aTraceId)
  1.1174 +		: Object(aTraceId,"M")
  1.1175 +		{
  1.1176 +		iContainer.Add(this);
  1.1177 +		}
  1.1178 +
  1.1179 +	~Mutex()
  1.1180 +		{
  1.1181 +		}
  1.1182 +
  1.1183 +	GENERIC_OBJECT_DEFINITIONS(Mutex);
  1.1184 +public:
  1.1185 +
  1.1186 +	static ObjectContainer iContainer;
  1.1187 +	};
  1.1188 +ObjectContainer Mutex::iContainer;
  1.1189 +
  1.1190 +
  1.1191 +class CondVar : public Object
  1.1192 +	{
  1.1193 +public:
  1.1194 +	CondVar(TUint32 aTraceId)
  1.1195 +		: Object(aTraceId,"V")
  1.1196 +		{
  1.1197 +		iContainer.Add(this);
  1.1198 +		}
  1.1199 +
  1.1200 +	~CondVar()
  1.1201 +		{
  1.1202 +		}
  1.1203 +
  1.1204 +	GENERIC_OBJECT_DEFINITIONS(CondVar);
  1.1205 +public:
  1.1206 +
  1.1207 +	static ObjectContainer iContainer;
  1.1208 +	};
  1.1209 +ObjectContainer CondVar::iContainer;
  1.1210 +
  1.1211 +
  1.1212 +
  1.1213 +
  1.1214 +//
  1.1215 +// CodeSeg
  1.1216 +//
  1.1217 +
  1.1218 +TUint CodeSegErrors = 0;
  1.1219 +
  1.1220 +class CodeSeg : public Object
  1.1221 +	{
  1.1222 +public:
  1.1223 +	CodeSeg(TUint32 aTraceId)
  1.1224 +		: Object(aTraceId,"CS"), iAllocatedMemory(0)
  1.1225 +		{
  1.1226 +		iContainer.Add(this);
  1.1227 +		}
  1.1228 +
  1.1229 +	GENERIC_OBJECT_DEFINITIONS(CodeSeg);
  1.1230 +
  1.1231 +	TUint iAllocatedMemory;
  1.1232 +public:
  1.1233 +	static ObjectContainer iContainer;
  1.1234 +	};
  1.1235 +ObjectContainer CodeSeg::iContainer;
  1.1236 +
  1.1237 +
  1.1238 +
  1.1239 +//
  1.1240 +// FastMutex
  1.1241 +//
  1.1242 +
  1.1243 +TUint FastMutexNestErrors = 0;
  1.1244 +
  1.1245 +class FastMutex : public Object
  1.1246 +	{
  1.1247 +public:
  1.1248 +	FastMutex(TUint32 aTraceId)
  1.1249 +		: Object(aTraceId,"FM"), iHoldingThread(0), iHeldCount(0), iTotalHeldTime(0),
  1.1250 +		  iMaxHeldTime(0), iMaxHeldTimestamp(0), iMaxHeldPc(0), iBlockCount(0)
  1.1251 +		{
  1.1252 +		iContainer.Add(this);
  1.1253 +		iNameLength = (TUint8)MakeName(iName,"NFastMutex-",aTraceId);
  1.1254 +		iNameLength = 19;
  1.1255 +		}
  1.1256 +
  1.1257 +	TUint32 Wait(Thread* aThread)
  1.1258 +		{
  1.1259 +		TUint32 time = 0;
  1.1260 +		if(iHoldingThread)
  1.1261 +			{
  1.1262 +			++FastMutexNestErrors;
  1.1263 +			ErrorOnThisTrace = true;
  1.1264 +			}
  1.1265 +		iHoldingThread = aThread;
  1.1266 +		iWaitCpuTimeBase = aThread->CpuTime();
  1.1267 +		if (aThread->iWaitFastMutex == this)
  1.1268 +			{
  1.1269 +			time = (TUint32)(Timestamp - aThread->iFMBlockStartTime);
  1.1270 +			}
  1.1271 +		aThread->iWaitFastMutex = 0;
  1.1272 +		return time;
  1.1273 +		}
  1.1274 +
  1.1275 +	void Block(Thread* aThread)
  1.1276 +		{
  1.1277 +		if (aThread->iWaitFastMutex != this)
  1.1278 +			{
  1.1279 +			aThread->iFMBlockStartTime = Timestamp;
  1.1280 +			aThread->iWaitFastMutex = this;
  1.1281 +			++iBlockCount;
  1.1282 +			}
  1.1283 +		};
  1.1284 +
  1.1285 +	TUint32 Signal(Thread* aThread, TUint32 aPc)
  1.1286 +		{
  1.1287 +		if (!iHoldingThread)	// First record for this mutex so ignore it as don't
  1.1288 +			return 0;			// have waiting thread details
  1.1289 +		
  1.1290 +		if(iHoldingThread!=aThread)
  1.1291 +			{
  1.1292 +			++FastMutexNestErrors;
  1.1293 +			ErrorOnThisTrace = true;
  1.1294 +			iHoldingThread = 0;
  1.1295 +			return 0;
  1.1296 +			}
  1.1297 +		iHoldingThread = 0;
  1.1298 +		TUint64 time = aThread->CpuTime()-iWaitCpuTimeBase;
  1.1299 +		++iHeldCount;
  1.1300 +		iTotalHeldTime += time;
  1.1301 +		if(time>iMaxHeldTime)
  1.1302 +			{
  1.1303 +			iMaxHeldTime = time;
  1.1304 +			iMaxHeldPc = aPc;
  1.1305 +			iMaxHeldTimestamp = Timestamp;
  1.1306 +			}
  1.1307 +		return (TUint32)time;
  1.1308 +		}
  1.1309 +
  1.1310 +	GENERIC_OBJECT_DEFINITIONS(FastMutex);
  1.1311 +
  1.1312 +public:
  1.1313 +	Thread* iHoldingThread;
  1.1314 +	TUint32 iHeldCount;		// number of times mutex acquired
  1.1315 +	TUint64 iTotalHeldTime;
  1.1316 +	TUint64 iWaitCpuTimeBase;
  1.1317 +	TUint64 iMaxHeldTime;
  1.1318 +	TUint64 iMaxHeldTimestamp;
  1.1319 +	TUint32 iMaxHeldPc;
  1.1320 +	TUint32 iBlockCount;	// number of times mutex caused a thread to wait
  1.1321 +
  1.1322 +	static ObjectContainer iContainer;
  1.1323 +	};
  1.1324 +ObjectContainer FastMutex::iContainer;
  1.1325 +
  1.1326 +
  1.1327 +
  1.1328 +
  1.1329 +//
  1.1330 +// ProfilingSample
  1.1331 +//
  1.1332 +
  1.1333 +TUint ProfilingSampleErrors = 0;
  1.1334 +
  1.1335 +class ProfilingSample : public Object
  1.1336 +	{
  1.1337 +public:
  1.1338 +	ProfilingSample(TUint32 aTraceId)
  1.1339 +		: Object(aTraceId,"PS")
  1.1340 +		{
  1.1341 +		iContainer.Add(this);
  1.1342 +		iNameLength = (TUint8)MakeName(iName,"ProfilingSample-",aTraceId);
  1.1343 +		}
  1.1344 +
  1.1345 +	void SetPC( TUint32 aPC )
  1.1346 +		{
  1.1347 +		iPC = aPC;
  1.1348 +		}
  1.1349 +
  1.1350 +	void SetThread( TUint32 aThread )
  1.1351 +		{
  1.1352 +		if( 0 != aThread )
  1.1353 +			iThread = aThread;
  1.1354 +		}
  1.1355 +
  1.1356 +	void SetType(const BTrace::TProfiling aType)
  1.1357 +		{
  1.1358 +		iType = aType;
  1.1359 +		}
  1.1360 +
  1.1361 +	GENERIC_OBJECT_DEFINITIONS(ProfilingSample);
  1.1362 +
  1.1363 +
  1.1364 +public:
  1.1365 +
  1.1366 +	static ObjectContainer iContainer;
  1.1367 +	static Thread* iTopTen[10];
  1.1368 +	static TUint32 iSamples;
  1.1369 +	static TUint32 iLastThread;
  1.1370 +
  1.1371 +	TUint32 iPC;
  1.1372 +	TUint32 iThread;
  1.1373 +	BTrace::TProfiling iType;
  1.1374 +
  1.1375 +	};
  1.1376 +
  1.1377 +TUint32 ProfilingSample::iSamples = 0;
  1.1378 +TUint32 ProfilingSample::iLastThread = 0;
  1.1379 +
  1.1380 +ObjectContainer ProfilingSample::iContainer;
  1.1381 +
  1.1382 +
  1.1383 +//
  1.1384 +// EThreadIdentification traces
  1.1385 +//
  1.1386 +
  1.1387 +void PreProcessThreadIdentification(TraceRecord& aTrace)
  1.1388 +	{
  1.1389 +	Thread* thread;
  1.1390 +	Process* process;
  1.1391 +
  1.1392 +	switch((BTrace::TThreadIdentification)aTrace.iSubCategory)
  1.1393 +		{
  1.1394 +	case BTrace::ENanoThreadCreate:
  1.1395 +		CHECK_TRACE_DATA_WORDS(1);
  1.1396 +		thread = Thread::FindOrCreate(aTrace,0);
  1.1397 +		break;
  1.1398 +
  1.1399 +	case BTrace::ENanoThreadDestroy:
  1.1400 +		CHECK_TRACE_DATA_WORDS(1);
  1.1401 +		thread = Thread::Find(aTrace,0);
  1.1402 +		if(thread)
  1.1403 +			thread->Destroy();
  1.1404 +		break;
  1.1405 +
  1.1406 +	case BTrace::EThreadCreate:
  1.1407 +	case BTrace::EThreadName:
  1.1408 +		CHECK_TRACE_DATA_WORDS(2);
  1.1409 +		thread = Thread::FindOrCreate(aTrace,0);
  1.1410 +		if(aTrace.iSubCategory==BTrace::EThreadCreate)
  1.1411 +			++thread->iAlive; // thread needs destroying twice (ENanoThreadDestroy+EThreadDestroy)
  1.1412 +		process = Process::FindOrCreate(aTrace,1);
  1.1413 +		thread->iOwner = process;
  1.1414 +		++process->iThreadCount;
  1.1415 +		if(process->iThreadCount>process->iMaxThreadCount)
  1.1416 +			process->iMaxThreadCount = process->iThreadCount;
  1.1417 +		thread->SetName(aTrace,2);
  1.1418 +		break;
  1.1419 +
  1.1420 +	case BTrace::EThreadDestroy:
  1.1421 +		CHECK_TRACE_DATA_WORDS(1);
  1.1422 +		thread = Thread::Find(aTrace,0);
  1.1423 +		if(thread)
  1.1424 +			{
  1.1425 +			thread->Destroy();
  1.1426 +			process = (Process*)thread->iOwner;
  1.1427 +			if(process && process->iThreadCount)
  1.1428 +				--process->iThreadCount;
  1.1429 +			}
  1.1430 +		break;
  1.1431 +
  1.1432 +	case BTrace::EProcessName:
  1.1433 +		CHECK_TRACE_DATA_WORDS(2);
  1.1434 +		if(aTrace.iData[0])
  1.1435 +			{
  1.1436 +			thread = Thread::FindOrCreate(aTrace,0);
  1.1437 +			process = Process::Find(aTrace.iData[1]);
  1.1438 +			if(!process || (process->iNameLength && !process->IsName(aTrace.iData+2,aTrace.iDataSize-2*4)))
  1.1439 +				{
  1.1440 +				if(process)
  1.1441 +					process->Destroy();
  1.1442 +				process = Process::Create(aTrace,1); // no existing process, or name different
  1.1443 +				}
  1.1444 +			else
  1.1445 +				process = Process::Find(aTrace,1); // find again (this will update trace data[1])
  1.1446 +			}
  1.1447 +		else
  1.1448 +			process = Process::Find(aTrace,1);
  1.1449 +		if(process)
  1.1450 +			process->SetName(aTrace,2);
  1.1451 +		break;
  1.1452 +
  1.1453 +	case BTrace::EThreadId:
  1.1454 +		CHECK_TRACE_DATA_WORDS(2);
  1.1455 +		thread = Thread::FindOrCreate(aTrace,0);
  1.1456 +		process = Process::FindOrCreate(aTrace,1);
  1.1457 +		thread->iId = aTrace.iData[2];
  1.1458 +		break;
  1.1459 +
  1.1460 +	case BTrace::EProcessCreate:
  1.1461 +		CHECK_TRACE_DATA_WORDS(1);
  1.1462 +		process = Process::FindOrCreate(aTrace,0);
  1.1463 +		break;
  1.1464 +
  1.1465 +	case BTrace::EProcessDestroy:
  1.1466 +		CHECK_TRACE_DATA_WORDS(1);
  1.1467 +		process = Process::FindOrCreate(aTrace,0);
  1.1468 +		if(process)
  1.1469 +			process->Destroy();
  1.1470 +		break;
  1.1471 +
  1.1472 +	default:
  1.1473 +		break;
  1.1474 +		}
  1.1475 +	}
  1.1476 +
  1.1477 +
  1.1478 +//
  1.1479 +// ECpuUsage traces
  1.1480 +//
  1.1481 +
  1.1482 +Cpu TheCpus[KMaxCpus];
  1.1483 +TUint InterruptNestErrors = 0;
  1.1484 +TUint CpuUsagePresent = 0;
  1.1485 +
  1.1486 +Cpu::Cpu()
  1.1487 +	:	iCurrentContext(EContextUnknown),
  1.1488 +		iFiqNest(0),
  1.1489 +		iIrqNest(0),
  1.1490 +		iIDFCNest(0),
  1.1491 +		iFiqTime(0),
  1.1492 +		iIrqTime(0),
  1.1493 +		iIDFCTime(0),
  1.1494 +		iCurrentThread(0),
  1.1495 +		iBaseTimestamp(0)
  1.1496 +	{
  1.1497 +	}
  1.1498 +
  1.1499 +void Cpu::Reset()
  1.1500 +	{
  1.1501 +	iCurrentContext = EContextUnknown;
  1.1502 +	iFiqNest = 0;
  1.1503 +	iIrqNest = 0;
  1.1504 +	iIDFCNest = 0;
  1.1505 +	iCurrentThread = 0;
  1.1506 +	iBaseTimestamp = 0;
  1.1507 +	}
  1.1508 +
  1.1509 +void ResetCpuUsage()
  1.1510 +	{
  1.1511 +	TInt i;
  1.1512 +	for (i=0; i<KMaxCpus; ++i)
  1.1513 +		TheCpus[i].Reset();
  1.1514 +	}
  1.1515 +
  1.1516 +
  1.1517 +void StartCpuUsage()
  1.1518 +	{
  1.1519 +	TInt i;
  1.1520 +	for (i=0; i<KMaxCpus; ++i)
  1.1521 +		new (&TheCpus[i]) Cpu;
  1.1522 +	InterruptNestErrors = 0;
  1.1523 +	}
  1.1524 +
  1.1525 +
  1.1526 +void Cpu::ChangeContext(TContext aType, Thread* aThread)
  1.1527 +	{
  1.1528 +	TUint64 delta = Timestamp-iBaseTimestamp;
  1.1529 +	switch(iCurrentContext)
  1.1530 +		{
  1.1531 +	case EContextThread:
  1.1532 +		iCurrentThread->iCpuTime += delta;
  1.1533 +		break;
  1.1534 +	case EContextFiq:
  1.1535 +		iFiqTime += delta;
  1.1536 +		break;
  1.1537 +	case EContextIrq:
  1.1538 +		iIrqTime += delta;
  1.1539 +		break;
  1.1540 +	case EContextIDFC:
  1.1541 +		iIDFCTime += delta;
  1.1542 +		break;
  1.1543 +	default:
  1.1544 +		break;
  1.1545 +		}
  1.1546 +
  1.1547 +	if(aType==EContextUnknown)
  1.1548 +		{
  1.1549 +		if(iFiqNest)
  1.1550 +			aType = EContextFiq;
  1.1551 +		else if(iIrqNest)
  1.1552 +			aType = EContextIrq;
  1.1553 +		else if(iIDFCNest)
  1.1554 +			aType = EContextIDFC;
  1.1555 +		else
  1.1556 +			{
  1.1557 +			aType = EContextThread;
  1.1558 +			aThread = iCurrentThread;
  1.1559 +			}
  1.1560 +		}
  1.1561 +
  1.1562 +	if(aType==EContextThread && !aThread)
  1.1563 +		{
  1.1564 +		iCurrentContext = EContextUnknown;
  1.1565 +		iBaseTimestamp = 0;
  1.1566 +		return;
  1.1567 +		}
  1.1568 +
  1.1569 +	iCurrentContext = aType;
  1.1570 +	if(aType==EContextThread)
  1.1571 +		{
  1.1572 +		iCurrentThread = aThread;
  1.1573 +		aThread->iLastCpu = this;
  1.1574 +		}
  1.1575 +
  1.1576 +	iBaseTimestamp = Timestamp;
  1.1577 +	}
  1.1578 +
  1.1579 +
  1.1580 +void PreProcessCpuUsage(TraceRecord& aTrace)
  1.1581 +	{
  1.1582 +	CpuUsagePresent = true;
  1.1583 +	Cpu& cpu = *aTrace.iCpu;
  1.1584 +
  1.1585 +	switch((BTrace::TCpuUsage)aTrace.iSubCategory)
  1.1586 +		{
  1.1587 +	case BTrace::EIrqStart:
  1.1588 +		++cpu.iIrqNest;
  1.1589 +		cpu.ChangeContext(EContextIrq);
  1.1590 +		break;
  1.1591 +
  1.1592 +	case BTrace::EFiqStart:
  1.1593 +		++cpu.iFiqNest;
  1.1594 +		cpu.ChangeContext(EContextFiq);
  1.1595 +		break;
  1.1596 +
  1.1597 +	case BTrace::EIDFCStart:
  1.1598 +		if(cpu.iIrqNest+cpu.iFiqNest>1 || cpu.iIDFCNest!=0)
  1.1599 +			{
  1.1600 +			++InterruptNestErrors;
  1.1601 +			ErrorOnThisTrace = true;
  1.1602 +			}
  1.1603 +		cpu.iIrqNest = 0;
  1.1604 +		cpu.iFiqNest = 0;
  1.1605 +		cpu.iIDFCNest = 1;
  1.1606 +		cpu.ChangeContext(EContextIDFC);
  1.1607 +		break;
  1.1608 +
  1.1609 +	case BTrace::EIrqEnd:
  1.1610 +		if(cpu.iIrqNest)
  1.1611 +			--cpu.iIrqNest;
  1.1612 +		else
  1.1613 +			{
  1.1614 +			++InterruptNestErrors;
  1.1615 +			ErrorOnThisTrace = true;
  1.1616 +			}
  1.1617 +		cpu.ChangeContext(EContextUnknown);
  1.1618 +		break;
  1.1619 +
  1.1620 +	case BTrace::EFiqEnd:
  1.1621 +		if(cpu.iFiqNest)
  1.1622 +			--cpu.iFiqNest;
  1.1623 +		else
  1.1624 +			{
  1.1625 +			++InterruptNestErrors;
  1.1626 +			ErrorOnThisTrace = true;
  1.1627 +			}
  1.1628 +		cpu.ChangeContext(EContextUnknown);
  1.1629 +		break;
  1.1630 +
  1.1631 +	case BTrace::EIDFCEnd:
  1.1632 +		if(cpu.iIDFCNest!=1)
  1.1633 +			{
  1.1634 +			++InterruptNestErrors;
  1.1635 +			ErrorOnThisTrace = true;
  1.1636 +			}
  1.1637 +		cpu.iIDFCNest = 0;
  1.1638 +		cpu.ChangeContext(EContextUnknown);
  1.1639 +		break;
  1.1640 +
  1.1641 +	case BTrace::ENewThreadContext:
  1.1642 +		if(cpu.iIrqNest+cpu.iFiqNest>1 || cpu.iIDFCNest!=0)
  1.1643 +			{
  1.1644 +			++InterruptNestErrors;
  1.1645 +			ErrorOnThisTrace = true;
  1.1646 +			}
  1.1647 +		cpu.iIrqNest = 0;
  1.1648 +		cpu.iFiqNest = 0;
  1.1649 +		cpu.iIDFCNest = 0;
  1.1650 +		cpu.ChangeContext(EContextThread,aTrace.iContextID);
  1.1651 +		break;
  1.1652 +		}
  1.1653 +	}
  1.1654 +
  1.1655 +
  1.1656 +void ReportThreads()
  1.1657 +	{
  1.1658 +	TUint numThreads = Thread::iContainer.Count();
  1.1659 +	if(!numThreads)
  1.1660 +		return;
  1.1661 +
  1.1662 +	TUint64 totalTime = 0;
  1.1663 +	printf("\nREPORT: Threads\n\n");
  1.1664 +	WarnIfError(0);
  1.1665 +	printf("%-10s %5s %10s %8s %s\n","","State","CPUTime","TraceId","Name");
  1.1666 +	TUint i;
  1.1667 +	for(i=0; i<numThreads; ++i)
  1.1668 +		{
  1.1669 +		Thread* thread = (Thread*)Thread::iContainer[i];
  1.1670 +		Object::FullNameBuf fullName;
  1.1671 +		thread->FullName(fullName);
  1.1672 +		Object::TraceNameBuf name;
  1.1673 +		thread->TraceName(name);
  1.1674 +		printf("%-10s %5s %10d %08x '%s'\n",name,
  1.1675 +			thread->iAlive?(const char*)"Alive":(const char*)"Dead",
  1.1676 +			(int)Time(thread->iCpuTime),(int)thread->iTraceId,fullName);
  1.1677 +		totalTime += thread->iCpuTime;
  1.1678 +		}
  1.1679 +	for (i=0; i<(TUint)KMaxCpus; ++i)
  1.1680 +		{
  1.1681 +		printf("CPU %1d\n", i);
  1.1682 +		Cpu& cpu = TheCpus[i];
  1.1683 +		printf("%-10s %5s %10d %s\n","FIQ","",(int)Time(cpu.iFiqTime),"");
  1.1684 +		printf("%-10s %5s %10d %s\n","IRQ","",(int)Time(cpu.iIrqTime),"");
  1.1685 +		printf("%-10s %5s %10d %s\n","IDFC","",(int)Time(cpu.iIDFCTime),"");
  1.1686 +		totalTime += cpu.iFiqTime + cpu.iIrqTime + cpu.iIDFCTime;
  1.1687 +		}
  1.1688 +	printf("%-10s %5s ----------\n","","");
  1.1689 +	printf("%-10s %5s %10d\n","","",(int)Time(totalTime));
  1.1690 +	printf("\n");
  1.1691 +	}
  1.1692 +
  1.1693 +
  1.1694 +void ReportProcesses()
  1.1695 +	{
  1.1696 +	TUint numProcesses = Process::iContainer.Count();
  1.1697 +	if(!numProcesses)
  1.1698 +		return;
  1.1699 +
  1.1700 +	printf("\nREPORT: Processes\n\n");
  1.1701 +	WarnIfError(0);
  1.1702 +	printf("%-10s %5s %7s %8s %s\n","","State","Threads","TraceId","Name");
  1.1703 +	TUint i;
  1.1704 +	for(i=0; i<numProcesses; ++i)
  1.1705 +		{
  1.1706 +		Process* process = (Process*)Process::iContainer[i];
  1.1707 +		Object::FullNameBuf fullName;
  1.1708 +		process->FullName(fullName);
  1.1709 +		Object::TraceNameBuf name;
  1.1710 +		process->TraceName(name);
  1.1711 +		printf("%-10s %5s %3u/%-3u %08x '%s'\n",name,
  1.1712 +			process->iAlive?(const char*)"Alive":(const char*)"Dead",
  1.1713 +			(unsigned int)process->iThreadCount,(unsigned int)process->iMaxThreadCount,
  1.1714 +			(unsigned int)process->iTraceId,fullName);
  1.1715 +		}
  1.1716 +	printf("\n");
  1.1717 +	}
  1.1718 +
  1.1719 +
  1.1720 +void EndCpuUsage()
  1.1721 +	{
  1.1722 +	TInt i;
  1.1723 +	for (i=0; i<KMaxCpus; ++i)
  1.1724 +		TheCpus[i].ChangeContext(EContextUnknown);
  1.1725 +	}
  1.1726 +
  1.1727 +
  1.1728 +//
  1.1729 +// EChunks traces
  1.1730 +//
  1.1731 +
  1.1732 +void StartChunks()
  1.1733 +	{
  1.1734 +	ChunkErrors = 0;
  1.1735 +	}
  1.1736 +
  1.1737 +
  1.1738 +void PreProcessChunks(TraceRecord& aTrace)
  1.1739 +	{
  1.1740 +	CHECK_TRACE_DATA_WORDS(1);
  1.1741 +	Chunk* chunk = Chunk::FindOrCreate(aTrace,0);
  1.1742 +
  1.1743 +	switch((BTrace::TChunks)aTrace.iSubCategory)
  1.1744 +		{
  1.1745 +	case BTrace::EChunkCreated:
  1.1746 +		CHECK_TRACE_DATA_WORDS(2);
  1.1747 +		chunk->SetName(aTrace,2);
  1.1748 +		chunk->SetMaxSize(aTrace.iData[1]);
  1.1749 +		// start by assuming thread is 'owned' by the thread which created it...
  1.1750 +		chunk->iOwner = aTrace.iContextID;
  1.1751 +		break;
  1.1752 +
  1.1753 +	case BTrace::EChunkInfo:
  1.1754 +		CHECK_TRACE_DATA_WORDS(3);
  1.1755 +		break; // ignore
  1.1756 +
  1.1757 +	case BTrace::EChunkDestroyed:
  1.1758 +		chunk->Destroy();
  1.1759 +		break;
  1.1760 +
  1.1761 +	case BTrace::EChunkMemoryAllocated:
  1.1762 +		{
  1.1763 +		CHECK_TRACE_DATA_WORDS(3);
  1.1764 +		chunk->Commit(aTrace.iData[1],aTrace.iData[2]);
  1.1765 +		TUint32 size = chunk->iCurrentSize+aTrace.iData[2];
  1.1766 +		if(size<chunk->iCurrentSize || size>chunk->iMaxSize)
  1.1767 +			size = chunk->iMaxSize;
  1.1768 +		chunk->iCurrentSize = size;
  1.1769 +		if(size>chunk->iPeakSize)
  1.1770 +			chunk->iPeakSize = size;
  1.1771 +		aTrace.iCalculatedData[0] = size/1024;
  1.1772 +		}
  1.1773 +		break;
  1.1774 +
  1.1775 +	case BTrace::EChunkMemoryDeallocated:
  1.1776 +		{
  1.1777 +		CHECK_TRACE_DATA_WORDS(3);
  1.1778 +		chunk->Decommit(aTrace.iData[1],aTrace.iData[2]);
  1.1779 +		TUint32 size = chunk->iCurrentSize-aTrace.iData[2];
  1.1780 +		if(size>chunk->iCurrentSize)
  1.1781 +			size = 0;
  1.1782 +		chunk->iCurrentSize = size;
  1.1783 +		aTrace.iCalculatedData[0] = size/1024;
  1.1784 +		}
  1.1785 +		break;
  1.1786 +
  1.1787 +	case BTrace::EChunkMemoryAdded:
  1.1788 +		CHECK_TRACE_DATA_WORDS(3);
  1.1789 +		chunk->Commit(aTrace.iData[1],aTrace.iData[2]);
  1.1790 +		break;
  1.1791 +
  1.1792 +	case BTrace::EChunkMemoryRemoved:
  1.1793 +		CHECK_TRACE_DATA_WORDS(3);
  1.1794 +		chunk->Decommit(aTrace.iData[1],aTrace.iData[2]);
  1.1795 +		break;
  1.1796 +
  1.1797 +	case BTrace::EChunkOwner:
  1.1798 +		{
  1.1799 +		CHECK_TRACE_DATA_WORDS(2);
  1.1800 +		Process* process = Process::FindOrCreate(aTrace,1);
  1.1801 +		// set owner, unless current owner is owned by the same process
  1.1802 +		// (this preserves creating thread names in ownership list which is more useful)
  1.1803 +		if(!chunk->iOwner || chunk->iOwner->iOwner!=process)
  1.1804 +			chunk->iOwner = process;
  1.1805 +		}
  1.1806 +		break;
  1.1807 +
  1.1808 +		}
  1.1809 +	}
  1.1810 +
  1.1811 +
  1.1812 +void ReportChunks()
  1.1813 +	{
  1.1814 +	TUint numChunks = Chunk::iContainer.Count();
  1.1815 +	if(!numChunks)
  1.1816 +		return;
  1.1817 +
  1.1818 +	if(!ReportLevel)
  1.1819 +		printf("\nREPORT: Chunks (Named objects only)\n\n");
  1.1820 +	else
  1.1821 +		printf("\nREPORT: Chunks\n\n");
  1.1822 +	WarnIfError(ChunkErrors);
  1.1823 +	printf("%-10s %5s %8s %8s %8s %8s %s\n",
  1.1824 +		"","State","Size","Peak","Max","TraceId","Name");
  1.1825 +	TUint totalSize = 0;
  1.1826 +	TUint i;
  1.1827 +	for(i=0; i<numChunks; ++i)
  1.1828 +		{
  1.1829 +		Chunk* chunk = (Chunk*)Chunk::iContainer[i];
  1.1830 +		if(ReportLevel==0 && !chunk->iNameSet)
  1.1831 +			continue; // only report explicitly named mutexes at report level 0
  1.1832 +		Object::FullNameBuf fullName;
  1.1833 +		chunk->FullName(fullName);
  1.1834 +		Object::TraceNameBuf name;
  1.1835 +		chunk->TraceName(name);
  1.1836 +		printf("%-10s %5s %7uk %7uk %7uk %08x '%s'\n",
  1.1837 +			name,chunk->iAlive?(const char*)"Alive":(const char*)"Dead",
  1.1838 +			(unsigned int)chunk->iCurrentSize/1024,(unsigned int)chunk->iPeakSize/1024,(unsigned int)chunk->iMaxSize/1024,
  1.1839 +			(unsigned int)chunk->iTraceId,fullName);
  1.1840 +		totalSize += chunk->iCurrentSize/1024;
  1.1841 +		}
  1.1842 +	printf("%-10s %5s --------\n","","");
  1.1843 +	printf("%-10s %5s %7uk\n","","",totalSize);
  1.1844 +	printf("\n");
  1.1845 +	}
  1.1846 +
  1.1847 +
  1.1848 +
  1.1849 +//
  1.1850 +// CodeSeg
  1.1851 +//
  1.1852 +
  1.1853 +void StartCodeSegs()
  1.1854 +	{
  1.1855 +	CodeSegErrors = 0;
  1.1856 +	}
  1.1857 +
  1.1858 +
  1.1859 +void PreProcessCodeSegs(TraceRecord& aTrace)
  1.1860 +	{
  1.1861 +	CHECK_TRACE_DATA_WORDS(1);
  1.1862 +	CodeSeg* codeseg;
  1.1863 +
  1.1864 +	switch((BTrace::TCodeSegs)aTrace.iSubCategory)
  1.1865 +		{
  1.1866 +	case BTrace::ECodeSegCreated:
  1.1867 +		codeseg = CodeSeg::FindOrCreate(aTrace,0);
  1.1868 +		codeseg->SetName(aTrace,1);
  1.1869 +		break;
  1.1870 +
  1.1871 +	case BTrace::ECodeSegInfo:
  1.1872 +		CHECK_TRACE_DATA_WORDS(10);
  1.1873 +		CodeSeg::FindOrCreate(aTrace,0);
  1.1874 +/*		- 4 bytes containing the attributes.
  1.1875 +		- 4 bytes containing the code base address (.text).
  1.1876 +		- 4 bytes containing the size of the code section (.text).
  1.1877 +		- 4 bytes containing the base address of the constant data section (.radata).
  1.1878 +		- 4 bytes containing the size of the constant data section (.radata).
  1.1879 +		- 4 bytes containing the base address of the initialised data section (.data).
  1.1880 +		- 4 bytes containing the size of the initialised data section (.data).
  1.1881 +		- 4 bytes containing the base address of the uninitialised data section (.bss).
  1.1882 +		- 4 bytes containing the size of the uninitialised data section (.bss).
  1.1883 +*/		break;
  1.1884 +
  1.1885 +	case BTrace::ECodeSegDestroyed:
  1.1886 +		codeseg = CodeSeg::FindOrCreate(aTrace,0);
  1.1887 +		codeseg->Destroy();
  1.1888 +		codeseg->iAllocatedMemory = 0; // clear this now because ECodeSegMemoryDeallocated comes after codeseg destroy
  1.1889 +		break;
  1.1890 +
  1.1891 +	case BTrace::ECodeSegMapped:
  1.1892 +		CHECK_TRACE_DATA_WORDS(2);
  1.1893 +		codeseg = CodeSeg::FindOrCreate(aTrace,0);
  1.1894 +		Process::FindOrCreate(aTrace,1);
  1.1895 +		break;
  1.1896 +
  1.1897 +	case BTrace::ECodeSegUnmapped:
  1.1898 +		CHECK_TRACE_DATA_WORDS(2);
  1.1899 +		CodeSeg::FindOrCreate(aTrace,0);
  1.1900 +		Process::FindOrCreate(aTrace,1);
  1.1901 +		break;
  1.1902 +
  1.1903 +	case BTrace::ECodeSegMemoryAllocated:
  1.1904 +		CHECK_TRACE_DATA_WORDS(2);
  1.1905 +		codeseg = CodeSeg::FindOrCreate(aTrace,0);
  1.1906 +		codeseg->iAllocatedMemory += aTrace.iData[1];
  1.1907 +		if(codeseg->iAllocatedMemory<aTrace.iData[1])
  1.1908 +			{
  1.1909 +			codeseg->iAllocatedMemory = ~0u; // overflowed!
  1.1910 +			++CodeSegErrors;
  1.1911 +			ErrorOnThisTrace = true;
  1.1912 +			}
  1.1913 +		break;
  1.1914 +
  1.1915 +	case BTrace::ECodeSegMemoryDeallocated:
  1.1916 +		{
  1.1917 +		CHECK_TRACE_DATA_WORDS(2);
  1.1918 +		codeseg = CodeSeg::Find(aTrace,0);
  1.1919 +		if(codeseg)
  1.1920 +			{
  1.1921 +			TUint32 memory = codeseg->iAllocatedMemory-aTrace.iData[1];
  1.1922 +			if(memory>codeseg->iAllocatedMemory)
  1.1923 +				{
  1.1924 +				memory = 0; // underflowed
  1.1925 +				++CodeSegErrors;
  1.1926 +				ErrorOnThisTrace = true;
  1.1927 +				}
  1.1928 +			codeseg->iAllocatedMemory = memory;
  1.1929 +			}
  1.1930 +		}
  1.1931 +		break;
  1.1932 +
  1.1933 +		}
  1.1934 +	}
  1.1935 +
  1.1936 +
  1.1937 +void ReportCodeSegs()
  1.1938 +	{
  1.1939 +	TUint numCodeSegs = CodeSeg::iContainer.Count();
  1.1940 +	if(!numCodeSegs)
  1.1941 +		return;
  1.1942 +
  1.1943 +	if(!ReportLevel)
  1.1944 +		printf("\nREPORT: CodeSegs (Named objects only)\n\n");
  1.1945 +	else
  1.1946 +		printf("\nREPORT: CodeSegs\n\n");
  1.1947 +	WarnIfError(CodeSegErrors);
  1.1948 +	printf("%-10s %5s %8s %8s %s\n",
  1.1949 +		"","State","Memory","TraceId","Name");
  1.1950 +	TUint totalSize = 0;
  1.1951 +	TUint i;
  1.1952 +	for(i=0; i<numCodeSegs; ++i)
  1.1953 +		{
  1.1954 +		CodeSeg* codeseg = (CodeSeg*)CodeSeg::iContainer[i];
  1.1955 +		if(ReportLevel==0 && !codeseg->iNameSet)
  1.1956 +			continue; // only report explicitly named mutexes at report level 0
  1.1957 +		Object::FullNameBuf fullName;
  1.1958 +		codeseg->FullName(fullName);
  1.1959 +		Object::TraceNameBuf name;
  1.1960 +		codeseg->TraceName(name);
  1.1961 +		printf("%-10s %5s %7uk %08x '%s'\n",
  1.1962 +			name,codeseg->iAlive?(const char*)"Alive":(const char*)"Dead",
  1.1963 +			(unsigned int)codeseg->iAllocatedMemory/1024,(unsigned int)codeseg->iTraceId,fullName);
  1.1964 +		totalSize += codeseg->iAllocatedMemory/1024;
  1.1965 +		}
  1.1966 +	printf("%-10s %5s --------\n","","");
  1.1967 +	printf("%-10s %5s %7uk\n","","",totalSize);
  1.1968 +	printf("\n");
  1.1969 +	}
  1.1970 +
  1.1971 +
  1.1972 +
  1.1973 +//
  1.1974 +// MetaTrace
  1.1975 +//
  1.1976 +
  1.1977 +TUint KernelMemoryInitialFree = 0;
  1.1978 +TUint KernelMemoryCurrentFree = 0;
  1.1979 +TUint KernelMemoryMisc = 0;
  1.1980 +TUint KernelMemoryDrvPhys = 0;
  1.1981 +TUint KernelMemoryDemandPagingCache = 0;
  1.1982 +TUint KernelMemoryErrors = 0;
  1.1983 +TBool KernelMemoryTracesPresent = false;
  1.1984 +
  1.1985 +void StartKernelMemory()
  1.1986 +	{
  1.1987 +	KernelMemoryInitialFree = 0;
  1.1988 +	KernelMemoryCurrentFree = 0;
  1.1989 +	KernelMemoryMisc = 0;
  1.1990 +	KernelMemoryDrvPhys = 0;
  1.1991 +	KernelMemoryErrors = 0;
  1.1992 +	KernelMemoryTracesPresent = false;
  1.1993 +	}
  1.1994 +
  1.1995 +
  1.1996 +void PreProcessKernelMemory(TraceRecord& aTrace)
  1.1997 +	{
  1.1998 +	CHECK_TRACE_DATA_WORDS(1);
  1.1999 +	KernelMemoryTracesPresent = true;
  1.2000 +	switch((BTrace::TKernelMemory)aTrace.iSubCategory)
  1.2001 +		{
  1.2002 +	case BTrace::EKernelMemoryInitialFree:
  1.2003 +		KernelMemoryInitialFree = aTrace.iData[0];
  1.2004 +		aTrace.iCalculatedData[0] = KernelMemoryInitialFree/1024;
  1.2005 +		break;
  1.2006 +
  1.2007 +	case BTrace::EKernelMemoryCurrentFree:
  1.2008 +		KernelMemoryCurrentFree = aTrace.iData[0];
  1.2009 +		aTrace.iCalculatedData[0] = KernelMemoryCurrentFree/1024;
  1.2010 +		break;
  1.2011 +
  1.2012 +	case BTrace::EKernelMemoryMiscAlloc:
  1.2013 +		KernelMemoryMisc += aTrace.iData[0];
  1.2014 +		if(KernelMemoryMisc < aTrace.iData[0])
  1.2015 +			{
  1.2016 +			KernelMemoryMisc = 0xffffffffu;
  1.2017 +			++KernelMemoryErrors;
  1.2018 +			ErrorOnThisTrace = true;
  1.2019 +			}
  1.2020 +		aTrace.iCalculatedData[0] = KernelMemoryMisc/1024;
  1.2021 +		break;
  1.2022 +
  1.2023 +	case BTrace::EKernelMemoryMiscFree:
  1.2024 +		if(KernelMemoryMisc >= aTrace.iData[0])
  1.2025 +			KernelMemoryMisc -= aTrace.iData[0];
  1.2026 +		else
  1.2027 +			{
  1.2028 +			KernelMemoryMisc = 0;
  1.2029 +			++KernelMemoryErrors;
  1.2030 +			ErrorOnThisTrace = true;
  1.2031 +			}
  1.2032 +		aTrace.iCalculatedData[0] = KernelMemoryMisc/1024;
  1.2033 +		break;
  1.2034 +
  1.2035 +	case BTrace::EKernelMemoryDemandPagingCache:
  1.2036 +		KernelMemoryDemandPagingCache = aTrace.iData[0];
  1.2037 +		break;
  1.2038 +
  1.2039 +	case BTrace::EKernelMemoryDrvPhysAlloc:
  1.2040 +		KernelMemoryDrvPhys += aTrace.iData[0];
  1.2041 +		if(KernelMemoryDrvPhys < aTrace.iData[0])
  1.2042 +			{
  1.2043 +			KernelMemoryDrvPhys = 0xffffffffu;
  1.2044 +			++KernelMemoryErrors;
  1.2045 +			ErrorOnThisTrace = true;
  1.2046 +			}
  1.2047 +		aTrace.iCalculatedData[0] = KernelMemoryDrvPhys/1024;
  1.2048 +		break;
  1.2049 +
  1.2050 +	case BTrace::EKernelMemoryDrvPhysFree:
  1.2051 +		if(KernelMemoryDrvPhys >= aTrace.iData[0])
  1.2052 +			KernelMemoryDrvPhys -= aTrace.iData[0];
  1.2053 +		else
  1.2054 +			{
  1.2055 +			KernelMemoryDrvPhys = 0;
  1.2056 +			++KernelMemoryErrors;
  1.2057 +			ErrorOnThisTrace = true;
  1.2058 +			}
  1.2059 +		aTrace.iCalculatedData[0] = KernelMemoryDrvPhys/1024;
  1.2060 +		break;
  1.2061 +		}
  1.2062 +	}
  1.2063 +
  1.2064 +void ReportKernelMemory()
  1.2065 +	{
  1.2066 +	if(!KernelMemoryTracesPresent)
  1.2067 +		return;
  1.2068 +
  1.2069 +	printf("\nREPORT: Kernel Memory\n\n");
  1.2070 +	WarnIfError(KernelMemoryErrors);
  1.2071 +	printf("Total RAM size............................. %dk\n",KernelMemoryInitialFree/1024);
  1.2072 +	printf("Miscelaneous RAM used by kernel............ %dk\n",KernelMemoryMisc/1024);
  1.2073 +	printf("Physical RAM allocated by device drivers... %dk\n",KernelMemoryDrvPhys/1024);
  1.2074 +	printf("Demand paging cache reserve................ %dk\n",KernelMemoryDemandPagingCache/1024);
  1.2075 +	if(ReportLevel>1)
  1.2076 +		printf("Last 'current free RAM' value seen......... %dk\n",KernelMemoryCurrentFree/1024);
  1.2077 +
  1.2078 +	printf("\n");
  1.2079 +	}
  1.2080 +
  1.2081 +//
  1.2082 +// MetaTrace
  1.2083 +//
  1.2084 +
  1.2085 +void StartMetaTrace()
  1.2086 +	{
  1.2087 +	TimestampPeriod = 0;
  1.2088 +	Timestamp2Period = 0;
  1.2089 +	}
  1.2090 +
  1.2091 +
  1.2092 +void PreProcessMetaTrace(TraceRecord& aTrace)
  1.2093 +	{
  1.2094 +	switch((BTrace::TMetaTrace)aTrace.iSubCategory)
  1.2095 +		{
  1.2096 +	case BTrace::EMetaTraceTimestampsInfo:
  1.2097 +		CHECK_TRACE_DATA_WORDS(3);
  1.2098 +		TimestampPeriod = aTrace.iData[0];
  1.2099 +		Timestamp2Period = aTrace.iData[1];
  1.2100 +		Timestamp64Bit = aTrace.iData[2]&1;
  1.2101 +		break;
  1.2102 +
  1.2103 +	case BTrace::EMetaTraceMeasurementStart:
  1.2104 +	case BTrace::EMetaTraceMeasurementEnd:
  1.2105 +		CHECK_TRACE_DATA_WORDS(2);
  1.2106 +		aTrace.iDataTypes[2] = EDataTypeText;
  1.2107 +		break;
  1.2108 +
  1.2109 +	case BTrace::EMetaTraceFilterChange:
  1.2110 +		CHECK_TRACE_DATA_WORDS(1);
  1.2111 +		break;
  1.2112 +		}
  1.2113 +	}
  1.2114 +
  1.2115 +//
  1.2116 +// EFastMutex traces
  1.2117 +//
  1.2118 +
  1.2119 +void StartFastMutex()
  1.2120 +	{
  1.2121 +	FastMutexNestErrors = 0;
  1.2122 +	}
  1.2123 +
  1.2124 +
  1.2125 +void PreProcessFastMutex(TraceRecord& aTrace)
  1.2126 +	{
  1.2127 +	CHECK_TRACE_DATA_WORDS(1);
  1.2128 +	FastMutex* mutex = FastMutex::FindOrCreate(aTrace,0);
  1.2129 +	Thread* thread = aTrace.iContextID;
  1.2130 +
  1.2131 +	switch((BTrace::TFastMutex)aTrace.iSubCategory)
  1.2132 +		{
  1.2133 +	case BTrace::EFastMutexWait:
  1.2134 +		aTrace.iCalculatedData[0] = Time(mutex->Wait(thread));
  1.2135 +		break;
  1.2136 +
  1.2137 +	case BTrace::EFastMutexSignal:
  1.2138 +		aTrace.iCalculatedData[0] = Time(mutex->Signal(thread,aTrace.iPC));
  1.2139 +		break;
  1.2140 +
  1.2141 +	case BTrace::EFastMutexFlash:
  1.2142 +		aTrace.iCalculatedData[0] = Time(mutex->Signal(thread,aTrace.iPC));
  1.2143 +		mutex->Wait(thread);
  1.2144 +		break;
  1.2145 +
  1.2146 +	case BTrace::EFastMutexName:
  1.2147 +		CHECK_TRACE_DATA_WORDS(2);
  1.2148 +		mutex->SetName(aTrace,2);
  1.2149 +		break;
  1.2150 +
  1.2151 +	case BTrace::EFastMutexBlock:
  1.2152 +		mutex->Block(thread);
  1.2153 +		break;
  1.2154 +
  1.2155 +		}
  1.2156 +	}
  1.2157 +
  1.2158 +
  1.2159 +void PreProcessSymbianKernelSync(TraceRecord& aTrace)
  1.2160 +	{
  1.2161 +	switch((BTrace::TSymbianKernelSync)aTrace.iSubCategory)
  1.2162 +		{
  1.2163 +	case BTrace::ESemaphoreCreate:
  1.2164 +		{
  1.2165 +		CHECK_TRACE_DATA_WORDS(2);
  1.2166 +		TUint32 ownerid = aTrace.iData[1];
  1.2167 +		Semaphore* sem = Semaphore::FindOrCreate(aTrace,0);
  1.2168 +		Object* owner = Thread::FindThreadOrProcess(aTrace,1);
  1.2169 +		sem->iOwner = owner;
  1.2170 +		if (!owner && ownerid)
  1.2171 +			sem->iOwnerTraceId = ownerid, ++Object::UnknownOwners;
  1.2172 +		sem->SetName(aTrace,2);
  1.2173 +		break;
  1.2174 +		}
  1.2175 +
  1.2176 +	case BTrace::ESemaphoreDestroy:
  1.2177 +		{
  1.2178 +		CHECK_TRACE_DATA_WORDS(1);
  1.2179 +		Semaphore* sem = Semaphore::Find(aTrace,0);
  1.2180 +		if (sem)
  1.2181 +			sem->Destroy();
  1.2182 +		break;
  1.2183 +		}
  1.2184 +
  1.2185 +	case BTrace::ESemaphoreAcquire:
  1.2186 +	case BTrace::ESemaphoreRelease:
  1.2187 +	case BTrace::ESemaphoreBlock:
  1.2188 +		{
  1.2189 +		CHECK_TRACE_DATA_WORDS(1);
  1.2190 +		Semaphore::FindOrCreate(aTrace,0);
  1.2191 +		break;
  1.2192 +		}
  1.2193 +
  1.2194 +
  1.2195 +	case BTrace::EMutexCreate:
  1.2196 +		{
  1.2197 +		CHECK_TRACE_DATA_WORDS(2);
  1.2198 +		TUint32 ownerid = aTrace.iData[1];
  1.2199 +		Mutex* m = Mutex::FindOrCreate(aTrace,0);
  1.2200 +		Object* owner = Thread::FindThreadOrProcess(aTrace,1);
  1.2201 +		m->iOwner = owner;
  1.2202 +		if (!owner && ownerid)
  1.2203 +			m->iOwnerTraceId = ownerid, ++Object::UnknownOwners;
  1.2204 +		m->SetName(aTrace,2);
  1.2205 +		break;
  1.2206 +		}
  1.2207 +
  1.2208 +	case BTrace::EMutexDestroy:
  1.2209 +		{
  1.2210 +		CHECK_TRACE_DATA_WORDS(1);
  1.2211 +		Mutex* m = Mutex::Find(aTrace,0);
  1.2212 +		if (m)
  1.2213 +			m->Destroy();
  1.2214 +		break;
  1.2215 +		}
  1.2216 +
  1.2217 +	case BTrace::EMutexAcquire:
  1.2218 +	case BTrace::EMutexRelease:
  1.2219 +	case BTrace::EMutexBlock:
  1.2220 +		{
  1.2221 +		CHECK_TRACE_DATA_WORDS(1);
  1.2222 +		Mutex::FindOrCreate(aTrace,0);
  1.2223 +		break;
  1.2224 +		}
  1.2225 +
  1.2226 +
  1.2227 +	case BTrace::ECondVarCreate:
  1.2228 +		{
  1.2229 +		CHECK_TRACE_DATA_WORDS(2);
  1.2230 +		TUint32 ownerid = aTrace.iData[1];
  1.2231 +		CondVar* cv = CondVar::FindOrCreate(aTrace,0);
  1.2232 +		Object* owner = Thread::FindThreadOrProcess(aTrace,1);
  1.2233 +		cv->iOwner = owner;
  1.2234 +		if (!owner && ownerid)
  1.2235 +			cv->iOwnerTraceId = ownerid, ++Object::UnknownOwners;
  1.2236 +		cv->SetName(aTrace,2);
  1.2237 +		break;
  1.2238 +		}
  1.2239 +
  1.2240 +	case BTrace::ECondVarDestroy:
  1.2241 +		{
  1.2242 +		CHECK_TRACE_DATA_WORDS(1);
  1.2243 +		CondVar* cv = CondVar::Find(aTrace,0);
  1.2244 +		if (cv)
  1.2245 +			cv->Destroy();
  1.2246 +		break;
  1.2247 +		}
  1.2248 +
  1.2249 +	case BTrace::ECondVarBlock:
  1.2250 +	case BTrace::ECondVarWakeUp:
  1.2251 +	case BTrace::ECondVarSignal:
  1.2252 +	case BTrace::ECondVarBroadcast:
  1.2253 +		{
  1.2254 +		CHECK_TRACE_DATA_WORDS(1);
  1.2255 +		CondVar::FindOrCreate(aTrace,0);
  1.2256 +		break;
  1.2257 +		}
  1.2258 +
  1.2259 +
  1.2260 +	default:
  1.2261 +		break;
  1.2262 +		}
  1.2263 +	}
  1.2264 +
  1.2265 +
  1.2266 +void ReportFastMutex()
  1.2267 +	{
  1.2268 +	TUint numMutexes = FastMutex::iContainer.Count();
  1.2269 +	if(!numMutexes)
  1.2270 +		return;
  1.2271 +
  1.2272 +	if(!ReportLevel)
  1.2273 +		printf("\nREPORT: FastMutexes (Named objects only)\n\n");
  1.2274 +	else
  1.2275 +		printf("\nREPORT: FastMutexes\n\n");
  1.2276 +	WarnIfError(0);
  1.2277 +	printf("%-10s %8s %8s %10s %10s %-8s %12s %8s %s\n",
  1.2278 +		"","MaxTime","AveTime","HeldCount","BlockCount","MaxPC","MaxTimestamp","TraceId","Name");
  1.2279 +	TUint i;
  1.2280 +	for(i=0; i<numMutexes; ++i)
  1.2281 +		{
  1.2282 +		FastMutex* mutex = (FastMutex*)FastMutex::iContainer[i];
  1.2283 +		if(ReportLevel==0 && !mutex->iNameSet)
  1.2284 +			continue; // only report explicitly named mutexes at report level 0
  1.2285 +		Object::FullNameBuf fullName;
  1.2286 +		mutex->FullName(fullName);
  1.2287 +		Object::TraceNameBuf name;
  1.2288 +		mutex->TraceName(name);
  1.2289 +		TUint32 averageHeldTime = mutex->iHeldCount ? Time(mutex->iTotalHeldTime/mutex->iHeldCount) : 0;
  1.2290 +		printf("%-10s %8u %8u %10u %10u %08x %12u %08x '%s'\n",
  1.2291 +			name,(unsigned int)Time(mutex->iMaxHeldTime),(unsigned int)averageHeldTime,(unsigned int)mutex->iHeldCount,(unsigned int)mutex->iBlockCount,
  1.2292 +			(unsigned int)mutex->iMaxHeldPc,(unsigned int)Time(mutex->iMaxHeldTimestamp-TimestampBase),(unsigned int)mutex->iTraceId,fullName);
  1.2293 +		}
  1.2294 +	printf("\n");
  1.2295 +	}
  1.2296 +
  1.2297 +
  1.2298 +//
  1.2299 +// ProfilingSample
  1.2300 +//
  1.2301 +
  1.2302 +void StartProfilingSample()
  1.2303 +	{
  1.2304 +	ProfilingSampleErrors = 0;
  1.2305 +	}
  1.2306 +
  1.2307 +
  1.2308 +/** 
  1.2309 +	Index 0 of TraceRecord is the program counter
  1.2310 +	The only one not having it are ECpuNonSymbianThreadSample samples.
  1.2311 +	Index 1 of TraceRecord is the NThread pointer.
  1.2312 +	The only one that has it is ECpuFullSample.
  1.2313 +	The samples are identified by their index, which is maintained by 
  1.2314 +	ProfilingSample::iSamples. Thus to create a ProfilingSample object we
  1.2315 +	need to put this value in the data at index 0 after copying the PC 
  1.2316 +	and Thread id (if present).
  1.2317 +	The reasoning is that all samples need to be represented and thus we 
  1.2318 +	need to create a ProfilingSample object, even when they are on the same 
  1.2319 +	PC and or thread. Each sample important and should not be discarded.
  1.2320 +*/
  1.2321 +void PreProcessProfiling(TraceRecord& aTrace)
  1.2322 +	{
  1.2323 +
  1.2324 +	ProfilingSample* sample;
  1.2325 +	Thread* thread;
  1.2326 +
  1.2327 +	switch((BTrace::TProfiling)aTrace.iSubCategory)
  1.2328 +		{
  1.2329 +
  1.2330 +	case BTrace::ECpuFullSample:
  1.2331 +		{
  1.2332 +		CHECK_TRACE_DATA_WORDS(2);
  1.2333 +
  1.2334 +		TUint32 aThread = aTrace.iData[1];
  1.2335 +		// The thread id is aTrace.iData[1], so find or create it
  1.2336 +		// This action can modify aTrace.iData[1], that is why we took a copy above
  1.2337 +		thread = Thread::FindOrCreate(aTrace,1);
  1.2338 +		if( thread )
  1.2339 +			thread->Sampled();
  1.2340 +
  1.2341 +		TUint32 aPC = aTrace.iData[0];
  1.2342 +
  1.2343 +		// Always create a sample identified by the running counter ProfilingSample::iSamples
  1.2344 +		aTrace.iData[0] = ProfilingSample::iSamples;
  1.2345 +		sample = ProfilingSample::Create(aTrace,0);
  1.2346 +		if( sample )
  1.2347 +			{
  1.2348 +			sample->SetPC( aPC );
  1.2349 +			sample->SetThread( aThread );
  1.2350 +			sample->SetType(BTrace::ECpuFullSample);
  1.2351 +			}
  1.2352 +
  1.2353 +		ProfilingSample::iLastThread = aThread;
  1.2354 +		}
  1.2355 +		break;
  1.2356 +
  1.2357 +	case BTrace::ECpuOptimisedSample:
  1.2358 +		{
  1.2359 +		CHECK_TRACE_DATA_WORDS(1);
  1.2360 +		TUint32 aPC = aTrace.iData[0];
  1.2361 +
  1.2362 +		aTrace.iData[0] = ProfilingSample::iSamples;
  1.2363 +		sample = ProfilingSample::Create(aTrace,0);
  1.2364 +		if( sample )
  1.2365 +			{
  1.2366 +			sample->SetPC( aPC );
  1.2367 +			sample->SetType( BTrace::ECpuOptimisedSample );
  1.2368 +			sample->SetThread(ProfilingSample::iLastThread);
  1.2369 +			}
  1.2370 +
  1.2371 +		if( 0 != ProfilingSample::iLastThread )
  1.2372 +			{
  1.2373 +			thread = Thread::Find(ProfilingSample::iLastThread);
  1.2374 +			if( thread )
  1.2375 +				{
  1.2376 +				thread->Sampled();
  1.2377 +				}
  1.2378 +			}
  1.2379 +
  1.2380 +		}
  1.2381 +		break;
  1.2382 +
  1.2383 +	case BTrace::ECpuIdfcSample:
  1.2384 +		{
  1.2385 +		CHECK_TRACE_DATA_WORDS(1);
  1.2386 +		TUint32 aPC = aTrace.iData[0];
  1.2387 +
  1.2388 +		aTrace.iData[0] = ProfilingSample::iSamples;
  1.2389 +		sample = ProfilingSample::Create(aTrace,0);
  1.2390 +
  1.2391 +		sample->SetPC( aPC );
  1.2392 +		sample->SetType(BTrace::ECpuIdfcSample);
  1.2393 +
  1.2394 +		}
  1.2395 +		break;
  1.2396 +
  1.2397 +	case BTrace::ECpuNonSymbianThreadSample:
  1.2398 +		{
  1.2399 +		// No data
  1.2400 +		aTrace.iData[0] = ProfilingSample::iSamples;
  1.2401 +		sample = ProfilingSample::Create(aTrace,0);
  1.2402 +		sample->SetType(BTrace::ECpuNonSymbianThreadSample);
  1.2403 +
  1.2404 +		}
  1.2405 +		break;
  1.2406 +
  1.2407 +	default:
  1.2408 +		ProfilingSampleErrors++;
  1.2409 +		ErrorOnThisTrace = true;
  1.2410 +		}
  1.2411 +
  1.2412 +	ProfilingSample::iSamples++;
  1.2413 +
  1.2414 +	}
  1.2415 +
  1.2416 +
  1.2417 +void ReportSampleProfiling()
  1.2418 +	{
  1.2419 +	printf("\nREPORT: Profiling\n\n");
  1.2420 +
  1.2421 +	TUint numSamples = ProfilingSample::iContainer.Count();
  1.2422 +	if(!numSamples)
  1.2423 +		{
  1.2424 +		printf("\n        No Samples\n\n");
  1.2425 +		return;
  1.2426 +		}
  1.2427 +
  1.2428 +	WarnIfError(0);
  1.2429 +
  1.2430 +
  1.2431 +	// Print thread samples
  1.2432 +	TUint numThreads = Thread::iContainer.Count();
  1.2433 +	if(numThreads)
  1.2434 +		{
  1.2435 +		printf(" Samples by Thread\n\n");
  1.2436 +		printf("%-11s %-8s %-8s\t%-12s\t%s\n\n", "", "TraceId", "Samples", "%", "Name");
  1.2437 +		TUint i;
  1.2438 +		TReal threadPercentage;
  1.2439 +		for(i=0; i<numThreads; ++i)
  1.2440 +			{
  1.2441 +			Thread* thread = (Thread*)Thread::iContainer[i];
  1.2442 +
  1.2443 +			if( thread && thread->iSamples )
  1.2444 +				{
  1.2445 +				Object::FullNameBuf fullName;
  1.2446 +				thread->FullName(fullName);
  1.2447 +				Object::TraceNameBuf name;
  1.2448 +				thread->TraceName(name);
  1.2449 +
  1.2450 +				threadPercentage = thread->iSamples*100.0/numSamples;
  1.2451 +
  1.2452 +				printf("%-10s %08x %8d\t%02.2f\t'%s'\n",
  1.2453 +							name,
  1.2454 +							(unsigned int)thread->iTraceId,
  1.2455 +							(unsigned int)(thread->iSamples),
  1.2456 +							threadPercentage,
  1.2457 +							fullName );
  1.2458 +
  1.2459 +				}//if samples
  1.2460 +			}//for numThreads
  1.2461 +		}//if threads
  1.2462 +
  1.2463 +
  1.2464 +	if(ReportLevel>0)
  1.2465 +		{
  1.2466 +
  1.2467 +		printf("\nAll samples\n\n%-21s %-8s %-8s\n\n", "Type", "ThreadId", "PC");
  1.2468 +
  1.2469 +		TUint i;
  1.2470 +		TUint fullSamples = 0;
  1.2471 +		TUint optSamples = 0;
  1.2472 +		TUint dfcSamples = 0;
  1.2473 +		TUint nonSymbSamples = 0;
  1.2474 +
  1.2475 +		for(i=0; i<numSamples; ++i)
  1.2476 +			{
  1.2477 +			ProfilingSample* sample = (ProfilingSample*)ProfilingSample::iContainer[i];
  1.2478 +			switch((BTrace::TProfiling)sample->iType)
  1.2479 +				{
  1.2480 +				case BTrace::ECpuFullSample:
  1.2481 +					{
  1.2482 +					if( ReportLevel>1)
  1.2483 +						printf("ECpuFull              %08x %08x\n",
  1.2484 +							 (unsigned int)(sample->iThread), (unsigned int)(sample->iPC) );
  1.2485 +
  1.2486 +					fullSamples++;
  1.2487 +					}
  1.2488 +					break;
  1.2489 +				case BTrace::ECpuOptimisedSample:
  1.2490 +					{
  1.2491 +					if( ReportLevel>1)
  1.2492 +						printf("ECpuOptimised         %08x %08x\n",
  1.2493 +							 (unsigned int)(sample->iThread), (unsigned int)(sample->iPC) );
  1.2494 +
  1.2495 +					optSamples++;
  1.2496 +					}
  1.2497 +					break;
  1.2498 +				case BTrace::ECpuIdfcSample:
  1.2499 +					{
  1.2500 +					if( ReportLevel>1)
  1.2501 +						printf("ECpuIdfc              %08x\n", (unsigned int)(sample->iPC) );
  1.2502 +
  1.2503 +					dfcSamples++;
  1.2504 +					}
  1.2505 +					break;
  1.2506 +				case BTrace::ECpuNonSymbianThreadSample:
  1.2507 +					{
  1.2508 +					if( ReportLevel>1)
  1.2509 +						printf("ECpuNonSymbianThread\n");
  1.2510 +
  1.2511 +					nonSymbSamples++;
  1.2512 +					}
  1.2513 +					break;
  1.2514 +				}//switch
  1.2515 +			}//for
  1.2516 +
  1.2517 +
  1.2518 +		TReal typePercentage;
  1.2519 +
  1.2520 +		printf("\nSamples by type\n");
  1.2521 +
  1.2522 +		typePercentage = fullSamples * 100.0 / numSamples;
  1.2523 +		printf(" Samples of type ECpuFullSample :\t\t%-10d\t%02.2f %%\n", fullSamples, typePercentage  );
  1.2524 +
  1.2525 +		typePercentage = optSamples * 100.0 / numSamples;
  1.2526 +		printf(" Samples of type ECpuOptimisedSample :\t\t%-10d\t%02.2f %%\n", optSamples, typePercentage  );
  1.2527 +
  1.2528 +		typePercentage = dfcSamples * 100.0 / numSamples;
  1.2529 +		printf(" Samples of type ECpuIdfcSample :\t\t%-10d\t%02.2f %%\n", dfcSamples, typePercentage  );
  1.2530 +
  1.2531 +		typePercentage = nonSymbSamples * 100.0 / numSamples;
  1.2532 +		printf(" Samples of type ECpuNonSymbianThreadSample :\t%-10d\t%02.2f %%\n", nonSymbSamples, typePercentage  );
  1.2533 +
  1.2534 +		printf(" Total Samples : \t\t\t\t%d\n", numSamples );
  1.2535 +
  1.2536 +		}//report level
  1.2537 +
  1.2538 +	printf("\n");
  1.2539 +	}
  1.2540 +
  1.2541 +//
  1.2542 +// Trace processing
  1.2543 +//
  1.2544 +
  1.2545 +TraceRecord** TraceIndex = 0;
  1.2546 +TUint TraceIndexSize = 0;
  1.2547 +TUint32 NextTraceId = 0;
  1.2548 +TraceRecord* LastTrace = 0;
  1.2549 +TBool Timestamp2Present = 0;
  1.2550 +TBool TraceDumpStarted = false;
  1.2551 +
  1.2552 +
  1.2553 +void StartTrace()
  1.2554 +	{
  1.2555 +	TraceDumpStarted = false;
  1.2556 +	TraceFormatErrors = 0;
  1.2557 +	TraceBufferFilled = false;
  1.2558 +	Timestamp2Present = false;
  1.2559 +	}
  1.2560 +
  1.2561 +
  1.2562 +TUint32 ReadTraceWord(const TUint8*& header)
  1.2563 +	{
  1.2564 +	TUint32 word;
  1.2565 +	memcpy(&word, header, sizeof(TUint32));
  1.2566 +	header += sizeof(TUint32);
  1.2567 +	return word;
  1.2568 +	}
  1.2569 +
  1.2570 +
  1.2571 +TBool PreProcessTrace(TraceRecord& aTrace, const TUint8* aData)
  1.2572 +	{
  1.2573 +	ErrorOnThisTrace = false;
  1.2574 +	aTrace.iError = 0;
  1.2575 +
  1.2576 +	aTrace.iDataSize = 0; // initialise to safe value
  1.2577 +
  1.2578 +	// process aTrace header...
  1.2579 +	TUint traceSize = aData[BTrace::ESizeIndex];
  1.2580 +	if(traceSize<4u || traceSize>(TUint)KMaxBTraceRecordSize)
  1.2581 +		{
  1.2582 +		aTrace.iError = 1;
  1.2583 +		return false; // bad size
  1.2584 +		}
  1.2585 +	aTrace.iCpuNum = 0;
  1.2586 +
  1.2587 +	TUint8 flags = aData[BTrace::EFlagsIndex];
  1.2588 +	if(!TraceRecordId)						// first trace record...?
  1.2589 +		flags &= ~BTrace::EMissingRecord;	// ignore missing traces before log start
  1.2590 +	aTrace.iFlags = flags;
  1.2591 +
  1.2592 +	TUint8 category = aData[BTrace::ECategoryIndex];
  1.2593 +	aTrace.iCategory = category;
  1.2594 +
  1.2595 +	TUint8 subCategory = aData[BTrace::ESubCategoryIndex];
  1.2596 +	aTrace.iSubCategory = subCategory;
  1.2597 +
  1.2598 +	const TUint8* header = aData+4;
  1.2599 +
  1.2600 +	TUint32 header2 = 0;
  1.2601 +	if(flags&BTrace::EHeader2Present)
  1.2602 +		{
  1.2603 +		header2 = ReadTraceWord(header);
  1.2604 +		aTrace.iCpuNum = (TUint8)(header2>>20);
  1.2605 +		}
  1.2606 +	aTrace.iHeader2 = header2;
  1.2607 +	aTrace.iCpu = TheCpus + aTrace.iCpuNum;
  1.2608 +
  1.2609 +	// process timestamp and timestamp2...
  1.2610 +	TUint32 ts1 = 0;
  1.2611 +	TUint32 ts2 = 0;
  1.2612 +	TUint64 timestamp = 0;
  1.2613 +	if(flags&BTrace::ETimestampPresent)
  1.2614 +		ts1 = ReadTraceWord(header);
  1.2615 +	if(flags&BTrace::ETimestamp2Present)
  1.2616 +		{
  1.2617 +		Timestamp2Present = true;
  1.2618 +		ts2 = ReadTraceWord(header);
  1.2619 +		}
  1.2620 +	aTrace.iTimestamp2 = ts2;
  1.2621 +	if(flags&BTrace::ETimestampPresent)
  1.2622 +		{
  1.2623 +		if (Timestamp64Bit)
  1.2624 +			{
  1.2625 +			timestamp = ts2;
  1.2626 +			timestamp <<= 32;
  1.2627 +			timestamp |= ts1;
  1.2628 +			Timestamp = timestamp;
  1.2629 +			}
  1.2630 +		else
  1.2631 +			{
  1.2632 +			timestamp = ts1;
  1.2633 +			if(timestamp<(Timestamp&0xffffffffu))
  1.2634 +				Timestamp += TUint64(1)<<32;
  1.2635 +			Timestamp &= TUint64(0xffffffff)<<32;
  1.2636 +			Timestamp |= timestamp; 
  1.2637 +			timestamp = Timestamp;
  1.2638 +			}
  1.2639 +		if(!TraceRecordId)
  1.2640 +			TimestampBase = timestamp; // record timestamp of first trace
  1.2641 +		}
  1.2642 +	aTrace.iTimestamp = timestamp;
  1.2643 +
  1.2644 +	// process context...
  1.2645 +	// coverity[assign_zero]
  1.2646 +	aTrace.iContextID = 0;
  1.2647 +	if(flags&BTrace::EContextIdPresent)
  1.2648 +		{
  1.2649 +		TUint32 contextId = ReadTraceWord(header);
  1.2650 +		Thread* thread = Thread::Find(contextId);
  1.2651 +		if(!thread)
  1.2652 +			thread = new Thread(contextId);
  1.2653 +		aTrace.iContextID = thread;
  1.2654 +		}
  1.2655 +
  1.2656 +	// process pc...
  1.2657 +	TUint32 pc = 0;
  1.2658 +	if(flags&BTrace::EPcPresent)
  1.2659 +		pc = ReadTraceWord(header);
  1.2660 +	aTrace.iPC = pc;
  1.2661 +
  1.2662 +	// process extra...
  1.2663 +	TUint32 extra = 0;
  1.2664 +	if(flags&BTrace::EExtraPresent)
  1.2665 +		extra = ReadTraceWord(header);
  1.2666 +	aTrace.iExtra = extra;
  1.2667 +
  1.2668 +	// process payload data...
  1.2669 +	TUint headerSize = header-aData;
  1.2670 +	aData = (TUint8*)header;
  1.2671 +	if(headerSize>traceSize)
  1.2672 +		{
  1.2673 +		aTrace.iError = 1;
  1.2674 +		return false; // bad trace record
  1.2675 +		}
  1.2676 +	TUint dataSize = traceSize-headerSize;
  1.2677 +	if(dataSize>sizeof(aTrace.iData))
  1.2678 +		{
  1.2679 +		aTrace.iError = 1;
  1.2680 +		return false; // bad trace record
  1.2681 +		}
  1.2682 +	aTrace.iDataSize = dataSize;
  1.2683 +	memcpy(&aTrace.iData,aData,dataSize);
  1.2684 +
  1.2685 +	// clear pre-processor specific data...
  1.2686 +	aTrace.iDataTypes[0] = 0;
  1.2687 +	aTrace.iDataTypes[1] = 0;
  1.2688 +	aTrace.iDataTypes[2] = 0;
  1.2689 +	aTrace.iDataTypes[3] = 0;
  1.2690 +	aTrace.iCalculatedData[0] = 0;
  1.2691 +	aTrace.iCalculatedData[1] = 0;
  1.2692 +
  1.2693 +	// check for missing.
  1.2694 +	if(flags & BTrace::EMissingRecord)
  1.2695 +		{// Some trace was missing as the btrace buffer must have been filled.
  1.2696 +		TraceBufferFilled = true;
  1.2697 +		aTrace.iError = 1;
  1.2698 +		return false;
  1.2699 +		}
  1.2700 +
  1.2701 +	// category specific processing...
  1.2702 +	switch(aTrace.iCategory)
  1.2703 +		{
  1.2704 +	case BTrace::ERDebugPrintf:
  1.2705 +	case BTrace::EKernPrintf:
  1.2706 +	case BTrace::EPlatsecPrintf:
  1.2707 +		if((flags&BTrace::EHeader2Present) && (header2&BTrace::EMultipartFlagMask))
  1.2708 +			aTrace.iDataTypes[2] = EDataTypeText;
  1.2709 +		else
  1.2710 +			aTrace.iDataTypes[1] = EDataTypeText;
  1.2711 +		break;
  1.2712 +	case BTrace::EThreadIdentification:
  1.2713 +		PreProcessThreadIdentification(aTrace); break;
  1.2714 +	case BTrace::ECpuUsage:
  1.2715 +		PreProcessCpuUsage(aTrace); break;
  1.2716 +	case BTrace::EChunks:
  1.2717 +		PreProcessChunks(aTrace); break;
  1.2718 +	case BTrace::ECodeSegs:
  1.2719 +		PreProcessCodeSegs(aTrace); break;
  1.2720 +	case BTrace::EKernelMemory:
  1.2721 +		PreProcessKernelMemory(aTrace); break;
  1.2722 +	case BTrace::EMetaTrace:
  1.2723 +		PreProcessMetaTrace(aTrace); break;
  1.2724 +	case BTrace::EFastMutex:
  1.2725 +		PreProcessFastMutex(aTrace); break;
  1.2726 +	case BTrace::EProfiling:
  1.2727 +		PreProcessProfiling(aTrace); break;
  1.2728 +	case BTrace::ESymbianKernelSync:
  1.2729 +		PreProcessSymbianKernelSync(aTrace); break;
  1.2730 +	default:
  1.2731 +		break;
  1.2732 +		}
  1.2733 +
  1.2734 +	// update trace ID...
  1.2735 +	++TraceRecordId;
  1.2736 +	if (ErrorOnThisTrace)
  1.2737 +		aTrace.iError = 1;
  1.2738 +	return true;
  1.2739 +	}
  1.2740 +
  1.2741 +
  1.2742 +void DumpTrace(TraceRecord& aTrace)
  1.2743 +	{
  1.2744 +	if(!TraceDumpStarted)
  1.2745 +		{
  1.2746 +		// print heading...
  1.2747 +		if(SMP)
  1.2748 +			printf("C ");
  1.2749 +		if(Timestamp2Present)
  1.2750 +			printf("%10s ","TimeStamp2");
  1.2751 +		printf("%10s ","Time");
  1.2752 +		printf("%-8s ","PC");
  1.2753 +		if(ReportLevel>2)
  1.2754 +			{
  1.2755 +			printf("%-60s ","Context");
  1.2756 +			printf("%18s ","Category");
  1.2757 +			printf("%24s ","SubCategory");
  1.2758 +			}
  1.2759 +		else
  1.2760 +			{
  1.2761 +			printf("%-10s ","Context");
  1.2762 +			printf("%24s ","SubCategory");
  1.2763 +			}
  1.2764 +		printf("Data...\n");
  1.2765 +		TraceDumpStarted = true;
  1.2766 +		}
  1.2767 +
  1.2768 +	if(aTrace.iFlags&BTrace::EMissingRecord)
  1.2769 +		printf("MISSING TRACE RECORD(S)\n");
  1.2770 +
  1.2771 +	// print CPU number
  1.2772 +	if (SMP)
  1.2773 +		{
  1.2774 +		printf("%1d ", aTrace.iCpuNum);
  1.2775 +		}
  1.2776 +
  1.2777 +	// print timestamp...
  1.2778 +	if(Timestamp2Present)
  1.2779 +		{
  1.2780 +		if(aTrace.iFlags&BTrace::ETimestamp2Present)
  1.2781 +			printf("%10u ",(unsigned int)aTrace.iTimestamp2);
  1.2782 +		else
  1.2783 +			printf("           ");
  1.2784 +		}
  1.2785 +
  1.2786 +	if(aTrace.iFlags&BTrace::ETimestampPresent)
  1.2787 +		printf("%10u ",(unsigned int)Time(aTrace.iTimestamp-TimestampBase));
  1.2788 +	else
  1.2789 +		printf("           ");
  1.2790 +
  1.2791 +	// print PC...
  1.2792 +	if(aTrace.iFlags&BTrace::EPcPresent)
  1.2793 +		printf("%08x ",(unsigned int)aTrace.iPC);
  1.2794 +	else
  1.2795 +		printf("         ");
  1.2796 +
  1.2797 +	// print context...
  1.2798 +	if(ReportLevel>2)
  1.2799 +		{
  1.2800 +		Object::FullTraceNameBuf fullName;
  1.2801 +		fullName[0] = 0;
  1.2802 +		if(aTrace.iFlags&BTrace::EContextIdPresent)
  1.2803 +			aTrace.iContextID->FullTraceName(fullName);
  1.2804 +		printf("%-60s ",fullName);
  1.2805 +		}
  1.2806 +	else
  1.2807 +		{
  1.2808 +		Object::TraceNameBuf traceName;
  1.2809 +		traceName[0] = 0;
  1.2810 +		if(aTrace.iFlags&BTrace::EContextIdPresent)
  1.2811 +			aTrace.iContextID->TraceName(traceName);
  1.2812 +		printf("%-10s ",traceName);
  1.2813 +		}
  1.2814 +	// print trace categories...
  1.2815 +	const char* catName = CategoryName(aTrace.iCategory);
  1.2816 +	const char* subCatName = SubCategoryName(aTrace.iCategory,aTrace.iSubCategory);
  1.2817 +	if(ReportLevel>2)
  1.2818 +		printf("%18s %-24s ",catName,subCatName);
  1.2819 +	else
  1.2820 +		{
  1.2821 +		if(subCatName[0])
  1.2822 +			printf("%24s ",subCatName);
  1.2823 +		else
  1.2824 +			printf("%24s ",catName);
  1.2825 +		};
  1.2826 +
  1.2827 +	// print trace data contents...
  1.2828 +	TUint i;
  1.2829 +	for(i=0; i<aTrace.iDataSize; i+=4)
  1.2830 +		{
  1.2831 +		TUint32 data = aTrace.iData[i/sizeof(TUint32)];
  1.2832 +		if(i<16)
  1.2833 +			{
  1.2834 +			// first 4 words of data may have 'type' info set during pre-processing...
  1.2835 +			switch(aTrace.iDataTypes[i/sizeof(TUint32)])
  1.2836 +				{
  1.2837 +			case EDataTypeObject:
  1.2838 +				{
  1.2839 +				// data is an object, print "full name"[traceID]...
  1.2840 +				Object* object = (Object*)data;
  1.2841 +				if(ReportLevel>2)
  1.2842 +					{
  1.2843 +					Object::FullTraceNameBuf name;
  1.2844 +					object->FullTraceName(name);
  1.2845 +					printf("%s ",name);
  1.2846 +					}
  1.2847 +				else
  1.2848 +					{
  1.2849 +					Object::TraceNameBuf name;
  1.2850 +					object->TraceName(name);
  1.2851 +					printf("%s ",name);
  1.2852 +					}
  1.2853 +				}
  1.2854 +				continue;
  1.2855 +
  1.2856 +			case EDataTypeText:
  1.2857 +				{
  1.2858 +				// rest of trace is text...
  1.2859 +				TUint8* text = (TUint8*)aTrace.iData+i;
  1.2860 +				TUint8* textEnd = text+(aTrace.iDataSize-i);
  1.2861 +				TUint8 buffer[256];
  1.2862 +				TUint x=0;
  1.2863 +				while(text<textEnd && x<sizeof(buffer)-2)
  1.2864 +					{
  1.2865 +					TUint8 c = *text++;
  1.2866 +					TUint8 escape = 0;
  1.2867 +					switch(c)
  1.2868 +						{
  1.2869 +					case 9: escape = 't'; break;
  1.2870 +					case 10: escape = 'n'; break;
  1.2871 +					case 13: escape = 'r'; break;
  1.2872 +					default:
  1.2873 +						if(c<' ') c = '?';
  1.2874 +						break;
  1.2875 +						}
  1.2876 +					if(!escape)
  1.2877 +						buffer[x++] = c;
  1.2878 +					else
  1.2879 +						{
  1.2880 +						buffer[x++] = '\\';
  1.2881 +						buffer[x++] = escape;
  1.2882 +						}
  1.2883 +					}
  1.2884 +				buffer[x] = 0;
  1.2885 +				printf("\"%s\" ",buffer);
  1.2886 +				i = aTrace.iDataSize; // skip to end of data
  1.2887 +				}
  1.2888 +				continue;
  1.2889 +
  1.2890 +			default:
  1.2891 +				break;
  1.2892 +				}
  1.2893 +			}
  1.2894 +		// default to print data as hex value...
  1.2895 +		printf("%08x ",(unsigned int)data);
  1.2896 +		}
  1.2897 +
  1.2898 +	// print any extra data added by pre-processing...
  1.2899 +	for(i=0; i<2; ++i)
  1.2900 +		{
  1.2901 +		if(aTrace.iCalculatedData[i])
  1.2902 +			printf("{%u} ",(unsigned int)aTrace.iCalculatedData[i]);
  1.2903 +		}
  1.2904 +
  1.2905 +	if (aTrace.iError)
  1.2906 +		printf(" ***ERROR***");
  1.2907 +
  1.2908 +	// end-of-line finally!
  1.2909 +	printf("\n");
  1.2910 +	}
  1.2911 +
  1.2912 +
  1.2913 +void DumpAllTraces()
  1.2914 +	{
  1.2915 +	printf("\nREPORT: Trace Dump\n\n");
  1.2916 +	for(TUint i=0; i<NextTraceId; i++)
  1.2917 +		DumpTrace(*TraceIndex[i]);
  1.2918 +	printf("\n");
  1.2919 +	}
  1.2920 +
  1.2921 +
  1.2922 +void ReportErrors()
  1.2923 +	{
  1.2924 +	TBool errors = 	TraceFormatErrors || InterruptNestErrors || TraceFormatErrors 
  1.2925 +		|| ChunkErrors || CodeSegErrors || FastMutexNestErrors || KernelMemoryErrors
  1.2926 +		|| ProfilingSampleErrors;
  1.2927 +
  1.2928 +	if(!errors)
  1.2929 +		return;
  1.2930 +		
  1.2931 +	printf("\nREPORT: Trace Analysis Errors\n\n");
  1.2932 +	if(TraceFormatErrors)
  1.2933 +		printf("\tTrace Format Errors = %d\n",TraceFormatErrors);
  1.2934 +	if(InterruptNestErrors)
  1.2935 +		printf("\tInterrupt Nest Errors = %d\n",InterruptNestErrors);
  1.2936 +	if(FastMutexNestErrors)
  1.2937 +		printf("\tFast Mutex Nest Errors = %d\n",FastMutexNestErrors);
  1.2938 +	if(KernelMemoryErrors)
  1.2939 +		printf("\tKernel Memory Errors = %d\n",KernelMemoryErrors);
  1.2940 +	if(ChunkErrors)
  1.2941 +		printf("\tChunk Errors = %d\n",ChunkErrors);
  1.2942 +	if(CodeSegErrors)
  1.2943 +		printf("\tCodeSeg Errors = %d\n",CodeSegErrors);
  1.2944 +	if(ProfilingSampleErrors)
  1.2945 +		printf("\tProfiling Errors = %d\n",ProfilingSampleErrors);
  1.2946 +	printf("\n");
  1.2947 +	}
  1.2948 +
  1.2949 +
  1.2950 +/**
  1.2951 +The last trace record created has been preporcessed.
  1.2952 +*/
  1.2953 +void DoneTrace()
  1.2954 +	{
  1.2955 +	if(LastTrace)
  1.2956 +		TraceIndex[NextTraceId++] = (TraceRecord*)realloc(LastTrace,sizeof(TraceHeader)+LastTrace->iDataSize);
  1.2957 +	LastTrace = 0;
  1.2958 +	}
  1.2959 +
  1.2960 +
  1.2961 +/**
  1.2962 +Create a new trace record.
  1.2963 +*/
  1.2964 +TraceRecord* NewTrace()
  1.2965 +	{
  1.2966 +	if(NextTraceId>=TraceIndexSize)
  1.2967 +		{
  1.2968 +		TraceIndexSize += 1024;
  1.2969 +		TraceIndex = (TraceRecord**)realloc(TraceIndex,TraceIndexSize*sizeof(TraceIndex[0]));
  1.2970 +		ASSERT(TraceIndex);
  1.2971 +		}
  1.2972 +	DoneTrace();
  1.2973 +	LastTrace = (TraceRecord*)malloc(sizeof(TraceRecord));
  1.2974 +	return LastTrace;
  1.2975 +	}
  1.2976 +
  1.2977 +
  1.2978 +/**
  1.2979 +Delete all processed traces records.
  1.2980 +*/
  1.2981 +void ResetTrace()
  1.2982 +	{
  1.2983 +	DoneTrace();
  1.2984 +	TUint i;
  1.2985 +	for(i=0; i<NextTraceId; ++i)
  1.2986 +		free(TraceIndex[i]);
  1.2987 +	free(TraceIndex);
  1.2988 +	TraceIndex = 0;
  1.2989 +	TraceIndexSize = 0;
  1.2990 +	LastTrace = 0;
  1.2991 +	NextTraceId = 0;
  1.2992 +	TraceRecordId = 0;
  1.2993 +	}
  1.2994 +
  1.2995 +
  1.2996 +void EndTrace()
  1.2997 +	{
  1.2998 +	DoneTrace();
  1.2999 +	}
  1.3000 +
  1.3001 +
  1.3002 +/**
  1.3003 +Process an entire BTrace log capture.
  1.3004 +
  1.3005 +@param aInput		Pointer to function which will supply raw trace data.
  1.3006 +					Function should place up to aMaxSize bytes of data at aBuffer and return
  1.3007 +					the number of bytes stored. Return zero to indicate end of data.
  1.3008 +@param aReportLevel	Level of detail required of trace alaysis.
  1.3009 +					0 = brief summary, 1 = full summary, 2 = condensed trace dump, 3 = full trace dump.
  1.3010 +*/
  1.3011 +void ProcessAllTrace(TUint (*aInput)(TAny* aBuffer, TUint aMaxSize),TInt aReportLevel)
  1.3012 +	{
  1.3013 +	ReportLevel = aReportLevel;
  1.3014 +//	__UHEAP_MARK;
  1.3015 +	printf("Btrace Analysis:\n");
  1.3016 +	printf("\nTHIS TOOL IS UNOFFICIAL, UNSUPPORTED AND SUBJECT TO CHANGE WITHOUT NOTICE!\n");
  1.3017 +
  1.3018 +	StartTrace();
  1.3019 +	StartCpuUsage();
  1.3020 +	StartChunks();
  1.3021 +	StartCodeSegs();
  1.3022 +	StartFastMutex();
  1.3023 +	StartKernelMemory();
  1.3024 +	StartMetaTrace();
  1.3025 +	StartProfilingSample();
  1.3026 +
  1.3027 +	for(; !TraceBufferFilled ;)
  1.3028 +		{
  1.3029 +		// read more data...
  1.3030 +		TUint size = (*aInput)(TraceBuffer+TraceBufferSize, sizeof(TraceBuffer)-TraceBufferSize);
  1.3031 +		if(!size)
  1.3032 +			break;
  1.3033 +		TraceBufferSize += size;
  1.3034 +
  1.3035 +		// process all the complete traces in buffer...
  1.3036 +		const TUint8* data = TraceBuffer;
  1.3037 +		TUint sizeRemaining = TraceBufferSize;
  1.3038 +		while(sizeRemaining>BTrace::ESizeIndex)
  1.3039 +			{
  1.3040 +			TUint traceSize = (data[BTrace::ESizeIndex]+3)&~3;
  1.3041 +			if(traceSize>sizeRemaining)
  1.3042 +				break;
  1.3043 +
  1.3044 +			TraceRecord* trace = NewTrace();
  1.3045 +			ASSERT(trace);
  1.3046 +			if(!PreProcessTrace(*trace,data))
  1.3047 +				{
  1.3048 +				if (!TraceBufferFilled)
  1.3049 +					{
  1.3050 +					// bad trace, create dummy 1 byte trace record...
  1.3051 +					memset(trace,0,sizeof(*trace));
  1.3052 +					trace->iCategory = BTrace::EMetaTrace;
  1.3053 +					trace->iSubCategory = KJunkTraceSubcategory;
  1.3054 +					trace->iDataSize = 4;
  1.3055 +					trace->iData[0] = *data;
  1.3056 +					++TraceFormatErrors;
  1.3057 +					ErrorOnThisTrace = true;
  1.3058 +					traceSize = 1;
  1.3059 +					}
  1.3060 +				else // The buffer was filled so ignore the rest of the data
  1.3061 +					break;
  1.3062 +				}
  1.3063 +
  1.3064 +			data += traceSize;
  1.3065 +			sizeRemaining -= traceSize;
  1.3066 +			}
  1.3067 +		
  1.3068 +		if (!TraceBufferFilled)
  1.3069 +			{
  1.3070 +			memcpy(TraceBuffer,data,sizeRemaining);
  1.3071 +			TraceBufferSize = sizeRemaining;
  1.3072 +			}
  1.3073 +		else
  1.3074 +			{
  1.3075 +			// The trace buffer was filled so ignore the rest of the data
  1.3076 +			// and just read whatever is left to flush it from the btrace buffer.
  1.3077 +			while ((*aInput)(TraceBuffer, sizeof(TraceBuffer))){};
  1.3078 +			TraceBufferSize = 0;	// reset here so a format error isn't reported
  1.3079 +			}
  1.3080 +
  1.3081 +		if(aReportLevel<2)
  1.3082 +			ResetTrace(); // free up memory as we go along
  1.3083 +		}
  1.3084 +	EndTrace();
  1.3085 +	EndCpuUsage();
  1.3086 +
  1.3087 +	if(TraceBufferSize)
  1.3088 +		{
  1.3089 +		++TraceFormatErrors;
  1.3090 +		ErrorOnThisTrace = true;
  1.3091 +		}
  1.3092 +
  1.3093 +	ReportTimeUnits();
  1.3094 +	ReportErrors();
  1.3095 +	if(aReportLevel>=2)
  1.3096 +		DumpAllTraces();
  1.3097 +	if(ReportLevel>=1 || CpuUsagePresent)
  1.3098 +		{
  1.3099 +		ReportProcesses();
  1.3100 +		ReportThreads();
  1.3101 +		}
  1.3102 +	ReportChunks();
  1.3103 +	ReportKernelMemory();
  1.3104 +	ReportCodeSegs();
  1.3105 +	ReportFastMutex();
  1.3106 +	ReportSampleProfiling();
  1.3107 +
  1.3108 +	ResetTrace();
  1.3109 +	ObjectContainer::Reset();
  1.3110 +//	__UHEAP_MARKEND;
  1.3111 +	}
  1.3112 +
  1.3113 +