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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\nkernsa\kprintf.cpp
19 #include <nktest/utils.h>
23 #define EXPORT_C /* */
37 extern void DebugPrint(const char*, int);
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.
43 If the current thread is not a symbian OS thread the global debug mask is used.
45 Only supports the first 32 global debug trace bits.
47 @return The debug mask.
50 extern TLinAddr RomHeaderAddress;
52 EXPORT_C TInt KDebugMask()
54 const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
55 return rh.iTraceMask[0];
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.
65 If the current thread is not a symbian OS thread the global debug mask is used.
67 @return The state of the debug mask bit number.
70 EXPORT_C TBool KDebugNum(TInt aBitNum)
73 const TRomHeader& rh = *(const TRomHeader*)RomHeaderAddress;
76 // special case for KALWAYS
77 if (aBitNum == KALWAYS)
79 m = rh.iTraceMask[0] ||
88 else if ( (aBitNum > KMAXTRACE) || (aBitNum < 0) )
92 TInt index = aBitNum >> 5;
93 m = rh.iTraceMask[index];
94 m &= 1 << (aBitNum & 31);
103 extern "C" unsigned int strlen(const char* s)
110 int appendstr(char* out, int outlen, const char* s)
114 char* d = out + outlen;
120 int AppendNumBase10U(char* out, unsigned int val, int width, int fill)
129 else if (val < 10000)
131 else if (val < 100000)
133 else if (val < 1000000)
135 else if (val < 10000000)
137 else if (val < 100000000)
139 else if (val < 1000000000)
141 int w = (len < width) ? width : len;
144 *--d = (char)(48 + val%10);
147 for (; d > out; *--d = (char)fill ) {}
151 int AppendNumBase10S(char* out, int sval, int width, int fill)
153 int sign = (sval<0) ? 1 : 0;
154 unsigned val = sign ? unsigned(-sval) : unsigned(sval);
162 else if (val < 10000)
164 else if (val < 100000)
166 else if (val < 1000000)
168 else if (val < 10000000)
170 else if (val < 100000000)
172 else if (val < 1000000000)
175 int w = (len < width) ? width : len;
178 *--d = (char)(48 + val%10);
181 if (sign) *--d = '-';
182 for (; d > out; *--d = (char)fill ) {}
186 int AppendNumBase16(char* out, unsigned int val, int width, int fill)
191 else if (val < 0x100)
193 else if (val < 0x1000)
195 else if (val < 0x10000)
197 else if (val < 0x100000)
199 else if (val < 0x1000000)
201 else if (val < 0x10000000)
203 int w = (len < width) ? width : len;
206 char c = (char)(48 + (val&15));
211 for (; d > out; *--d = (char)fill ) {}
215 int AppendNumBase16L(char* out, Uint64 val, int width, int fill)
217 TUint vl = (TUint)val;
218 TUint vh = (TUint)(val>>32);
222 l = AppendNumBase16(out, vh, width-8, fill);
223 l += AppendNumBase16(out+l, vl, 8, fill);
226 l = AppendNumBase16(out, vl, width, fill);
233 Formats and appends text to the specified narrow descriptor without making any
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.
239 Format directives have the following syntax:
241 <format-directive> ::=
242 "%" [<padding-character>] [<field-width>] [<long-flag>] <conversion-specifier>
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'.
249 The long flag specifier ('l') modifies the semantic of the conversion
250 specifier as explained below.
252 The possible values for the conversion specifiers, the long flag and the way in
253 which arguments are interpreted, are as follows:
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
261 lx Interpret the argument as a Uint64 hexadecimal representation
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
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.
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
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
296 @panic The set of panics that can be raised when appending data to descriptors.
300 EXPORT_C TInt AppendFormat(char* aOut, const char* aFmt, VA_LIST aList)
302 #define NEXT_FMT(c,p) if (((c)=*(p)++)==0) return outLen;
313 TBool long_arg=EFalse;
321 while(c>='0' && c<='9')
323 width=width*10+c-'0';
339 TInt val=VA_ARG(aList,TInt);
340 char* d = aOut + outLen;
341 outLen += AppendNumBase10S(d, val, width, fill);
351 TUint val=VA_ARG(aList,TUint);
352 char* d = aOut + outLen;
353 outLen += AppendNumBase10U(d, val, width, fill);
362 Uint64 val=VA_ARG(aList,Uint64);
363 char* d = aOut + outLen;
364 outLen += AppendNumBase16L(d, val, width, fill);
368 TUint val=VA_ARG(aList,TUint);
369 char* d = aOut + outLen;
370 outLen += AppendNumBase16(d, val, width, fill);
376 const char* s = VA_ARG(aList,const char*);
377 outLen = appendstr(aOut, outLen, s);
380 case 'M': // fast mutex
382 NFastMutex* pM=VA_ARG(aList,NFastMutex*);
383 outLen = appendstr(aOut, outLen, "M");
385 outLen = appendstr(aOut, outLen, 0);
386 else if (pM==&TheScheduler.iLock)
387 outLen = appendstr(aOut, outLen, "SYSLOCK");
389 outLen += AppendNumBase16(aOut+outLen, (TUint)pM, 8, '0');
392 case 'm': // fast semaphore
394 NFastSemaphore* pS=VA_ARG(aList,NFastSemaphore*);
395 outLen = appendstr(aOut, outLen, "S");
397 outLen = appendstr(aOut, outLen, 0);
399 outLen += AppendNumBase16(aOut+outLen, (TUint)pS, 8, '0');
402 case 'T': // NKERN thread
404 NThread* pN=VA_ARG(aList,NThread*);
406 if (pN && pN->iNThreadBaseSpare8)
407 outLen = appendstr(aOut, outLen, (const char*)pN->iNThreadBaseSpare8);
409 if (pN && pN->iSpare8)
410 outLen = appendstr(aOut, outLen, (const char*)pN->iSpare8);
414 outLen = appendstr(aOut, outLen, "T");
416 outLen = appendstr(aOut, outLen, 0);
418 outLen += AppendNumBase16(aOut+outLen, (TUint)pN, 8, '0');
423 case 'G': // NKERN thread group
425 NThreadGroup* pG=VA_ARG(aList,NThreadGroup*);
426 // if (pG && pG->iNThreadBaseSpare8)
427 // outLen = appendstr(aOut, outLen, (const char*)pG->iNThreadBaseSpare8);
430 outLen = appendstr(aOut, outLen, "G");
432 outLen = appendstr(aOut, outLen, 0);
434 outLen += AppendNumBase16(aOut+outLen, (TUint)pG, 8, '0');
440 c=(char)VA_ARG(aList,TUint);
456 Prints a formatted string on the debug port.
458 The function uses Kern::AppendFormat() to do the formatting.
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
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.
467 Some of the formatting options may not work inside an ISR.
469 Be careful not to use a string that is too long to fit onto the stack.
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.
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
482 @see Kern::AppendFormat()
484 extern "C" void puts(const char* s);
485 extern "C" void prthex8(TUint);
486 EXPORT_C void KPrintf(const char* aFmt, ...)
488 extern TUint32 __tr();
493 int c = AppendFormat(printBuf+2,aFmt,list) + 2;
496 printBuf[0] = __trace_cpu_num()+48;
499 if (NKern::Crashed())
501 DebugPrint(printBuf,c);
505 // Handle BTrace first...
506 TUint category = BTrace::EKernPrintf;
507 TInt result = BTraceContextBig(category,0,0,printBuf,c);
509 NThread* csThread = 0;
510 NThread* curr = NKern::CurrentThread();
511 if (curr && NKern::CurrentContext() == NKern::EThread && !NKern::KernelLocked())
514 NKern::_ThreadEnterCS();
518 DebugPrint(printBuf,c);
522 NKern::_ThreadLeaveCS();
528 /******************************************************************************
530 ******************************************************************************/
532 #define BTRACE_INCLUDE_TIMESTAMPS
534 TAny* BTraceBufferBase[KMaxCpus];
535 TAny* BTraceBufferEnd[KMaxCpus];
536 TAny* BTraceBufferPtr[KMaxCpus]; // next free position
537 TBool BTraceBufferWrap[KMaxCpus];
540 //const TUint KBTraceBufferSize = 16 * 1024 * 1024;
541 const TUint KBTraceBufferSize = 1 * 1024 * 1024;
542 const TUint KBTraceSlotSize = 128;
544 __ASSERT_COMPILE(KBTraceSlotSize >= (TUint)KMaxBTraceRecordSize);
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)
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);
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();
565 aHeader += 4<<BTrace::ESizeIndex*8;
566 aHeader |= BTrace::ETimestampPresent<<BTrace::EFlagsIndex*8;
567 TUint32 timeStamp = NKern::FastCounter();
570 TUint size = (aHeader+3)&0xfc;
572 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
573 TInt irq = NKern::DisableAllInterrupts();
577 TUint32* dst = (TUint32*)BTraceBufferPtr[cpu];
582 BTraceBufferPtr[cpu] = ((TUint8*)BTraceBufferPtr[cpu]) + KBTraceSlotSize;
583 if (BTraceBufferPtr[cpu] >= BTraceBufferEnd[cpu])
585 BTraceBufferPtr[cpu] = BTraceBufferBase[cpu];
586 BTraceBufferWrap[cpu] = TRUE;
589 size >>= 2; // we are now counting words, not bytes
591 if (dst+size > (TUint32*)BTraceBufferEnd[cpu])
595 // store first word of trace...
601 if (aHeader&(BTrace::EHeader2Present<<(BTrace::EFlagsIndex*8)))
609 #ifdef BTRACE_INCLUDE_TIMESTAMPS
610 // store timestamp...
611 #if defined(__EPOC32__) && defined(__CPU_X86)
613 *dst++ = TUint32(timeStamp);
615 *dst++ = TUint32(timeStamp>>32);
622 if(aHeader&(BTrace::EContextIdPresent<<(BTrace::EFlagsIndex*8)))
629 if(aHeader&(BTrace::EPcPresent<<(BTrace::EFlagsIndex*8)))
636 if(aHeader&(BTrace::EExtraPresent<<(BTrace::EFlagsIndex*8)))
643 // store remaining words of trace...
677 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
678 NKern::RestoreInterrupts(irq);
684 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
685 NKern::RestoreInterrupts(irq);
690 #if !defined(__SMP__) || !defined(__USE_BTRACE_LOCK__)
691 NKern::RestoreInterrupts(irq);
698 TBool SBTraceData::CheckFilter2(TUint32)
703 void InitBTraceHandler()
707 TInt ncpus = NKern::NumberOfCpus();
711 for (cpu=0; cpu<ncpus; ++cpu)
713 BTraceBufferBase[cpu] = malloc(KBTraceBufferSize);
714 TEST_OOM(BTraceBufferBase[cpu]);
715 BTraceBufferEnd[cpu] = ((TUint8*)BTraceBufferBase[cpu]) + KBTraceBufferSize;
717 TUint8* p = (TUint8*)BTraceBufferBase[cpu];
719 BTraceBufferPtr[cpu] = p;
720 BTraceBufferWrap[cpu] = FALSE;
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]);
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));
736 void DumpBTraceBuffer()
738 BTraceActive = FALSE;
742 TInt ncpus = NKern::NumberOfCpus();
747 for (cpu=0; cpu<=ncpus; ++cpu)
749 memset(x, cpu+0xc0, sizeof(x));
750 DebugPrint(x, sizeof(x));
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))
760 TInt size = *(const TUint8*)p;
761 size = (size + 3) &~ 3;
769 SBTraceData& traceData = BTraceData;
770 memset(traceData.iFilter, 0, sizeof(traceData.iFilter));
771 traceData.iHandler = 0;
772 TEST_PRINT("\r\n\nBTrace Dump Complete");
782 BTraceActive = FALSE;
785 TInt KCrazySchedulerEnabled()