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 + }