VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/log/tracebuf.cpp@ 38659

Last change on this file since 38659 was 37409, checked in by vboxsync, 14 years ago

iprt/trace: Added the CPU/APIC ID to the trace entires. Added some introspection APIs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1
2/*******************************************************************************
3* Header Files *
4*******************************************************************************/
5#include "internal/iprt.h"
6#include <iprt/trace.h>
7
8
9#include <iprt/assert.h>
10#include <iprt/asm.h>
11#include <iprt/err.h>
12#include <iprt/log.h>
13#ifndef IN_RC
14# include <iprt/mem.h>
15#endif
16#if defined(IN_RING0) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
17# include <iprt/mp.h>
18#else
19# include <iprt/asm-amd64-x86.h>
20#endif
21#include <iprt/path.h>
22#include <iprt/string.h>
23#include <iprt/time.h>
24
25#include "internal/magics.h"
26
27
28/*******************************************************************************
29* Structures and Typedefs *
30*******************************************************************************/
31/** Alignment used to place the trace buffer members, this should be a multiple
32 * of the cache line size if possible. (We should dynamically determine it.) */
33#define RTTRACEBUF_ALIGNMENT 64
34AssertCompile(RTTRACEBUF_ALIGNMENT >= sizeof(uint64_t) * 2);
35
36/** The maximum number of entries. */
37#define RTTRACEBUF_MAX_ENTRIES _64K
38/** The minimum number of entries. */
39#define RTTRACEBUF_MIN_ENTRIES 4
40/** The default number of entries. */
41#define RTTRACEBUF_DEF_ENTRIES 256
42
43/** The maximum entry size. */
44#define RTTRACEBUF_MAX_ENTRY_SIZE _1M
45/** The minimum entry size. */
46#define RTTRACEBUF_MIN_ENTRY_SIZE RTTRACEBUF_ALIGNMENT
47/** The default entry size. */
48#define RTTRACEBUF_DEF_ENTRY_SIZE 256
49AssertCompile(!(RTTRACEBUF_DEF_ENTRY_SIZE & (RTTRACEBUF_DEF_ENTRY_SIZE - 1)));
50
51/**
52 * The volatile trace buffer members.
53 */
54typedef struct RTTRACEBUFVOLATILE
55{
56 /** Reference counter. */
57 uint32_t volatile cRefs;
58 /** The next entry to make use of. */
59 uint32_t volatile iEntry;
60} RTTRACEBUFVOLATILE;
61/** Pointer to the volatile parts of a trace buffer. */
62typedef RTTRACEBUFVOLATILE *PRTTRACEBUFVOLATILE;
63
64
65/**
66 * Trace buffer entry.
67 */
68typedef struct RTTRACEBUFENTRY
69{
70 /** The nano second entry time stamp. */
71 uint64_t NanoTS;
72 /** The ID of the CPU the event was recorded. */
73 RTCPUID idCpu;
74 /** The message. */
75 char szMsg[RTTRACEBUF_ALIGNMENT - sizeof(uint64_t) - sizeof(RTCPUID)];
76} RTTRACEBUFENTRY;
77AssertCompile(sizeof(RTTRACEBUFENTRY) <= RTTRACEBUF_ALIGNMENT);
78/** Pointer to a trace buffer entry. */
79typedef RTTRACEBUFENTRY *PRTTRACEBUFENTRY;
80
81
82
83/**
84 * Trace buffer structure.
85 *
86 * @remarks This structure must be context agnostic, i.e. no pointers or
87 * other types that may differ between contexts (R3/R0/RC).
88 */
89typedef struct RTTRACEBUFINT
90{
91 /** Magic value (RTTRACEBUF_MAGIC). */
92 uint32_t u32Magic;
93 /** The entry size. */
94 uint32_t cbEntry;
95 /** The number of entries. */
96 uint32_t cEntries;
97 /** Flags (always zero for now). */
98 uint32_t fFlags;
99 /** The offset to the volatile members (RTTRACEBUFVOLATILE) (relative to
100 * the start of this structure). */
101 uint32_t offVolatile;
102 /** The offset to the entries (relative to the start of this structure). */
103 uint32_t offEntries;
104 /** Reserved entries. */
105 uint32_t au32Reserved[2];
106} RTTRACEBUFINT;
107/** Pointer to a const trace buffer. */
108typedef RTTRACEBUFINT const *PCRTTRACEBUFINT;
109
110
111/*******************************************************************************
112* Defined Constants And Macros *
113*******************************************************************************/
114/**
115 * Get the current CPU Id.
116 */
117#if defined(IN_RING0) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
118# define RTTRACEBUF_CUR_CPU() RTMpCpuId()
119#else
120# define RTTRACEBUF_CUR_CPU() ASMGetApicId()
121#endif
122
123/** Calculates the address of the volatile trace buffer members. */
124#define RTTRACEBUF_TO_VOLATILE(a_pThis) ((PRTTRACEBUFVOLATILE)((uint8_t *)(a_pThis) + (a_pThis)->offVolatile))
125
126/** Calculates the address of a trace buffer entry. */
127#define RTTRACEBUF_TO_ENTRY(a_pThis, a_iEntry) \
128 ((PRTTRACEBUFENTRY)( (uint8_t *)(a_pThis) + (a_pThis)->offEntries + (a_iEntry) * (a_pThis)->cbEntry ))
129
130/** Validates a trace buffer handle and returns rc if not valid. */
131#define RTTRACEBUF_VALID_RETURN_RC(a_pThis, a_rc) \
132 do { \
133 AssertPtrReturn((a_pThis), (a_rc)); \
134 AssertReturn((a_pThis)->u32Magic == RTTRACEBUF_MAGIC, (a_rc)); \
135 AssertReturn((a_pThis)->offVolatile < RTTRACEBUF_ALIGNMENT * 2, (a_rc)); \
136 AssertReturn(RTTRACEBUF_TO_VOLATILE(a_pThis)->cRefs > 0, (a_rc)); \
137 } while (0)
138
139/**
140 * Resolves and validates a trace buffer handle and returns rc if not valid.
141 *
142 * @param a_hTraceBuf The trace buffer handle passed by the user.
143 * @param a_pThis Where to store the trace buffer pointer.
144 */
145#define RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(a_hTraceBuf, a_pThis) \
146 do { \
147 uint32_t cRefs; \
148 if ((a_hTraceBuf) == RTTRACEBUF_DEFAULT) \
149 { \
150 (a_pThis) = RTTraceGetDefaultBuf(); \
151 if (!RT_VALID_PTR(a_pThis)) \
152 return VERR_NOT_FOUND; \
153 } \
154 else \
155 { \
156 (a_pThis) = (a_hTraceBuf); \
157 AssertPtrReturn((a_pThis), VERR_INVALID_HANDLE); \
158 } \
159 AssertReturn((a_pThis)->u32Magic == RTTRACEBUF_MAGIC, VERR_INVALID_HANDLE); \
160 AssertReturn((a_pThis)->offVolatile < RTTRACEBUF_ALIGNMENT * 2, VERR_INVALID_HANDLE); \
161 \
162 cRefs = ASMAtomicIncU32(&RTTRACEBUF_TO_VOLATILE(a_pThis)->cRefs); \
163 if (RT_UNLIKELY(cRefs < 1 || cRefs >= _1M)) \
164 { \
165 ASMAtomicDecU32(&RTTRACEBUF_TO_VOLATILE(a_pThis)->cRefs); \
166 AssertFailedReturn(VERR_INVALID_HANDLE); \
167 } \
168 } while (0)
169
170
171/**
172 * Drops a trace buffer reference.
173 *
174 * @param a_pThis Pointer to the trace buffer.
175 */
176#define RTTRACEBUF_DROP_REFERENCE(a_pThis) \
177 do { \
178 uint32_t cRefs = ASMAtomicDecU32(&RTTRACEBUF_TO_VOLATILE(a_pThis)->cRefs); \
179 if (!cRefs) \
180 rtTraceBufDestroy((RTTRACEBUFINT *)a_pThis); \
181 } while (0)
182
183
184/**
185 * The prologue code for a RTTraceAddSomething function.
186 *
187 * Resolves a trace buffer handle, grabs a reference to it and allocates the
188 * next entry. Return with an appropriate error status on failure.
189 *
190 * @param a_hTraceBuf The trace buffer handle passed by the user.
191 *
192 * @remarks This is kind of ugly, sorry.
193 */
194#define RTTRACEBUF_ADD_PROLOGUE(a_hTraceBuf) \
195 int rc; \
196 uint32_t cRefs; \
197 uint32_t iEntry; \
198 PCRTTRACEBUFINT pThis; \
199 PRTTRACEBUFVOLATILE pVolatile; \
200 PRTTRACEBUFENTRY pEntry; \
201 char *pszBuf; \
202 size_t cchBuf; \
203 \
204 /* Resolve and validate the handle. */ \
205 if ((a_hTraceBuf) == RTTRACEBUF_DEFAULT) \
206 { \
207 pThis = RTTraceGetDefaultBuf(); \
208 if (!RT_VALID_PTR(pThis)) \
209 return VERR_NOT_FOUND; \
210 } \
211 else if ((a_hTraceBuf) != NIL_RTTRACEBUF) \
212 { \
213 pThis = (a_hTraceBuf); \
214 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); \
215 } \
216 else \
217 return VERR_INVALID_HANDLE; \
218 \
219 AssertReturn(pThis->u32Magic == RTTRACEBUF_MAGIC, VERR_INVALID_HANDLE); \
220 if (pThis->fFlags & RTTRACEBUF_FLAGS_DISABLED) \
221 return VINF_SUCCESS; \
222 AssertReturn(pThis->offVolatile < RTTRACEBUF_ALIGNMENT * 2, VERR_INVALID_HANDLE); \
223 pVolatile = RTTRACEBUF_TO_VOLATILE(pThis); \
224 \
225 /* Grab a reference. */ \
226 cRefs = ASMAtomicIncU32(&pVolatile->cRefs); \
227 if (RT_UNLIKELY(cRefs < 1 || cRefs >= _1M)) \
228 { \
229 ASMAtomicDecU32(&pVolatile->cRefs); \
230 AssertFailedReturn(VERR_INVALID_HANDLE); \
231 } \
232 \
233 /* Grab the next entry and set the time stamp. */ \
234 iEntry = ASMAtomicIncU32(&pVolatile->iEntry) - 1; \
235 iEntry %= pThis->cEntries; \
236 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iEntry); \
237 pEntry->NanoTS = RTTimeNanoTS(); \
238 pEntry->idCpu = RTTRACEBUF_CUR_CPU(); \
239 pszBuf = &pEntry->szMsg[0]; \
240 *pszBuf = '\0'; \
241 cchBuf = pThis->cbEntry - RT_OFFSETOF(RTTRACEBUFENTRY, szMsg) - 1; \
242 rc = VINF_SUCCESS
243
244
245/**
246 * Used by a RTTraceAddPosSomething to store the source position in the entry
247 * prior to adding the actual trace message text.
248 *
249 * Both pszBuf and cchBuf will be adjusted such that pszBuf points and the zero
250 * terminator after the source position part.
251 */
252#define RTTRACEBUF_ADD_STORE_SRC_POS() \
253 do { \
254 /* file(line): - no path */ \
255 size_t cchPos = RTStrPrintf(pszBuf, cchBuf, "%s(%d): ", RTPathFilename(pszFile), iLine); \
256 pszBuf += cchPos; \
257 cchBuf -= cchPos; \
258 } while (0)
259
260
261/**
262 * The epilogue code for a RTTraceAddSomething function.
263 *
264 * This will release the trace buffer reference.
265 */
266#define RTTRACEBUF_ADD_EPILOGUE() \
267 cRefs = ASMAtomicDecU32(&pVolatile->cRefs); \
268 if (!cRefs) \
269 rtTraceBufDestroy((RTTRACEBUFINT *)pThis); \
270 return rc
271
272
273#ifndef IN_RC /* Drop this in RC context (too lazy to split the file). */
274
275RTDECL(int) RTTraceBufCreate(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags)
276{
277 AssertPtrReturn(phTraceBuf, VERR_INVALID_POINTER);
278 AssertReturn(!(fFlags & ~(RTTRACEBUF_FLAGS_MASK & ~ RTTRACEBUF_FLAGS_FREE_ME)), VERR_INVALID_PARAMETER);
279 AssertMsgReturn(cbEntry <= RTTRACEBUF_MAX_ENTRIES, ("%#x\n", cbEntry), VERR_OUT_OF_RANGE);
280 AssertMsgReturn(cEntries <= RTTRACEBUF_MAX_ENTRY_SIZE, ("%#x\n", cEntries), VERR_OUT_OF_RANGE);
281
282 /*
283 * Apply default and alignment adjustments.
284 */
285 if (!cbEntry)
286 cbEntry = RTTRACEBUF_DEF_ENTRY_SIZE;
287 else
288 cbEntry = RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT);
289
290 if (!cEntries)
291 cEntries = RTTRACEBUF_DEF_ENTRIES;
292 else if (cEntries < RTTRACEBUF_MIN_ENTRIES)
293 cEntries = RTTRACEBUF_MIN_ENTRIES;
294
295 /*
296 * Calculate the required buffer size, allocte it and hand it on to the
297 * carver API.
298 */
299 size_t cbBlock = cbEntry * cEntries
300 + RT_ALIGN_Z(sizeof(RTTRACEBUFINT), RTTRACEBUF_ALIGNMENT)
301 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
302 void *pvBlock = RTMemAlloc(cbBlock);
303 if (!((uintptr_t)pvBlock & (RTTRACEBUF_ALIGNMENT - 1)))
304 {
305 RTMemFree(pvBlock);
306 cbBlock += RTTRACEBUF_ALIGNMENT - 1;
307 pvBlock = RTMemAlloc(cbBlock);
308 }
309 int rc;
310 if (pvBlock)
311 {
312 rc = RTTraceBufCarve(phTraceBuf, cEntries, cbEntry, fFlags, pvBlock, &cbBlock);
313 if (RT_FAILURE(rc))
314 RTMemFree(pvBlock);
315 }
316 else
317 rc = VERR_NO_MEMORY;
318 return rc;
319}
320
321
322RTDECL(int) RTTraceBufCarve(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags,
323 void *pvBlock, size_t *pcbBlock)
324{
325 AssertPtrReturn(phTraceBuf, VERR_INVALID_POINTER);
326 AssertReturn(!(fFlags & ~RTTRACEBUF_FLAGS_MASK), VERR_INVALID_PARAMETER);
327 AssertMsgReturn(cbEntry <= RTTRACEBUF_MAX_ENTRIES, ("%#x\n", cbEntry), VERR_OUT_OF_RANGE);
328 AssertMsgReturn(cEntries <= RTTRACEBUF_MAX_ENTRY_SIZE, ("%#x\n", cEntries), VERR_OUT_OF_RANGE);
329 AssertPtrReturn(pcbBlock, VERR_INVALID_POINTER);
330 size_t const cbBlock = *pcbBlock;
331 AssertReturn(RT_VALID_PTR(pvBlock) || !cbBlock, VERR_INVALID_POINTER);
332
333 /*
334 * Apply defaults, align sizes and check against available buffer space.
335 * This code can be made a bit more clever, if someone feels like it.
336 */
337 size_t const cbHdr = RT_ALIGN_Z(sizeof(RTTRACEBUFINT), RTTRACEBUF_ALIGNMENT)
338 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
339 size_t const cbEntryBuf = cbBlock > cbHdr ? cbBlock - cbHdr : 0;
340 if (cbEntry)
341 cbEntry = RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT);
342 else
343 {
344 if (!cbEntryBuf)
345 {
346 cbEntry = RTTRACEBUF_DEF_ENTRY_SIZE;
347 cEntries = RTTRACEBUF_DEF_ENTRIES;
348 }
349 else if (cEntries)
350 {
351 size_t cbEntryZ = cbBlock / cEntries;
352 cbEntryZ &= ~(RTTRACEBUF_ALIGNMENT - 1);
353 if (cbEntryZ > RTTRACEBUF_MAX_ENTRIES)
354 cbEntryZ = RTTRACEBUF_MAX_ENTRIES;
355 cbEntry = (uint32_t)cbEntryZ;
356 }
357 else if (cbBlock >= RT_ALIGN_32(512, RTTRACEBUF_ALIGNMENT) * 256)
358 cbEntry = RT_ALIGN_32(512, RTTRACEBUF_ALIGNMENT);
359 else if (cbBlock >= RT_ALIGN_32(256, RTTRACEBUF_ALIGNMENT) * 64)
360 cbEntry = RT_ALIGN_32(256, RTTRACEBUF_ALIGNMENT);
361 else if (cbBlock >= RT_ALIGN_32(128, RTTRACEBUF_ALIGNMENT) * 32)
362 cbEntry = RT_ALIGN_32(128, RTTRACEBUF_ALIGNMENT);
363 else
364 cbEntry = sizeof(RTTRACEBUFENTRY);
365 }
366 Assert(RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT) == cbEntry);
367
368 if (!cEntries)
369 {
370 size_t cEntriesZ = cbEntryBuf / cbEntry;
371 if (cEntriesZ > RTTRACEBUF_MAX_ENTRIES)
372 cEntriesZ = RTTRACEBUF_MAX_ENTRIES;
373 cEntries = (uint32_t)cEntriesZ;
374 }
375 if (cEntries < RTTRACEBUF_MIN_ENTRIES)
376 cEntries = RTTRACEBUF_MIN_ENTRIES;
377
378 uint32_t offVolatile = RTTRACEBUF_ALIGNMENT - ((uintptr_t)pvBlock & (RTTRACEBUF_ALIGNMENT - 1));
379 if (offVolatile < sizeof(RTTRACEBUFINT))
380 offVolatile += RTTRACEBUF_ALIGNMENT;
381 size_t cbReqBlock = offVolatile
382 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT)
383 + cbEntry * cEntries;
384 if (*pcbBlock < cbReqBlock)
385 {
386 *pcbBlock = cbReqBlock;
387 return VERR_BUFFER_OVERFLOW;
388 }
389
390 /*
391 * Do the carving.
392 */
393 memset(pvBlock, 0, cbBlock);
394
395 RTTRACEBUFINT *pThis = (RTTRACEBUFINT *)pvBlock;
396 pThis->u32Magic = RTTRACEBUF_MAGIC;
397 pThis->cbEntry = cbEntry;
398 pThis->cEntries = cEntries;
399 pThis->fFlags = fFlags;
400 pThis->offVolatile = offVolatile;
401 pThis->offEntries = offVolatile + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
402
403 PRTTRACEBUFVOLATILE pVolatile = (PRTTRACEBUFVOLATILE)((uint8_t *)pThis + offVolatile);
404 pVolatile->cRefs = 1;
405 pVolatile->iEntry = 0;
406
407 *pcbBlock = cbBlock - cbReqBlock;
408 *phTraceBuf = pThis;
409 return VINF_SUCCESS;
410}
411
412#endif /* !IN_RC */
413
414
415/**
416 * Destructor.
417 *
418 * @param pThis The trace buffer to destroy.
419 */
420static void rtTraceBufDestroy(RTTRACEBUFINT *pThis)
421{
422 AssertReturnVoid(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTTRACEBUF_MAGIC_DEAD, RTTRACEBUF_MAGIC));
423 if (pThis->fFlags & RTTRACEBUF_FLAGS_FREE_ME)
424 {
425#ifdef IN_RC
426 AssertReleaseFailed();
427#else
428 RTMemFree(pThis);
429#endif
430 }
431}
432
433
434RTDECL(uint32_t)RTTraceBufRetain(RTTRACEBUF hTraceBuf)
435{
436 PCRTTRACEBUFINT pThis = hTraceBuf;
437 RTTRACEBUF_VALID_RETURN_RC(pThis, UINT32_MAX);
438 return ASMAtomicIncU32(&RTTRACEBUF_TO_VOLATILE(pThis)->cRefs);
439}
440
441
442RTDECL(uint32_t) RTTraceBufRelease(RTTRACEBUF hTraceBuf)
443{
444 if (hTraceBuf == NIL_RTTRACEBUF)
445 return 0;
446
447 PCRTTRACEBUFINT pThis = hTraceBuf;
448 RTTRACEBUF_VALID_RETURN_RC(pThis, UINT32_MAX);
449
450 uint32_t cRefs = ASMAtomicDecU32(&RTTRACEBUF_TO_VOLATILE(pThis)->cRefs);
451 if (!cRefs)
452 rtTraceBufDestroy((RTTRACEBUFINT *)pThis);
453 return cRefs;
454}
455
456
457RTDECL(int) RTTraceBufAddMsg(RTTRACEBUF hTraceBuf, const char *pszMsg)
458{
459 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
460 RTStrCopy(pszBuf, cchBuf, pszMsg);
461 RTTRACEBUF_ADD_EPILOGUE();
462}
463
464
465RTDECL(int) RTTraceBufAddMsgEx( RTTRACEBUF hTraceBuf, const char *pszMsg, size_t cbMaxMsg)
466{
467 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
468 RTStrCopyEx(pszBuf, cchBuf, pszMsg, cbMaxMsg);
469 RTTRACEBUF_ADD_EPILOGUE();
470}
471
472
473RTDECL(int) RTTraceBufAddMsgF(RTTRACEBUF hTraceBuf, const char *pszMsgFmt, ...)
474{
475 int rc;
476 va_list va;
477 va_start(va, pszMsgFmt);
478 rc = RTTraceBufAddMsgV(hTraceBuf, pszMsgFmt, va);
479 va_end(va);
480 return rc;
481}
482
483
484RTDECL(int) RTTraceBufAddMsgV(RTTRACEBUF hTraceBuf, const char *pszMsgFmt, va_list va)
485{
486 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
487 RTStrPrintfV(pszBuf, cchBuf, pszMsgFmt, va);
488 RTTRACEBUF_ADD_EPILOGUE();
489}
490
491
492RTDECL(int) RTTraceBufAddPos(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL)
493{
494 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
495 RTTRACEBUF_ADD_STORE_SRC_POS();
496 RTTRACEBUF_ADD_EPILOGUE();
497}
498
499
500RTDECL(int) RTTraceBufAddPosMsg(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg)
501{
502 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
503 RTTRACEBUF_ADD_STORE_SRC_POS();
504 RTStrCopy(pszBuf, cchBuf, pszMsg);
505 RTTRACEBUF_ADD_EPILOGUE();
506}
507
508
509RTDECL(int) RTTraceBufAddPosMsgEx(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg, size_t cbMaxMsg)
510{
511 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
512 RTTRACEBUF_ADD_STORE_SRC_POS();
513 RTStrCopyEx(pszBuf, cchBuf, pszMsg, cbMaxMsg);
514 RTTRACEBUF_ADD_EPILOGUE();
515}
516
517
518RTDECL(int) RTTraceBufAddPosMsgF(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, ...)
519{
520 int rc;
521 va_list va;
522 va_start(va, pszMsgFmt);
523 rc = RTTraceBufAddPosMsgV(hTraceBuf, RT_SRC_POS_ARGS, pszMsgFmt, va);
524 va_end(va);
525 return rc;
526}
527
528
529RTDECL(int) RTTraceBufAddPosMsgV(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, va_list va)
530{
531 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
532 RTTRACEBUF_ADD_STORE_SRC_POS();
533 RTStrPrintfV(pszBuf, cchBuf, pszMsgFmt, va);
534 RTTRACEBUF_ADD_EPILOGUE();
535}
536
537
538RTDECL(int) RTTraceBufEnumEntries(RTTRACEBUF hTraceBuf, PFNRTTRACEBUFCALLBACK pfnCallback, void *pvUser)
539{
540 int rc = VINF_SUCCESS;
541 uint32_t iBase;
542 uint32_t cLeft;
543 PCRTTRACEBUFINT pThis;
544 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
545
546 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
547 cLeft = pThis->cEntries;
548 while (cLeft--)
549 {
550 PRTTRACEBUFENTRY pEntry;
551
552 iBase %= pThis->cEntries;
553 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
554 if (pEntry->NanoTS)
555 {
556 rc = pfnCallback((RTTRACEBUF)pThis, cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg, pvUser);
557 if (rc != VINF_SUCCESS)
558 break;
559 }
560
561 /* next */
562 iBase += 1;
563 }
564
565 RTTRACEBUF_DROP_REFERENCE(pThis);
566 return rc;
567}
568
569
570RTDECL(uint32_t) RTTraceBufGetEntrySize(RTTRACEBUF hTraceBuf)
571{
572 PCRTTRACEBUFINT pThis = hTraceBuf;
573 RTTRACEBUF_VALID_RETURN_RC(pThis, 0);
574 return pThis->cbEntry;
575}
576
577
578RTDECL(uint32_t) RTTraceBufGetEntryCount(RTTRACEBUF hTraceBuf)
579{
580 PCRTTRACEBUFINT pThis = hTraceBuf;
581 RTTRACEBUF_VALID_RETURN_RC(pThis, 0);
582 return pThis->cEntries;
583}
584
585
586RTDECL(bool) RTTraceBufDisable(RTTRACEBUF hTraceBuf)
587{
588 PCRTTRACEBUFINT pThis = hTraceBuf;
589 RTTRACEBUF_VALID_RETURN_RC(pThis, false);
590 return !ASMAtomicBitTestAndSet((void volatile *)&pThis->fFlags, RTTRACEBUF_FLAGS_DISABLED_BIT);
591}
592
593
594RTDECL(bool) RTTraceBufEnable(RTTRACEBUF hTraceBuf)
595{
596 PCRTTRACEBUFINT pThis = hTraceBuf;
597 RTTRACEBUF_VALID_RETURN_RC(pThis, false);
598 return !ASMAtomicBitTestAndClear((void volatile *)&pThis->fFlags, RTTRACEBUF_FLAGS_DISABLED_BIT);
599}
600
601
602/*
603 *
604 * Move the following to a separate file, consider using the enumerator.
605 *
606 */
607
608RTDECL(int) RTTraceBufDumpToLog(RTTRACEBUF hTraceBuf)
609{
610 uint32_t iBase;
611 uint32_t cLeft;
612 PCRTTRACEBUFINT pThis;
613 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
614
615 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
616 cLeft = pThis->cEntries;
617 while (cLeft--)
618 {
619 PRTTRACEBUFENTRY pEntry;
620
621 iBase %= pThis->cEntries;
622 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
623 if (pEntry->NanoTS)
624 RTLogPrintf("%04u/%'llu/%02x: %s\n", cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg);
625
626 /* next */
627 iBase += 1;
628 }
629
630 RTTRACEBUF_DROP_REFERENCE(pThis);
631 return VINF_SUCCESS;
632}
633
634
635RTDECL(int) RTTraceBufDumpToAssert(RTTRACEBUF hTraceBuf)
636{
637 uint32_t iBase;
638 uint32_t cLeft;
639 PCRTTRACEBUFINT pThis;
640 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
641
642 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
643 cLeft = pThis->cEntries;
644 while (cLeft--)
645 {
646 PRTTRACEBUFENTRY pEntry;
647
648 iBase %= pThis->cEntries;
649 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
650 if (pEntry->NanoTS)
651 RTAssertMsg2AddWeak("%u/%'llu/%02x: %s\n", cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg);
652
653 /* next */
654 iBase += 1;
655 }
656
657 RTTRACEBUF_DROP_REFERENCE(pThis);
658 return VINF_SUCCESS;
659}
660
661
662
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette