os/kernelhwsrv/kerneltest/e32test/nkernsa/kprintf.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/nkernsa/kprintf.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,788 @@
     1.4 +// Copyright (c) 2005-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 +// e32test\nkernsa\kprintf.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#define __E32CMN_H__
    1.22 +#include <nktest/utils.h>
    1.23 +#include "nk_priv.h"
    1.24 +
    1.25 +#undef EXPORT_C
    1.26 +#define EXPORT_C /* */
    1.27 +
    1.28 +class TVersion
    1.29 +	{
    1.30 +public:
    1.31 +	TInt8 iMajor;
    1.32 +	TInt8 iMinor;
    1.33 +	TInt16 iBuild;
    1.34 +	};
    1.35 +
    1.36 +class TDesC;
    1.37 +
    1.38 +#include <e32rom.h>
    1.39 +
    1.40 +extern void DebugPrint(const char*, int);
    1.41 +
    1.42 +/**
    1.43 +Returns the active debug mask obtained by logically ANDing the global debug mask
    1.44 +in the super page with the per-thread debug mask in the current DThread object.
    1.45 +
    1.46 +If the current thread is not a symbian OS thread the global debug mask is used.
    1.47 +
    1.48 +Only supports the first 32 global debug trace bits.
    1.49 +
    1.50 +@return The debug mask.
    1.51 +*/
    1.52 +extern "C" {
    1.53 +extern TLinAddr RomHeaderAddress;
    1.54 +}
    1.55 +EXPORT_C TInt KDebugMask()
    1.56 +	{
    1.57 +	const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
    1.58 +	return rh.iTraceMask[0];
    1.59 +	}
    1.60 +
    1.61 +
    1.62 +
    1.63 +/**
    1.64 +Returns the state (ETrue or EFalse) of given bit in the active debug mask
    1.65 +which is obtained by logically ANDing the global debug mask in the super page 
    1.66 +with the per-thread debug mask in the current DThread object.
    1.67 +
    1.68 +If the current thread is not a symbian OS thread the global debug mask is used.
    1.69 +
    1.70 +@return The state of the debug mask bit number.
    1.71 +*/
    1.72 +
    1.73 +EXPORT_C TBool KDebugNum(TInt aBitNum)
    1.74 +	{
    1.75 +#if 1
    1.76 +	const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
    1.77 +	TInt m = 0;
    1.78 +
    1.79 +	// special case for KALWAYS
    1.80 +	if (aBitNum == KALWAYS)
    1.81 +		{
    1.82 +		m = rh.iTraceMask[0] ||
    1.83 +			rh.iTraceMask[1] ||
    1.84 +			rh.iTraceMask[2] ||
    1.85 +			rh.iTraceMask[3] ||
    1.86 +			rh.iTraceMask[4] ||
    1.87 +			rh.iTraceMask[5] ||
    1.88 +			rh.iTraceMask[6] ||
    1.89 +		    rh.iTraceMask[7];
    1.90 +		}
    1.91 +	else if  ( (aBitNum > KMAXTRACE) || (aBitNum < 0) )
    1.92 +		m = 0;
    1.93 +	else
    1.94 +		{
    1.95 +		TInt index = aBitNum >> 5;
    1.96 +		m = rh.iTraceMask[index];
    1.97 +		m &= 1 << (aBitNum & 31);
    1.98 +		}
    1.99 +
   1.100 +	return (m != 0);
   1.101 +#else
   1.102 +	return 1;
   1.103 +#endif
   1.104 +	}
   1.105 +
   1.106 +extern "C" unsigned int strlen(const char* s)
   1.107 +	{
   1.108 +	const char* s0 = s;
   1.109 +	while(*s++) {}
   1.110 +	return s - s0 - 1;
   1.111 +	}
   1.112 +
   1.113 +int appendstr(char* out, int outlen, const char* s)
   1.114 +	{
   1.115 +	if (!s)
   1.116 +		s = "NULL";
   1.117 +	char* d = out + outlen;
   1.118 +	while(*s)
   1.119 +		*d++ = *s++;
   1.120 +	return d - out;
   1.121 +	}
   1.122 +
   1.123 +int AppendNumBase10U(char* out, unsigned int val, int width, int fill)
   1.124 +	{
   1.125 +	int len = 10;
   1.126 +	if (val < 10)
   1.127 +		len = 1;
   1.128 +	else if (val < 100)
   1.129 +		len = 2;
   1.130 +	else if (val < 1000)
   1.131 +		len = 3;
   1.132 +	else if (val < 10000)
   1.133 +		len = 4;
   1.134 +	else if (val < 100000)
   1.135 +		len = 5;
   1.136 +	else if (val < 1000000)
   1.137 +		len = 6;
   1.138 +	else if (val < 10000000)
   1.139 +		len = 7;
   1.140 +	else if (val < 100000000)
   1.141 +		len = 8;
   1.142 +	else if (val < 1000000000)
   1.143 +		len = 9;
   1.144 +	int w = (len < width) ? width : len;
   1.145 +	char* d = out + w;
   1.146 +	do	{
   1.147 +		*--d = (char)(48 + val%10);
   1.148 +		val /= 10;
   1.149 +		} while(val);
   1.150 +	for (; d > out; *--d = (char)fill ) {}
   1.151 +	return w;
   1.152 +	}
   1.153 +
   1.154 +int AppendNumBase10S(char* out, int sval, int width, int fill)
   1.155 +	{
   1.156 +	int sign = (sval<0) ? 1 : 0;
   1.157 +	unsigned val = sign ? unsigned(-sval) : unsigned(sval);
   1.158 +	int len = 10;
   1.159 +	if (val < 10)
   1.160 +		len = 1;
   1.161 +	else if (val < 100)
   1.162 +		len = 2;
   1.163 +	else if (val < 1000)
   1.164 +		len = 3;
   1.165 +	else if (val < 10000)
   1.166 +		len = 4;
   1.167 +	else if (val < 100000)
   1.168 +		len = 5;
   1.169 +	else if (val < 1000000)
   1.170 +		len = 6;
   1.171 +	else if (val < 10000000)
   1.172 +		len = 7;
   1.173 +	else if (val < 100000000)
   1.174 +		len = 8;
   1.175 +	else if (val < 1000000000)
   1.176 +		len = 9;
   1.177 +	if (sign) ++len;
   1.178 +	int w = (len < width) ? width : len;
   1.179 +	char* d = out + w;
   1.180 +	do	{
   1.181 +		*--d = (char)(48 + val%10);
   1.182 +		val /= 10;
   1.183 +		} while(val);
   1.184 +	if (sign) *--d = '-';
   1.185 +	for (; d > out; *--d = (char)fill ) {}
   1.186 +	return w;
   1.187 +	}
   1.188 +
   1.189 +int AppendNumBase16(char* out, unsigned int val, int width, int fill)
   1.190 +	{
   1.191 +	int len = 8;
   1.192 +	if (val < 0x10)
   1.193 +		len = 1;
   1.194 +	else if (val < 0x100)
   1.195 +		len = 2;
   1.196 +	else if (val < 0x1000)
   1.197 +		len = 3;
   1.198 +	else if (val < 0x10000)
   1.199 +		len = 4;
   1.200 +	else if (val < 0x100000)
   1.201 +		len = 5;
   1.202 +	else if (val < 0x1000000)
   1.203 +		len = 6;
   1.204 +	else if (val < 0x10000000)
   1.205 +		len = 7;
   1.206 +	int w = (len < width) ? width : len;
   1.207 +	char* d = out + w;
   1.208 +	do	{
   1.209 +		char c = (char)(48 + (val&15));
   1.210 +		if (c>'9') c+=0x07;
   1.211 +		*--d = c;
   1.212 +		val >>= 4;
   1.213 +		} while(val);
   1.214 +	for (; d > out; *--d = (char)fill ) {}
   1.215 +	return w;
   1.216 +	}
   1.217 +
   1.218 +int AppendNumBase16L(char* out, Uint64 val, int width, int fill)
   1.219 +	{
   1.220 +	TUint vl = (TUint)val;
   1.221 +	TUint vh = (TUint)(val>>32);
   1.222 +	TInt l = 0;
   1.223 +	if (vh)
   1.224 +		{
   1.225 +		l = AppendNumBase16(out, vh, width-8, fill);
   1.226 +		l += AppendNumBase16(out+l, vl, 8, fill);
   1.227 +		}
   1.228 +	else
   1.229 +		l = AppendNumBase16(out, vl, width, fill);
   1.230 +	return l;
   1.231 +	}
   1.232 +
   1.233 +
   1.234 +
   1.235 +/**
   1.236 +Formats and appends text to the specified narrow descriptor without making any
   1.237 +executive calls.
   1.238 +
   1.239 +The function takes a format string and a variable number of arguments. The
   1.240 +format specifiers in the format string are used to interpret and the arguments.
   1.241 +
   1.242 +Format directives have the following syntax:
   1.243 +@code
   1.244 +<format-directive> ::= 
   1.245 +	"%" [<padding-character>] [<field-width>] [<long-flag>] <conversion-specifier>
   1.246 +@endcode
   1.247 +
   1.248 +If a field width is specified and the width of the formatted field is less
   1.249 +than this width, then the field is padded with the padding character.
   1.250 +The only supported padding characters are ' ' (default) and '0'.
   1.251 +
   1.252 +The long flag specifier ('l') modifies the semantic of the conversion
   1.253 +specifier as explained below.
   1.254 +
   1.255 +The possible values for the conversion specifiers, the long flag and the way in
   1.256 +which arguments are interpreted, are as follows:
   1.257 +@code
   1.258 +d	Interpret the argument as a TInt decimal representation
   1.259 +ld	NOT SUPPORTED - use lx instead
   1.260 +u	Interpret the argument as a TUint decimal representation
   1.261 +lu	NOT SUPPORTED - use lx instead
   1.262 +x	Interpret the argument as a TUint hexadecimal representation
   1.263 +X	As above
   1.264 +lx	Interpret the argument as a Uint64 hexadecimal representation
   1.265 +lX	As above
   1.266 +c	Interpret the argument as a character
   1.267 +s	Interpret the argument as a pointer to narrow C string
   1.268 +ls	Interpret the argument as a pointer to narrow C string
   1.269 +S 	Interpret the argument as a pointer to narrow descriptor or NULL
   1.270 +lS	NOT SUPPORTED - use S instead
   1.271 +O	Interpret the argument as a pointer to DObject or NULL 
   1.272 +	Generates the object full name or 'NULL'
   1.273 +o	Interpret the argument as a pointer to DObject or NULL
   1.274 +	Generates the object name or 'NULL'
   1.275 +M	Interpret the argument as a pointer to a fast mutex or NULL
   1.276 +	Generates the name, if this is a well-known fast mutex, address otherwise
   1.277 +m	Interpret the argument as a pointer to a fast semaphore or NULL
   1.278 +	Generates the owning thread name, if this is a well-known fast semaphore, address otherwise
   1.279 +T	Interpret the argument as a pointer to a nanothread or NULL 
   1.280 +	Generates the full name, if this is a Symbian OS thread, address otherwise
   1.281 +C	Interpret the argument as a pointer to a DCodeSeg or NULL
   1.282 +	Generates the filename and module version number
   1.283 +@endcode
   1.284 +
   1.285 +The function can be called from the interrupt context, but extreme caution is advised as it
   1.286 +may require a lot of stack space and interrupt stacks are very small.
   1.287 +
   1.288 +@param aDes 	Narrow descriptor that must be big-enough to hold result
   1.289 +@param aFmt 	The format string
   1.290 +@param aList 	A variable number of arguments to be converted to text as dictated by the format string
   1.291 +
   1.292 +@pre Calling thread can be either in a critical section or not.
   1.293 +@pre Interrupts must be enabled.
   1.294 +@pre Kernel must be unlocked
   1.295 +@pre No fast mutex can be held.
   1.296 +@pre Call in any context.
   1.297 +@pre Suitable for use in a device driver
   1.298 +
   1.299 +@panic The set of panics that can be raised when appending data to descriptors.
   1.300 +
   1.301 +@see   TDes8
   1.302 +*/
   1.303 +EXPORT_C TInt AppendFormat(char* aOut, const char* aFmt, VA_LIST aList)
   1.304 +	{
   1.305 +#define NEXT_FMT(c,p) if (((c)=*(p)++)==0) return outLen;
   1.306 +
   1.307 +	TInt outLen = 0;
   1.308 +	FOREVER
   1.309 +		{
   1.310 +		char c;
   1.311 +		NEXT_FMT(c,aFmt);
   1.312 +		if (c=='%')
   1.313 +			{
   1.314 +			char fill=' ';
   1.315 +			TInt width=0;
   1.316 +			TBool long_arg=EFalse;
   1.317 +			TBool ok=ETrue;
   1.318 +			NEXT_FMT(c,aFmt);
   1.319 +			if (c=='0')
   1.320 +				{
   1.321 +				fill='0';
   1.322 +				NEXT_FMT(c,aFmt);
   1.323 +				}
   1.324 +			while(c>='0' && c<='9')
   1.325 +				{
   1.326 +				width=width*10+c-'0';
   1.327 +				NEXT_FMT(c,aFmt);
   1.328 +				}
   1.329 +			if (c=='l')
   1.330 +				{
   1.331 +				long_arg=ETrue;
   1.332 +				NEXT_FMT(c,aFmt);
   1.333 +				}
   1.334 +			switch(c)
   1.335 +				{
   1.336 +				case 'd':
   1.337 +					{
   1.338 +					if (long_arg)
   1.339 +						ok=EFalse;
   1.340 +					else
   1.341 +						{
   1.342 +						TInt val=VA_ARG(aList,TInt);
   1.343 +						char* d = aOut + outLen;
   1.344 +						outLen += AppendNumBase10S(d, val, width, fill);
   1.345 +						}
   1.346 +					break;
   1.347 +					}
   1.348 +				case 'u':
   1.349 +					{
   1.350 +					if (long_arg)
   1.351 +						ok=EFalse;
   1.352 +					else
   1.353 +						{
   1.354 +						TUint val=VA_ARG(aList,TUint);
   1.355 +						char* d = aOut + outLen;
   1.356 +						outLen += AppendNumBase10U(d, val, width, fill);
   1.357 +						}
   1.358 +					break;
   1.359 +					}
   1.360 +				case 'x':
   1.361 +				case 'X':
   1.362 +					{
   1.363 +					if (long_arg)
   1.364 +						{
   1.365 +						Uint64 val=VA_ARG(aList,Uint64);
   1.366 +						char* d = aOut + outLen;
   1.367 +						outLen += AppendNumBase16L(d, val, width, fill);
   1.368 +						}
   1.369 +					else
   1.370 +						{
   1.371 +						TUint val=VA_ARG(aList,TUint);
   1.372 +						char* d = aOut + outLen;
   1.373 +						outLen += AppendNumBase16(d, val, width, fill);
   1.374 +						}
   1.375 +					break;
   1.376 +					}
   1.377 +				case 's':
   1.378 +					{
   1.379 +					const char* s = VA_ARG(aList,const char*);
   1.380 +					outLen = appendstr(aOut, outLen, s);
   1.381 +					break;
   1.382 +					}
   1.383 +				case 'M':		// fast mutex
   1.384 +					{
   1.385 +					NFastMutex* pM=VA_ARG(aList,NFastMutex*);
   1.386 +					outLen = appendstr(aOut, outLen, "M");
   1.387 +					if (!pM)
   1.388 +						outLen = appendstr(aOut, outLen, 0);
   1.389 +					else if (pM==&TheScheduler.iLock)
   1.390 +						outLen = appendstr(aOut, outLen, "SYSLOCK");
   1.391 +					else
   1.392 +						outLen += AppendNumBase16(aOut+outLen, (TUint)pM, 8, '0');
   1.393 +					break;
   1.394 +					}
   1.395 +				case 'm':		// fast semaphore
   1.396 +					{
   1.397 +					NFastSemaphore* pS=VA_ARG(aList,NFastSemaphore*);
   1.398 +					outLen = appendstr(aOut, outLen, "S");
   1.399 +					if (!pS)
   1.400 +						outLen = appendstr(aOut, outLen, 0);
   1.401 +					else
   1.402 +						outLen += AppendNumBase16(aOut+outLen, (TUint)pS, 8, '0');
   1.403 +					break;
   1.404 +					}
   1.405 +				case 'T':		// NKERN thread
   1.406 +					{
   1.407 +					NThread* pN=VA_ARG(aList,NThread*);
   1.408 +#ifdef __SMP__
   1.409 +					if (pN && pN->iNThreadBaseSpare8)
   1.410 +						outLen = appendstr(aOut, outLen, (const char*)pN->iNThreadBaseSpare8);
   1.411 +#else
   1.412 +					if (pN && pN->iSpare8)
   1.413 +						outLen = appendstr(aOut, outLen, (const char*)pN->iSpare8);
   1.414 +#endif
   1.415 +					else
   1.416 +						{
   1.417 +						outLen = appendstr(aOut, outLen, "T");
   1.418 +						if (!pN)
   1.419 +							outLen = appendstr(aOut, outLen, 0);
   1.420 +						else
   1.421 +							outLen += AppendNumBase16(aOut+outLen, (TUint)pN, 8, '0');
   1.422 +						}
   1.423 +					break;
   1.424 +					}
   1.425 +#ifdef __SMP__
   1.426 +				case 'G':		// NKERN thread group
   1.427 +					{
   1.428 +					NThreadGroup* pG=VA_ARG(aList,NThreadGroup*);
   1.429 +//					if (pG && pG->iNThreadBaseSpare8)
   1.430 +//						outLen = appendstr(aOut, outLen, (const char*)pG->iNThreadBaseSpare8);
   1.431 +//					else
   1.432 +						{
   1.433 +						outLen = appendstr(aOut, outLen, "G");
   1.434 +						if (!pG)
   1.435 +							outLen = appendstr(aOut, outLen, 0);
   1.436 +						else
   1.437 +							outLen += AppendNumBase16(aOut+outLen, (TUint)pG, 8, '0');
   1.438 +						}
   1.439 +					break;
   1.440 +					}
   1.441 +#endif
   1.442 +				case 'c':
   1.443 +					c=(char)VA_ARG(aList,TUint);
   1.444 +					// fall through
   1.445 +				default:
   1.446 +					ok=EFalse;
   1.447 +					break;
   1.448 +				}
   1.449 +				if (ok)
   1.450 +					continue;
   1.451 +			}
   1.452 +		aOut[outLen++]=c;
   1.453 +		}
   1.454 +	return outLen;
   1.455 +	}
   1.456 +
   1.457 +
   1.458 +/**
   1.459 +Prints a formatted string on the debug port.
   1.460 +
   1.461 +The function uses Kern::AppendFormat() to do the formatting.
   1.462 +
   1.463 +Although it is safe to call this function from an ISR, it polls the output
   1.464 +serial port and may take a long time to complete, invalidating any
   1.465 +real-time guarantee.
   1.466 +
   1.467 +If called from an ISR, it is possible for output text to be intermingled
   1.468 +with other output text if one set of output interrupts or preempts another.
   1.469 +
   1.470 +Some of the formatting options may not work inside an ISR.
   1.471 +
   1.472 +Be careful not to use a string that is too long to fit onto the stack.
   1.473 +
   1.474 +@param aFmt The format string. This must not be longer than 256 characters.
   1.475 +@param ...	A variable number of arguments to be converted to text as dictated
   1.476 +            by the format string.
   1.477 +
   1.478 +@pre Calling thread can either be in a critical section or not.
   1.479 +@pre Interrupts must be enabled.
   1.480 +@pre Kernel must be unlocked
   1.481 +@pre No fast mutex can be held.
   1.482 +@pre Call in any context.
   1.483 +@pre Suitable for use in a device driver
   1.484 +
   1.485 +@see Kern::AppendFormat()
   1.486 +*/
   1.487 +extern "C" void puts(const char* s);
   1.488 +extern "C" void prthex8(TUint);
   1.489 +EXPORT_C void KPrintf(const char* aFmt, ...)
   1.490 +	{
   1.491 +	extern TUint32 __tr();
   1.492 +
   1.493 +	char printBuf[256];
   1.494 +	VA_LIST list;
   1.495 +	VA_START(list,aFmt);
   1.496 +	int c = AppendFormat(printBuf+2,aFmt,list) + 2;
   1.497 +	printBuf[c++] = 13;
   1.498 +	printBuf[c++] = 10;
   1.499 +	printBuf[0] = __trace_cpu_num()+48;
   1.500 +	printBuf[1] = 58;
   1.501 +
   1.502 +	if (NKern::Crashed())
   1.503 +		{
   1.504 +		DebugPrint(printBuf,c);
   1.505 +		return;
   1.506 +		}
   1.507 +
   1.508 +	// Handle BTrace first...
   1.509 +	TUint category = BTrace::EKernPrintf;
   1.510 +	TInt result = BTraceContextBig(category,0,0,printBuf,c);
   1.511 +
   1.512 +	NThread* csThread = 0;
   1.513 +	NThread* curr = NKern::CurrentThread();
   1.514 +	if (curr && NKern::CurrentContext() == NKern::EThread && !NKern::KernelLocked())
   1.515 +		{
   1.516 +		csThread = curr;
   1.517 +		NKern::_ThreadEnterCS();
   1.518 +		}
   1.519 +	if (!result)
   1.520 +		{
   1.521 +		DebugPrint(printBuf,c);
   1.522 +		}
   1.523 +	if (csThread)
   1.524 +		{
   1.525 +		NKern::_ThreadLeaveCS();
   1.526 +		}
   1.527 +	}
   1.528 +
   1.529 +
   1.530 +
   1.531 +/******************************************************************************
   1.532 + * BTRACE SUPPORT
   1.533 + ******************************************************************************/
   1.534 +
   1.535 +#define BTRACE_INCLUDE_TIMESTAMPS
   1.536 +
   1.537 +TAny* BTraceBufferBase[KMaxCpus];
   1.538 +TAny* BTraceBufferEnd[KMaxCpus];
   1.539 +TAny* BTraceBufferPtr[KMaxCpus];	// next free position
   1.540 +TBool BTraceBufferWrap[KMaxCpus];
   1.541 +TBool BTraceActive;
   1.542 +
   1.543 +//const TUint KBTraceBufferSize = 16 * 1024 * 1024;
   1.544 +const TUint KBTraceBufferSize = 1 * 1024 * 1024;
   1.545 +const TUint KBTraceSlotSize = 128;
   1.546 +
   1.547 +__ASSERT_COMPILE(KBTraceSlotSize >= (TUint)KMaxBTraceRecordSize);
   1.548 +
   1.549 +TBool HandleBTrace(TUint32 aHeader,TUint32 aHeader2,const TUint32 aContext,const TUint32 a1,const TUint32 a2,const TUint32 a3,const TUint32 aExtra,const TUint32 aPc)
   1.550 +	{
   1.551 +#ifdef __SMP__
   1.552 +	// Header 2 always present and contains CPU number
   1.553 +	// If Header2 not originally there, add 4 to size
   1.554 +	TInt cpu = NKern::CurrentCpu();
   1.555 +	if (!(aHeader&(BTrace::EHeader2Present<<BTrace::EFlagsIndex*8)))
   1.556 +		aHeader += (4<<BTrace::ESizeIndex*8) + (BTrace::EHeader2Present<<BTrace::EFlagsIndex*8), aHeader2=0;
   1.557 +	aHeader2 = (aHeader2 &~ BTrace::ECpuIdMask) | (cpu<<20);
   1.558 +#else
   1.559 +	TInt cpu = 0;
   1.560 +#endif
   1.561 +#ifdef BTRACE_INCLUDE_TIMESTAMPS
   1.562 +	// Add timestamp to trace...
   1.563 +#if defined(__EPOC32__) && defined(__CPU_X86)
   1.564 +	aHeader += 8<<BTrace::ESizeIndex*8;
   1.565 +	aHeader |= BTrace::ETimestampPresent<<BTrace::EFlagsIndex*8 | BTrace::ETimestamp2Present<<BTrace::EFlagsIndex*8;
   1.566 +	TUint64 timeStamp = fast_counter();
   1.567 +#else
   1.568 +	aHeader += 4<<BTrace::ESizeIndex*8;
   1.569 +	aHeader |= BTrace::ETimestampPresent<<BTrace::EFlagsIndex*8;
   1.570 +	TUint32 timeStamp = NKern::FastCounter();
   1.571 +#endif
   1.572 +#endif
   1.573 +	TUint size = (aHeader+3)&0xfc;
   1.574 +
   1.575 +#if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   1.576 +	TInt irq = NKern::DisableAllInterrupts();
   1.577 +#endif
   1.578 +
   1.579 +	TUint32* src;
   1.580 +	TUint32* dst = (TUint32*)BTraceBufferPtr[cpu];
   1.581 +
   1.582 +	if (!BTraceActive)
   1.583 +		goto trace_off;
   1.584 +
   1.585 +	BTraceBufferPtr[cpu] = ((TUint8*)BTraceBufferPtr[cpu]) + KBTraceSlotSize;
   1.586 +	if (BTraceBufferPtr[cpu] >= BTraceBufferEnd[cpu])
   1.587 +		{
   1.588 +		BTraceBufferPtr[cpu] = BTraceBufferBase[cpu];
   1.589 +		BTraceBufferWrap[cpu] = TRUE;
   1.590 +		}
   1.591 +
   1.592 +	size >>= 2; // we are now counting words, not bytes
   1.593 +
   1.594 +	if (dst+size > (TUint32*)BTraceBufferEnd[cpu])
   1.595 +		goto trace_dropped;
   1.596 +
   1.597 +	{
   1.598 +	// store first word of trace...
   1.599 +	TUint w = aHeader;
   1.600 +	--size;
   1.601 +	*dst++ = w;
   1.602 +
   1.603 +#ifndef __SMP__
   1.604 +	if (aHeader&(BTrace::EHeader2Present<<(BTrace::EFlagsIndex*8)))
   1.605 +#endif
   1.606 +		{
   1.607 +		w = aHeader2;
   1.608 +		--size;
   1.609 +		*dst++ = w;
   1.610 +		}
   1.611 +
   1.612 +#ifdef BTRACE_INCLUDE_TIMESTAMPS
   1.613 +	// store timestamp...
   1.614 +#if defined(__EPOC32__) && defined(__CPU_X86)
   1.615 +	--size;
   1.616 +	*dst++ = TUint32(timeStamp);
   1.617 +	--size;
   1.618 +	*dst++ = TUint32(timeStamp>>32);
   1.619 +#else
   1.620 +	--size;
   1.621 +	*dst++ = timeStamp;
   1.622 +#endif
   1.623 +#endif
   1.624 +
   1.625 +	if(aHeader&(BTrace::EContextIdPresent<<(BTrace::EFlagsIndex*8)))
   1.626 +		{
   1.627 +		w = aContext;
   1.628 +		--size;
   1.629 +		*dst++ = w;
   1.630 +		}
   1.631 +
   1.632 +	if(aHeader&(BTrace::EPcPresent<<(BTrace::EFlagsIndex*8)))
   1.633 +		{
   1.634 +		w = aPc;
   1.635 +		--size;
   1.636 +		*dst++ = w;
   1.637 +		}
   1.638 +
   1.639 +	if(aHeader&(BTrace::EExtraPresent<<(BTrace::EFlagsIndex*8)))
   1.640 +		{
   1.641 +		w = aExtra;
   1.642 +		--size;
   1.643 +		*dst++ = w;
   1.644 +		}
   1.645 +
   1.646 +	// store remaining words of trace...
   1.647 +	if(size)
   1.648 +		{
   1.649 +		w = a1;
   1.650 +		--size;
   1.651 +		*dst++ = w;
   1.652 +		if(size)
   1.653 +			{
   1.654 +			w = a2;
   1.655 +			--size;
   1.656 +			*dst++ = w;
   1.657 +			if(size)
   1.658 +				{
   1.659 +				if(size==1)
   1.660 +					{
   1.661 +					w = a3;
   1.662 +					*dst++ = w;
   1.663 +					}
   1.664 +				else
   1.665 +					{
   1.666 +					src = (TUint32*)a3;
   1.667 +					do
   1.668 +						{
   1.669 +						w = *src++;
   1.670 +						--size;
   1.671 +						*dst++ = w;
   1.672 +						}
   1.673 +					while(size);
   1.674 +					}
   1.675 +				}
   1.676 +			}
   1.677 +		}
   1.678 +	}
   1.679 +
   1.680 +#if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   1.681 +	NKern::RestoreInterrupts(irq);
   1.682 +#endif
   1.683 +	return ETrue;
   1.684 +
   1.685 +
   1.686 +trace_dropped:
   1.687 +#if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   1.688 +	NKern::RestoreInterrupts(irq);
   1.689 +#endif
   1.690 +	return ETrue;
   1.691 +
   1.692 +trace_off:
   1.693 +#if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   1.694 +	NKern::RestoreInterrupts(irq);
   1.695 +#endif
   1.696 +	return ETrue;
   1.697 +//	return EFalse;
   1.698 +	}
   1.699 +
   1.700 +
   1.701 +TBool SBTraceData::CheckFilter2(TUint32)
   1.702 +	{
   1.703 +	return TRUE;
   1.704 +	}
   1.705 +
   1.706 +void InitBTraceHandler()
   1.707 +	{
   1.708 +	TInt cpu;
   1.709 +#ifdef __SMP__
   1.710 +	TInt ncpus = NKern::NumberOfCpus();
   1.711 +#else
   1.712 +	TInt ncpus = 1;
   1.713 +#endif
   1.714 +	for (cpu=0; cpu<ncpus; ++cpu)
   1.715 +		{
   1.716 +		BTraceBufferBase[cpu] = malloc(KBTraceBufferSize);
   1.717 +		TEST_OOM(BTraceBufferBase[cpu]);
   1.718 +		BTraceBufferEnd[cpu] = ((TUint8*)BTraceBufferBase[cpu]) + KBTraceBufferSize;
   1.719 +
   1.720 +		TUint8* p = (TUint8*)BTraceBufferBase[cpu];
   1.721 +
   1.722 +		BTraceBufferPtr[cpu] = p;
   1.723 +		BTraceBufferWrap[cpu] = FALSE;
   1.724 +
   1.725 +		TEST_PRINT2("BTraceBufferBase[%d] = %08x", cpu, BTraceBufferBase[cpu]);
   1.726 +		TEST_PRINT2("BTraceBufferEnd[%d]  = %08x", cpu, BTraceBufferEnd[cpu]);
   1.727 +		TEST_PRINT2("BTraceBufferPtr[%d]  = %08x", cpu, BTraceBufferPtr[cpu]);
   1.728 +		}
   1.729 +
   1.730 +	SBTraceData& traceData = BTraceData;
   1.731 +	traceData.iHandler = &HandleBTrace;
   1.732 +//	traceData.iFilter[BTrace::EKernPrintf] = 1;
   1.733 +	traceData.iFilter[BTrace::EThreadIdentification] = 1;
   1.734 +	traceData.iFilter[BTrace::ECpuUsage] = 1;
   1.735 +	traceData.iFilter[0xdd] = 1;
   1.736 +//	memset(traceData.iFilter, 1, sizeof(traceData.iFilter));
   1.737 +	}
   1.738 +
   1.739 +void DumpBTraceBuffer()
   1.740 +	{
   1.741 +	BTraceActive = FALSE;
   1.742 +
   1.743 +	TInt cpu;
   1.744 +#ifdef __SMP__
   1.745 +	TInt ncpus = NKern::NumberOfCpus();
   1.746 +#else
   1.747 +	TInt ncpus = 1;
   1.748 +#endif
   1.749 +	char x[64];
   1.750 +	for (cpu=0; cpu<=ncpus; ++cpu)
   1.751 +		{
   1.752 +		memset(x, cpu+0xc0, sizeof(x));
   1.753 +		DebugPrint(x, sizeof(x));
   1.754 +		if (cpu == ncpus)
   1.755 +			break;
   1.756 +		const char* b = (const char*)BTraceBufferBase[cpu];
   1.757 +		const char* e = (const char*)BTraceBufferEnd[cpu];
   1.758 +		const char* f = (const char*)BTraceBufferPtr[cpu];
   1.759 +		const char* p = BTraceBufferWrap[cpu] ? f : b;
   1.760 +		if (!p || (!BTraceBufferWrap[cpu] && p==f))
   1.761 +			continue;
   1.762 +		do	{
   1.763 +			TInt size = *(const TUint8*)p;
   1.764 +			size = (size + 3) &~ 3;
   1.765 +			DebugPrint(p, size);
   1.766 +			p+=KBTraceSlotSize;
   1.767 +			if (p==e)
   1.768 +				p = b;
   1.769 +			} while (p!=f);
   1.770 +		}
   1.771 +
   1.772 +	SBTraceData& traceData = BTraceData;
   1.773 +	memset(traceData.iFilter, 0, sizeof(traceData.iFilter));
   1.774 +	traceData.iHandler = 0;
   1.775 +	TEST_PRINT("\r\n\nBTrace Dump Complete");
   1.776 +	}
   1.777 +
   1.778 +void StartBTrace()
   1.779 +	{
   1.780 +	BTraceActive = TRUE;
   1.781 +	}
   1.782 +
   1.783 +void StopBTrace()
   1.784 +	{
   1.785 +	BTraceActive = FALSE;
   1.786 +	}
   1.787 +
   1.788 +TInt KCrazySchedulerEnabled()
   1.789 +	{
   1.790 +	return 0;
   1.791 +	}