os/kernelhwsrv/kerneltest/e32test/nkernsa/kprintf.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\nkernsa\kprintf.cpp
    15 // 
    16 //
    17 
    18 #define __E32CMN_H__
    19 #include <nktest/utils.h>
    20 #include "nk_priv.h"
    21 
    22 #undef EXPORT_C
    23 #define EXPORT_C /* */
    24 
    25 class TVersion
    26 	{
    27 public:
    28 	TInt8 iMajor;
    29 	TInt8 iMinor;
    30 	TInt16 iBuild;
    31 	};
    32 
    33 class TDesC;
    34 
    35 #include <e32rom.h>
    36 
    37 extern void DebugPrint(const char*, int);
    38 
    39 /**
    40 Returns the active debug mask obtained by logically ANDing the global debug mask
    41 in the super page with the per-thread debug mask in the current DThread object.
    42 
    43 If the current thread is not a symbian OS thread the global debug mask is used.
    44 
    45 Only supports the first 32 global debug trace bits.
    46 
    47 @return The debug mask.
    48 */
    49 extern "C" {
    50 extern TLinAddr RomHeaderAddress;
    51 }
    52 EXPORT_C TInt KDebugMask()
    53 	{
    54 	const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
    55 	return rh.iTraceMask[0];
    56 	}
    57 
    58 
    59 
    60 /**
    61 Returns the state (ETrue or EFalse) of given bit in the active debug mask
    62 which is obtained by logically ANDing the global debug mask in the super page 
    63 with the per-thread debug mask in the current DThread object.
    64 
    65 If the current thread is not a symbian OS thread the global debug mask is used.
    66 
    67 @return The state of the debug mask bit number.
    68 */
    69 
    70 EXPORT_C TBool KDebugNum(TInt aBitNum)
    71 	{
    72 #if 1
    73 	const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
    74 	TInt m = 0;
    75 
    76 	// special case for KALWAYS
    77 	if (aBitNum == KALWAYS)
    78 		{
    79 		m = rh.iTraceMask[0] ||
    80 			rh.iTraceMask[1] ||
    81 			rh.iTraceMask[2] ||
    82 			rh.iTraceMask[3] ||
    83 			rh.iTraceMask[4] ||
    84 			rh.iTraceMask[5] ||
    85 			rh.iTraceMask[6] ||
    86 		    rh.iTraceMask[7];
    87 		}
    88 	else if  ( (aBitNum > KMAXTRACE) || (aBitNum < 0) )
    89 		m = 0;
    90 	else
    91 		{
    92 		TInt index = aBitNum >> 5;
    93 		m = rh.iTraceMask[index];
    94 		m &= 1 << (aBitNum & 31);
    95 		}
    96 
    97 	return (m != 0);
    98 #else
    99 	return 1;
   100 #endif
   101 	}
   102 
   103 extern "C" unsigned int strlen(const char* s)
   104 	{
   105 	const char* s0 = s;
   106 	while(*s++) {}
   107 	return s - s0 - 1;
   108 	}
   109 
   110 int appendstr(char* out, int outlen, const char* s)
   111 	{
   112 	if (!s)
   113 		s = "NULL";
   114 	char* d = out + outlen;
   115 	while(*s)
   116 		*d++ = *s++;
   117 	return d - out;
   118 	}
   119 
   120 int AppendNumBase10U(char* out, unsigned int val, int width, int fill)
   121 	{
   122 	int len = 10;
   123 	if (val < 10)
   124 		len = 1;
   125 	else if (val < 100)
   126 		len = 2;
   127 	else if (val < 1000)
   128 		len = 3;
   129 	else if (val < 10000)
   130 		len = 4;
   131 	else if (val < 100000)
   132 		len = 5;
   133 	else if (val < 1000000)
   134 		len = 6;
   135 	else if (val < 10000000)
   136 		len = 7;
   137 	else if (val < 100000000)
   138 		len = 8;
   139 	else if (val < 1000000000)
   140 		len = 9;
   141 	int w = (len < width) ? width : len;
   142 	char* d = out + w;
   143 	do	{
   144 		*--d = (char)(48 + val%10);
   145 		val /= 10;
   146 		} while(val);
   147 	for (; d > out; *--d = (char)fill ) {}
   148 	return w;
   149 	}
   150 
   151 int AppendNumBase10S(char* out, int sval, int width, int fill)
   152 	{
   153 	int sign = (sval<0) ? 1 : 0;
   154 	unsigned val = sign ? unsigned(-sval) : unsigned(sval);
   155 	int len = 10;
   156 	if (val < 10)
   157 		len = 1;
   158 	else if (val < 100)
   159 		len = 2;
   160 	else if (val < 1000)
   161 		len = 3;
   162 	else if (val < 10000)
   163 		len = 4;
   164 	else if (val < 100000)
   165 		len = 5;
   166 	else if (val < 1000000)
   167 		len = 6;
   168 	else if (val < 10000000)
   169 		len = 7;
   170 	else if (val < 100000000)
   171 		len = 8;
   172 	else if (val < 1000000000)
   173 		len = 9;
   174 	if (sign) ++len;
   175 	int w = (len < width) ? width : len;
   176 	char* d = out + w;
   177 	do	{
   178 		*--d = (char)(48 + val%10);
   179 		val /= 10;
   180 		} while(val);
   181 	if (sign) *--d = '-';
   182 	for (; d > out; *--d = (char)fill ) {}
   183 	return w;
   184 	}
   185 
   186 int AppendNumBase16(char* out, unsigned int val, int width, int fill)
   187 	{
   188 	int len = 8;
   189 	if (val < 0x10)
   190 		len = 1;
   191 	else if (val < 0x100)
   192 		len = 2;
   193 	else if (val < 0x1000)
   194 		len = 3;
   195 	else if (val < 0x10000)
   196 		len = 4;
   197 	else if (val < 0x100000)
   198 		len = 5;
   199 	else if (val < 0x1000000)
   200 		len = 6;
   201 	else if (val < 0x10000000)
   202 		len = 7;
   203 	int w = (len < width) ? width : len;
   204 	char* d = out + w;
   205 	do	{
   206 		char c = (char)(48 + (val&15));
   207 		if (c>'9') c+=0x07;
   208 		*--d = c;
   209 		val >>= 4;
   210 		} while(val);
   211 	for (; d > out; *--d = (char)fill ) {}
   212 	return w;
   213 	}
   214 
   215 int AppendNumBase16L(char* out, Uint64 val, int width, int fill)
   216 	{
   217 	TUint vl = (TUint)val;
   218 	TUint vh = (TUint)(val>>32);
   219 	TInt l = 0;
   220 	if (vh)
   221 		{
   222 		l = AppendNumBase16(out, vh, width-8, fill);
   223 		l += AppendNumBase16(out+l, vl, 8, fill);
   224 		}
   225 	else
   226 		l = AppendNumBase16(out, vl, width, fill);
   227 	return l;
   228 	}
   229 
   230 
   231 
   232 /**
   233 Formats and appends text to the specified narrow descriptor without making any
   234 executive calls.
   235 
   236 The function takes a format string and a variable number of arguments. The
   237 format specifiers in the format string are used to interpret and the arguments.
   238 
   239 Format directives have the following syntax:
   240 @code
   241 <format-directive> ::= 
   242 	"%" [<padding-character>] [<field-width>] [<long-flag>] <conversion-specifier>
   243 @endcode
   244 
   245 If a field width is specified and the width of the formatted field is less
   246 than this width, then the field is padded with the padding character.
   247 The only supported padding characters are ' ' (default) and '0'.
   248 
   249 The long flag specifier ('l') modifies the semantic of the conversion
   250 specifier as explained below.
   251 
   252 The possible values for the conversion specifiers, the long flag and the way in
   253 which arguments are interpreted, are as follows:
   254 @code
   255 d	Interpret the argument as a TInt decimal representation
   256 ld	NOT SUPPORTED - use lx instead
   257 u	Interpret the argument as a TUint decimal representation
   258 lu	NOT SUPPORTED - use lx instead
   259 x	Interpret the argument as a TUint hexadecimal representation
   260 X	As above
   261 lx	Interpret the argument as a Uint64 hexadecimal representation
   262 lX	As above
   263 c	Interpret the argument as a character
   264 s	Interpret the argument as a pointer to narrow C string
   265 ls	Interpret the argument as a pointer to narrow C string
   266 S 	Interpret the argument as a pointer to narrow descriptor or NULL
   267 lS	NOT SUPPORTED - use S instead
   268 O	Interpret the argument as a pointer to DObject or NULL 
   269 	Generates the object full name or 'NULL'
   270 o	Interpret the argument as a pointer to DObject or NULL
   271 	Generates the object name or 'NULL'
   272 M	Interpret the argument as a pointer to a fast mutex or NULL
   273 	Generates the name, if this is a well-known fast mutex, address otherwise
   274 m	Interpret the argument as a pointer to a fast semaphore or NULL
   275 	Generates the owning thread name, if this is a well-known fast semaphore, address otherwise
   276 T	Interpret the argument as a pointer to a nanothread or NULL 
   277 	Generates the full name, if this is a Symbian OS thread, address otherwise
   278 C	Interpret the argument as a pointer to a DCodeSeg or NULL
   279 	Generates the filename and module version number
   280 @endcode
   281 
   282 The function can be called from the interrupt context, but extreme caution is advised as it
   283 may require a lot of stack space and interrupt stacks are very small.
   284 
   285 @param aDes 	Narrow descriptor that must be big-enough to hold result
   286 @param aFmt 	The format string
   287 @param aList 	A variable number of arguments to be converted to text as dictated by the format string
   288 
   289 @pre Calling thread can be either in a critical section or not.
   290 @pre Interrupts must be enabled.
   291 @pre Kernel must be unlocked
   292 @pre No fast mutex can be held.
   293 @pre Call in any context.
   294 @pre Suitable for use in a device driver
   295 
   296 @panic The set of panics that can be raised when appending data to descriptors.
   297 
   298 @see   TDes8
   299 */
   300 EXPORT_C TInt AppendFormat(char* aOut, const char* aFmt, VA_LIST aList)
   301 	{
   302 #define NEXT_FMT(c,p) if (((c)=*(p)++)==0) return outLen;
   303 
   304 	TInt outLen = 0;
   305 	FOREVER
   306 		{
   307 		char c;
   308 		NEXT_FMT(c,aFmt);
   309 		if (c=='%')
   310 			{
   311 			char fill=' ';
   312 			TInt width=0;
   313 			TBool long_arg=EFalse;
   314 			TBool ok=ETrue;
   315 			NEXT_FMT(c,aFmt);
   316 			if (c=='0')
   317 				{
   318 				fill='0';
   319 				NEXT_FMT(c,aFmt);
   320 				}
   321 			while(c>='0' && c<='9')
   322 				{
   323 				width=width*10+c-'0';
   324 				NEXT_FMT(c,aFmt);
   325 				}
   326 			if (c=='l')
   327 				{
   328 				long_arg=ETrue;
   329 				NEXT_FMT(c,aFmt);
   330 				}
   331 			switch(c)
   332 				{
   333 				case 'd':
   334 					{
   335 					if (long_arg)
   336 						ok=EFalse;
   337 					else
   338 						{
   339 						TInt val=VA_ARG(aList,TInt);
   340 						char* d = aOut + outLen;
   341 						outLen += AppendNumBase10S(d, val, width, fill);
   342 						}
   343 					break;
   344 					}
   345 				case 'u':
   346 					{
   347 					if (long_arg)
   348 						ok=EFalse;
   349 					else
   350 						{
   351 						TUint val=VA_ARG(aList,TUint);
   352 						char* d = aOut + outLen;
   353 						outLen += AppendNumBase10U(d, val, width, fill);
   354 						}
   355 					break;
   356 					}
   357 				case 'x':
   358 				case 'X':
   359 					{
   360 					if (long_arg)
   361 						{
   362 						Uint64 val=VA_ARG(aList,Uint64);
   363 						char* d = aOut + outLen;
   364 						outLen += AppendNumBase16L(d, val, width, fill);
   365 						}
   366 					else
   367 						{
   368 						TUint val=VA_ARG(aList,TUint);
   369 						char* d = aOut + outLen;
   370 						outLen += AppendNumBase16(d, val, width, fill);
   371 						}
   372 					break;
   373 					}
   374 				case 's':
   375 					{
   376 					const char* s = VA_ARG(aList,const char*);
   377 					outLen = appendstr(aOut, outLen, s);
   378 					break;
   379 					}
   380 				case 'M':		// fast mutex
   381 					{
   382 					NFastMutex* pM=VA_ARG(aList,NFastMutex*);
   383 					outLen = appendstr(aOut, outLen, "M");
   384 					if (!pM)
   385 						outLen = appendstr(aOut, outLen, 0);
   386 					else if (pM==&TheScheduler.iLock)
   387 						outLen = appendstr(aOut, outLen, "SYSLOCK");
   388 					else
   389 						outLen += AppendNumBase16(aOut+outLen, (TUint)pM, 8, '0');
   390 					break;
   391 					}
   392 				case 'm':		// fast semaphore
   393 					{
   394 					NFastSemaphore* pS=VA_ARG(aList,NFastSemaphore*);
   395 					outLen = appendstr(aOut, outLen, "S");
   396 					if (!pS)
   397 						outLen = appendstr(aOut, outLen, 0);
   398 					else
   399 						outLen += AppendNumBase16(aOut+outLen, (TUint)pS, 8, '0');
   400 					break;
   401 					}
   402 				case 'T':		// NKERN thread
   403 					{
   404 					NThread* pN=VA_ARG(aList,NThread*);
   405 #ifdef __SMP__
   406 					if (pN && pN->iNThreadBaseSpare8)
   407 						outLen = appendstr(aOut, outLen, (const char*)pN->iNThreadBaseSpare8);
   408 #else
   409 					if (pN && pN->iSpare8)
   410 						outLen = appendstr(aOut, outLen, (const char*)pN->iSpare8);
   411 #endif
   412 					else
   413 						{
   414 						outLen = appendstr(aOut, outLen, "T");
   415 						if (!pN)
   416 							outLen = appendstr(aOut, outLen, 0);
   417 						else
   418 							outLen += AppendNumBase16(aOut+outLen, (TUint)pN, 8, '0');
   419 						}
   420 					break;
   421 					}
   422 #ifdef __SMP__
   423 				case 'G':		// NKERN thread group
   424 					{
   425 					NThreadGroup* pG=VA_ARG(aList,NThreadGroup*);
   426 //					if (pG && pG->iNThreadBaseSpare8)
   427 //						outLen = appendstr(aOut, outLen, (const char*)pG->iNThreadBaseSpare8);
   428 //					else
   429 						{
   430 						outLen = appendstr(aOut, outLen, "G");
   431 						if (!pG)
   432 							outLen = appendstr(aOut, outLen, 0);
   433 						else
   434 							outLen += AppendNumBase16(aOut+outLen, (TUint)pG, 8, '0');
   435 						}
   436 					break;
   437 					}
   438 #endif
   439 				case 'c':
   440 					c=(char)VA_ARG(aList,TUint);
   441 					// fall through
   442 				default:
   443 					ok=EFalse;
   444 					break;
   445 				}
   446 				if (ok)
   447 					continue;
   448 			}
   449 		aOut[outLen++]=c;
   450 		}
   451 	return outLen;
   452 	}
   453 
   454 
   455 /**
   456 Prints a formatted string on the debug port.
   457 
   458 The function uses Kern::AppendFormat() to do the formatting.
   459 
   460 Although it is safe to call this function from an ISR, it polls the output
   461 serial port and may take a long time to complete, invalidating any
   462 real-time guarantee.
   463 
   464 If called from an ISR, it is possible for output text to be intermingled
   465 with other output text if one set of output interrupts or preempts another.
   466 
   467 Some of the formatting options may not work inside an ISR.
   468 
   469 Be careful not to use a string that is too long to fit onto the stack.
   470 
   471 @param aFmt The format string. This must not be longer than 256 characters.
   472 @param ...	A variable number of arguments to be converted to text as dictated
   473             by the format string.
   474 
   475 @pre Calling thread can either be in a critical section or not.
   476 @pre Interrupts must be enabled.
   477 @pre Kernel must be unlocked
   478 @pre No fast mutex can be held.
   479 @pre Call in any context.
   480 @pre Suitable for use in a device driver
   481 
   482 @see Kern::AppendFormat()
   483 */
   484 extern "C" void puts(const char* s);
   485 extern "C" void prthex8(TUint);
   486 EXPORT_C void KPrintf(const char* aFmt, ...)
   487 	{
   488 	extern TUint32 __tr();
   489 
   490 	char printBuf[256];
   491 	VA_LIST list;
   492 	VA_START(list,aFmt);
   493 	int c = AppendFormat(printBuf+2,aFmt,list) + 2;
   494 	printBuf[c++] = 13;
   495 	printBuf[c++] = 10;
   496 	printBuf[0] = __trace_cpu_num()+48;
   497 	printBuf[1] = 58;
   498 
   499 	if (NKern::Crashed())
   500 		{
   501 		DebugPrint(printBuf,c);
   502 		return;
   503 		}
   504 
   505 	// Handle BTrace first...
   506 	TUint category = BTrace::EKernPrintf;
   507 	TInt result = BTraceContextBig(category,0,0,printBuf,c);
   508 
   509 	NThread* csThread = 0;
   510 	NThread* curr = NKern::CurrentThread();
   511 	if (curr && NKern::CurrentContext() == NKern::EThread && !NKern::KernelLocked())
   512 		{
   513 		csThread = curr;
   514 		NKern::_ThreadEnterCS();
   515 		}
   516 	if (!result)
   517 		{
   518 		DebugPrint(printBuf,c);
   519 		}
   520 	if (csThread)
   521 		{
   522 		NKern::_ThreadLeaveCS();
   523 		}
   524 	}
   525 
   526 
   527 
   528 /******************************************************************************
   529  * BTRACE SUPPORT
   530  ******************************************************************************/
   531 
   532 #define BTRACE_INCLUDE_TIMESTAMPS
   533 
   534 TAny* BTraceBufferBase[KMaxCpus];
   535 TAny* BTraceBufferEnd[KMaxCpus];
   536 TAny* BTraceBufferPtr[KMaxCpus];	// next free position
   537 TBool BTraceBufferWrap[KMaxCpus];
   538 TBool BTraceActive;
   539 
   540 //const TUint KBTraceBufferSize = 16 * 1024 * 1024;
   541 const TUint KBTraceBufferSize = 1 * 1024 * 1024;
   542 const TUint KBTraceSlotSize = 128;
   543 
   544 __ASSERT_COMPILE(KBTraceSlotSize >= (TUint)KMaxBTraceRecordSize);
   545 
   546 TBool HandleBTrace(TUint32 aHeader,TUint32 aHeader2,const TUint32 aContext,const TUint32 a1,const TUint32 a2,const TUint32 a3,const TUint32 aExtra,const TUint32 aPc)
   547 	{
   548 #ifdef __SMP__
   549 	// Header 2 always present and contains CPU number
   550 	// If Header2 not originally there, add 4 to size
   551 	TInt cpu = NKern::CurrentCpu();
   552 	if (!(aHeader&(BTrace::EHeader2Present<<BTrace::EFlagsIndex*8)))
   553 		aHeader += (4<<BTrace::ESizeIndex*8) + (BTrace::EHeader2Present<<BTrace::EFlagsIndex*8), aHeader2=0;
   554 	aHeader2 = (aHeader2 &~ BTrace::ECpuIdMask) | (cpu<<20);
   555 #else
   556 	TInt cpu = 0;
   557 #endif
   558 #ifdef BTRACE_INCLUDE_TIMESTAMPS
   559 	// Add timestamp to trace...
   560 #if defined(__EPOC32__) && defined(__CPU_X86)
   561 	aHeader += 8<<BTrace::ESizeIndex*8;
   562 	aHeader |= BTrace::ETimestampPresent<<BTrace::EFlagsIndex*8 | BTrace::ETimestamp2Present<<BTrace::EFlagsIndex*8;
   563 	TUint64 timeStamp = fast_counter();
   564 #else
   565 	aHeader += 4<<BTrace::ESizeIndex*8;
   566 	aHeader |= BTrace::ETimestampPresent<<BTrace::EFlagsIndex*8;
   567 	TUint32 timeStamp = NKern::FastCounter();
   568 #endif
   569 #endif
   570 	TUint size = (aHeader+3)&0xfc;
   571 
   572 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   573 	TInt irq = NKern::DisableAllInterrupts();
   574 #endif
   575 
   576 	TUint32* src;
   577 	TUint32* dst = (TUint32*)BTraceBufferPtr[cpu];
   578 
   579 	if (!BTraceActive)
   580 		goto trace_off;
   581 
   582 	BTraceBufferPtr[cpu] = ((TUint8*)BTraceBufferPtr[cpu]) + KBTraceSlotSize;
   583 	if (BTraceBufferPtr[cpu] >= BTraceBufferEnd[cpu])
   584 		{
   585 		BTraceBufferPtr[cpu] = BTraceBufferBase[cpu];
   586 		BTraceBufferWrap[cpu] = TRUE;
   587 		}
   588 
   589 	size >>= 2; // we are now counting words, not bytes
   590 
   591 	if (dst+size > (TUint32*)BTraceBufferEnd[cpu])
   592 		goto trace_dropped;
   593 
   594 	{
   595 	// store first word of trace...
   596 	TUint w = aHeader;
   597 	--size;
   598 	*dst++ = w;
   599 
   600 #ifndef __SMP__
   601 	if (aHeader&(BTrace::EHeader2Present<<(BTrace::EFlagsIndex*8)))
   602 #endif
   603 		{
   604 		w = aHeader2;
   605 		--size;
   606 		*dst++ = w;
   607 		}
   608 
   609 #ifdef BTRACE_INCLUDE_TIMESTAMPS
   610 	// store timestamp...
   611 #if defined(__EPOC32__) && defined(__CPU_X86)
   612 	--size;
   613 	*dst++ = TUint32(timeStamp);
   614 	--size;
   615 	*dst++ = TUint32(timeStamp>>32);
   616 #else
   617 	--size;
   618 	*dst++ = timeStamp;
   619 #endif
   620 #endif
   621 
   622 	if(aHeader&(BTrace::EContextIdPresent<<(BTrace::EFlagsIndex*8)))
   623 		{
   624 		w = aContext;
   625 		--size;
   626 		*dst++ = w;
   627 		}
   628 
   629 	if(aHeader&(BTrace::EPcPresent<<(BTrace::EFlagsIndex*8)))
   630 		{
   631 		w = aPc;
   632 		--size;
   633 		*dst++ = w;
   634 		}
   635 
   636 	if(aHeader&(BTrace::EExtraPresent<<(BTrace::EFlagsIndex*8)))
   637 		{
   638 		w = aExtra;
   639 		--size;
   640 		*dst++ = w;
   641 		}
   642 
   643 	// store remaining words of trace...
   644 	if(size)
   645 		{
   646 		w = a1;
   647 		--size;
   648 		*dst++ = w;
   649 		if(size)
   650 			{
   651 			w = a2;
   652 			--size;
   653 			*dst++ = w;
   654 			if(size)
   655 				{
   656 				if(size==1)
   657 					{
   658 					w = a3;
   659 					*dst++ = w;
   660 					}
   661 				else
   662 					{
   663 					src = (TUint32*)a3;
   664 					do
   665 						{
   666 						w = *src++;
   667 						--size;
   668 						*dst++ = w;
   669 						}
   670 					while(size);
   671 					}
   672 				}
   673 			}
   674 		}
   675 	}
   676 
   677 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   678 	NKern::RestoreInterrupts(irq);
   679 #endif
   680 	return ETrue;
   681 
   682 
   683 trace_dropped:
   684 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   685 	NKern::RestoreInterrupts(irq);
   686 #endif
   687 	return ETrue;
   688 
   689 trace_off:
   690 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
   691 	NKern::RestoreInterrupts(irq);
   692 #endif
   693 	return ETrue;
   694 //	return EFalse;
   695 	}
   696 
   697 
   698 TBool SBTraceData::CheckFilter2(TUint32)
   699 	{
   700 	return TRUE;
   701 	}
   702 
   703 void InitBTraceHandler()
   704 	{
   705 	TInt cpu;
   706 #ifdef __SMP__
   707 	TInt ncpus = NKern::NumberOfCpus();
   708 #else
   709 	TInt ncpus = 1;
   710 #endif
   711 	for (cpu=0; cpu<ncpus; ++cpu)
   712 		{
   713 		BTraceBufferBase[cpu] = malloc(KBTraceBufferSize);
   714 		TEST_OOM(BTraceBufferBase[cpu]);
   715 		BTraceBufferEnd[cpu] = ((TUint8*)BTraceBufferBase[cpu]) + KBTraceBufferSize;
   716 
   717 		TUint8* p = (TUint8*)BTraceBufferBase[cpu];
   718 
   719 		BTraceBufferPtr[cpu] = p;
   720 		BTraceBufferWrap[cpu] = FALSE;
   721 
   722 		TEST_PRINT2("BTraceBufferBase[%d] = %08x", cpu, BTraceBufferBase[cpu]);
   723 		TEST_PRINT2("BTraceBufferEnd[%d]  = %08x", cpu, BTraceBufferEnd[cpu]);
   724 		TEST_PRINT2("BTraceBufferPtr[%d]  = %08x", cpu, BTraceBufferPtr[cpu]);
   725 		}
   726 
   727 	SBTraceData& traceData = BTraceData;
   728 	traceData.iHandler = &HandleBTrace;
   729 //	traceData.iFilter[BTrace::EKernPrintf] = 1;
   730 	traceData.iFilter[BTrace::EThreadIdentification] = 1;
   731 	traceData.iFilter[BTrace::ECpuUsage] = 1;
   732 	traceData.iFilter[0xdd] = 1;
   733 //	memset(traceData.iFilter, 1, sizeof(traceData.iFilter));
   734 	}
   735 
   736 void DumpBTraceBuffer()
   737 	{
   738 	BTraceActive = FALSE;
   739 
   740 	TInt cpu;
   741 #ifdef __SMP__
   742 	TInt ncpus = NKern::NumberOfCpus();
   743 #else
   744 	TInt ncpus = 1;
   745 #endif
   746 	char x[64];
   747 	for (cpu=0; cpu<=ncpus; ++cpu)
   748 		{
   749 		memset(x, cpu+0xc0, sizeof(x));
   750 		DebugPrint(x, sizeof(x));
   751 		if (cpu == ncpus)
   752 			break;
   753 		const char* b = (const char*)BTraceBufferBase[cpu];
   754 		const char* e = (const char*)BTraceBufferEnd[cpu];
   755 		const char* f = (const char*)BTraceBufferPtr[cpu];
   756 		const char* p = BTraceBufferWrap[cpu] ? f : b;
   757 		if (!p || (!BTraceBufferWrap[cpu] && p==f))
   758 			continue;
   759 		do	{
   760 			TInt size = *(const TUint8*)p;
   761 			size = (size + 3) &~ 3;
   762 			DebugPrint(p, size);
   763 			p+=KBTraceSlotSize;
   764 			if (p==e)
   765 				p = b;
   766 			} while (p!=f);
   767 		}
   768 
   769 	SBTraceData& traceData = BTraceData;
   770 	memset(traceData.iFilter, 0, sizeof(traceData.iFilter));
   771 	traceData.iHandler = 0;
   772 	TEST_PRINT("\r\n\nBTrace Dump Complete");
   773 	}
   774 
   775 void StartBTrace()
   776 	{
   777 	BTraceActive = TRUE;
   778 	}
   779 
   780 void StopBTrace()
   781 	{
   782 	BTraceActive = FALSE;
   783 	}
   784 
   785 TInt KCrazySchedulerEnabled()
   786 	{
   787 	return 0;
   788 	}