VirtualBox

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

Last change on this file since 39627 was 39327, checked in by vboxsync, 13 years ago

scm whitespace cleanups.

  • 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 NOREF(pszFunction); \
259 } while (0)
260
261
262/**
263 * The epilogue code for a RTTraceAddSomething function.
264 *
265 * This will release the trace buffer reference.
266 */
267#define RTTRACEBUF_ADD_EPILOGUE() \
268 cRefs = ASMAtomicDecU32(&pVolatile->cRefs); \
269 if (!cRefs) \
270 rtTraceBufDestroy((RTTRACEBUFINT *)pThis); \
271 return rc
272
273
274#ifndef IN_RC /* Drop this in RC context (too lazy to split the file). */
275
276RTDECL(int) RTTraceBufCreate(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags)
277{
278 AssertPtrReturn(phTraceBuf, VERR_INVALID_POINTER);
279 AssertReturn(!(fFlags & ~(RTTRACEBUF_FLAGS_MASK & ~ RTTRACEBUF_FLAGS_FREE_ME)), VERR_INVALID_PARAMETER);
280 AssertMsgReturn(cbEntry <= RTTRACEBUF_MAX_ENTRIES, ("%#x\n", cbEntry), VERR_OUT_OF_RANGE);
281 AssertMsgReturn(cEntries <= RTTRACEBUF_MAX_ENTRY_SIZE, ("%#x\n", cEntries), VERR_OUT_OF_RANGE);
282
283 /*
284 * Apply default and alignment adjustments.
285 */
286 if (!cbEntry)
287 cbEntry = RTTRACEBUF_DEF_ENTRY_SIZE;
288 else
289 cbEntry = RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT);
290
291 if (!cEntries)
292 cEntries = RTTRACEBUF_DEF_ENTRIES;
293 else if (cEntries < RTTRACEBUF_MIN_ENTRIES)
294 cEntries = RTTRACEBUF_MIN_ENTRIES;
295
296 /*
297 * Calculate the required buffer size, allocte it and hand it on to the
298 * carver API.
299 */
300 size_t cbBlock = cbEntry * cEntries
301 + RT_ALIGN_Z(sizeof(RTTRACEBUFINT), RTTRACEBUF_ALIGNMENT)
302 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
303 void *pvBlock = RTMemAlloc(cbBlock);
304 if (!((uintptr_t)pvBlock & (RTTRACEBUF_ALIGNMENT - 1)))
305 {
306 RTMemFree(pvBlock);
307 cbBlock += RTTRACEBUF_ALIGNMENT - 1;
308 pvBlock = RTMemAlloc(cbBlock);
309 }
310 int rc;
311 if (pvBlock)
312 {
313 rc = RTTraceBufCarve(phTraceBuf, cEntries, cbEntry, fFlags, pvBlock, &cbBlock);
314 if (RT_FAILURE(rc))
315 RTMemFree(pvBlock);
316 }
317 else
318 rc = VERR_NO_MEMORY;
319 return rc;
320}
321
322
323RTDECL(int) RTTraceBufCarve(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags,
324 void *pvBlock, size_t *pcbBlock)
325{
326 AssertPtrReturn(phTraceBuf, VERR_INVALID_POINTER);
327 AssertReturn(!(fFlags & ~RTTRACEBUF_FLAGS_MASK), VERR_INVALID_PARAMETER);
328 AssertMsgReturn(cbEntry <= RTTRACEBUF_MAX_ENTRIES, ("%#x\n", cbEntry), VERR_OUT_OF_RANGE);
329 AssertMsgReturn(cEntries <= RTTRACEBUF_MAX_ENTRY_SIZE, ("%#x\n", cEntries), VERR_OUT_OF_RANGE);
330 AssertPtrReturn(pcbBlock, VERR_INVALID_POINTER);
331 size_t const cbBlock = *pcbBlock;
332 AssertReturn(RT_VALID_PTR(pvBlock) || !cbBlock, VERR_INVALID_POINTER);
333
334 /*
335 * Apply defaults, align sizes and check against available buffer space.
336 * This code can be made a bit more clever, if someone feels like it.
337 */
338 size_t const cbHdr = RT_ALIGN_Z(sizeof(RTTRACEBUFINT), RTTRACEBUF_ALIGNMENT)
339 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
340 size_t const cbEntryBuf = cbBlock > cbHdr ? cbBlock - cbHdr : 0;
341 if (cbEntry)
342 cbEntry = RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT);
343 else
344 {
345 if (!cbEntryBuf)
346 {
347 cbEntry = RTTRACEBUF_DEF_ENTRY_SIZE;
348 cEntries = RTTRACEBUF_DEF_ENTRIES;
349 }
350 else if (cEntries)
351 {
352 size_t cbEntryZ = cbBlock / cEntries;
353 cbEntryZ &= ~(RTTRACEBUF_ALIGNMENT - 1);
354 if (cbEntryZ > RTTRACEBUF_MAX_ENTRIES)
355 cbEntryZ = RTTRACEBUF_MAX_ENTRIES;
356 cbEntry = (uint32_t)cbEntryZ;
357 }
358 else if (cbBlock >= RT_ALIGN_32(512, RTTRACEBUF_ALIGNMENT) * 256)
359 cbEntry = RT_ALIGN_32(512, RTTRACEBUF_ALIGNMENT);
360 else if (cbBlock >= RT_ALIGN_32(256, RTTRACEBUF_ALIGNMENT) * 64)
361 cbEntry = RT_ALIGN_32(256, RTTRACEBUF_ALIGNMENT);
362 else if (cbBlock >= RT_ALIGN_32(128, RTTRACEBUF_ALIGNMENT) * 32)
363 cbEntry = RT_ALIGN_32(128, RTTRACEBUF_ALIGNMENT);
364 else
365 cbEntry = sizeof(RTTRACEBUFENTRY);
366 }
367 Assert(RT_ALIGN_32(cbEntry, RTTRACEBUF_ALIGNMENT) == cbEntry);
368
369 if (!cEntries)
370 {
371 size_t cEntriesZ = cbEntryBuf / cbEntry;
372 if (cEntriesZ > RTTRACEBUF_MAX_ENTRIES)
373 cEntriesZ = RTTRACEBUF_MAX_ENTRIES;
374 cEntries = (uint32_t)cEntriesZ;
375 }
376 if (cEntries < RTTRACEBUF_MIN_ENTRIES)
377 cEntries = RTTRACEBUF_MIN_ENTRIES;
378
379 uint32_t offVolatile = RTTRACEBUF_ALIGNMENT - ((uintptr_t)pvBlock & (RTTRACEBUF_ALIGNMENT - 1));
380 if (offVolatile < sizeof(RTTRACEBUFINT))
381 offVolatile += RTTRACEBUF_ALIGNMENT;
382 size_t cbReqBlock = offVolatile
383 + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT)
384 + cbEntry * cEntries;
385 if (*pcbBlock < cbReqBlock)
386 {
387 *pcbBlock = cbReqBlock;
388 return VERR_BUFFER_OVERFLOW;
389 }
390
391 /*
392 * Do the carving.
393 */
394 memset(pvBlock, 0, cbBlock);
395
396 RTTRACEBUFINT *pThis = (RTTRACEBUFINT *)pvBlock;
397 pThis->u32Magic = RTTRACEBUF_MAGIC;
398 pThis->cbEntry = cbEntry;
399 pThis->cEntries = cEntries;
400 pThis->fFlags = fFlags;
401 pThis->offVolatile = offVolatile;
402 pThis->offEntries = offVolatile + RT_ALIGN_Z(sizeof(RTTRACEBUFVOLATILE), RTTRACEBUF_ALIGNMENT);
403
404 PRTTRACEBUFVOLATILE pVolatile = (PRTTRACEBUFVOLATILE)((uint8_t *)pThis + offVolatile);
405 pVolatile->cRefs = 1;
406 pVolatile->iEntry = 0;
407
408 *pcbBlock = cbBlock - cbReqBlock;
409 *phTraceBuf = pThis;
410 return VINF_SUCCESS;
411}
412
413#endif /* !IN_RC */
414
415
416/**
417 * Destructor.
418 *
419 * @param pThis The trace buffer to destroy.
420 */
421static void rtTraceBufDestroy(RTTRACEBUFINT *pThis)
422{
423 AssertReturnVoid(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTTRACEBUF_MAGIC_DEAD, RTTRACEBUF_MAGIC));
424 if (pThis->fFlags & RTTRACEBUF_FLAGS_FREE_ME)
425 {
426#ifdef IN_RC
427 AssertReleaseFailed();
428#else
429 RTMemFree(pThis);
430#endif
431 }
432}
433
434
435RTDECL(uint32_t)RTTraceBufRetain(RTTRACEBUF hTraceBuf)
436{
437 PCRTTRACEBUFINT pThis = hTraceBuf;
438 RTTRACEBUF_VALID_RETURN_RC(pThis, UINT32_MAX);
439 return ASMAtomicIncU32(&RTTRACEBUF_TO_VOLATILE(pThis)->cRefs);
440}
441
442
443RTDECL(uint32_t) RTTraceBufRelease(RTTRACEBUF hTraceBuf)
444{
445 if (hTraceBuf == NIL_RTTRACEBUF)
446 return 0;
447
448 PCRTTRACEBUFINT pThis = hTraceBuf;
449 RTTRACEBUF_VALID_RETURN_RC(pThis, UINT32_MAX);
450
451 uint32_t cRefs = ASMAtomicDecU32(&RTTRACEBUF_TO_VOLATILE(pThis)->cRefs);
452 if (!cRefs)
453 rtTraceBufDestroy((RTTRACEBUFINT *)pThis);
454 return cRefs;
455}
456
457
458RTDECL(int) RTTraceBufAddMsg(RTTRACEBUF hTraceBuf, const char *pszMsg)
459{
460 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
461 RTStrCopy(pszBuf, cchBuf, pszMsg);
462 RTTRACEBUF_ADD_EPILOGUE();
463}
464
465
466RTDECL(int) RTTraceBufAddMsgEx( RTTRACEBUF hTraceBuf, const char *pszMsg, size_t cbMaxMsg)
467{
468 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
469 RTStrCopyEx(pszBuf, cchBuf, pszMsg, cbMaxMsg);
470 RTTRACEBUF_ADD_EPILOGUE();
471}
472
473
474RTDECL(int) RTTraceBufAddMsgF(RTTRACEBUF hTraceBuf, const char *pszMsgFmt, ...)
475{
476 int rc;
477 va_list va;
478 va_start(va, pszMsgFmt);
479 rc = RTTraceBufAddMsgV(hTraceBuf, pszMsgFmt, va);
480 va_end(va);
481 return rc;
482}
483
484
485RTDECL(int) RTTraceBufAddMsgV(RTTRACEBUF hTraceBuf, const char *pszMsgFmt, va_list va)
486{
487 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
488 RTStrPrintfV(pszBuf, cchBuf, pszMsgFmt, va);
489 RTTRACEBUF_ADD_EPILOGUE();
490}
491
492
493RTDECL(int) RTTraceBufAddPos(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL)
494{
495 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
496 RTTRACEBUF_ADD_STORE_SRC_POS();
497 RTTRACEBUF_ADD_EPILOGUE();
498}
499
500
501RTDECL(int) RTTraceBufAddPosMsg(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg)
502{
503 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
504 RTTRACEBUF_ADD_STORE_SRC_POS();
505 RTStrCopy(pszBuf, cchBuf, pszMsg);
506 RTTRACEBUF_ADD_EPILOGUE();
507}
508
509
510RTDECL(int) RTTraceBufAddPosMsgEx(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg, size_t cbMaxMsg)
511{
512 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
513 RTTRACEBUF_ADD_STORE_SRC_POS();
514 RTStrCopyEx(pszBuf, cchBuf, pszMsg, cbMaxMsg);
515 RTTRACEBUF_ADD_EPILOGUE();
516}
517
518
519RTDECL(int) RTTraceBufAddPosMsgF(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, ...)
520{
521 int rc;
522 va_list va;
523 va_start(va, pszMsgFmt);
524 rc = RTTraceBufAddPosMsgV(hTraceBuf, RT_SRC_POS_ARGS, pszMsgFmt, va);
525 va_end(va);
526 return rc;
527}
528
529
530RTDECL(int) RTTraceBufAddPosMsgV(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, va_list va)
531{
532 RTTRACEBUF_ADD_PROLOGUE(hTraceBuf);
533 RTTRACEBUF_ADD_STORE_SRC_POS();
534 RTStrPrintfV(pszBuf, cchBuf, pszMsgFmt, va);
535 RTTRACEBUF_ADD_EPILOGUE();
536}
537
538
539RTDECL(int) RTTraceBufEnumEntries(RTTRACEBUF hTraceBuf, PFNRTTRACEBUFCALLBACK pfnCallback, void *pvUser)
540{
541 int rc = VINF_SUCCESS;
542 uint32_t iBase;
543 uint32_t cLeft;
544 PCRTTRACEBUFINT pThis;
545 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
546
547 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
548 cLeft = pThis->cEntries;
549 while (cLeft--)
550 {
551 PRTTRACEBUFENTRY pEntry;
552
553 iBase %= pThis->cEntries;
554 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
555 if (pEntry->NanoTS)
556 {
557 rc = pfnCallback((RTTRACEBUF)pThis, cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg, pvUser);
558 if (rc != VINF_SUCCESS)
559 break;
560 }
561
562 /* next */
563 iBase += 1;
564 }
565
566 RTTRACEBUF_DROP_REFERENCE(pThis);
567 return rc;
568}
569
570
571RTDECL(uint32_t) RTTraceBufGetEntrySize(RTTRACEBUF hTraceBuf)
572{
573 PCRTTRACEBUFINT pThis = hTraceBuf;
574 RTTRACEBUF_VALID_RETURN_RC(pThis, 0);
575 return pThis->cbEntry;
576}
577
578
579RTDECL(uint32_t) RTTraceBufGetEntryCount(RTTRACEBUF hTraceBuf)
580{
581 PCRTTRACEBUFINT pThis = hTraceBuf;
582 RTTRACEBUF_VALID_RETURN_RC(pThis, 0);
583 return pThis->cEntries;
584}
585
586
587RTDECL(bool) RTTraceBufDisable(RTTRACEBUF hTraceBuf)
588{
589 PCRTTRACEBUFINT pThis = hTraceBuf;
590 RTTRACEBUF_VALID_RETURN_RC(pThis, false);
591 return !ASMAtomicBitTestAndSet((void volatile *)&pThis->fFlags, RTTRACEBUF_FLAGS_DISABLED_BIT);
592}
593
594
595RTDECL(bool) RTTraceBufEnable(RTTRACEBUF hTraceBuf)
596{
597 PCRTTRACEBUFINT pThis = hTraceBuf;
598 RTTRACEBUF_VALID_RETURN_RC(pThis, false);
599 return !ASMAtomicBitTestAndClear((void volatile *)&pThis->fFlags, RTTRACEBUF_FLAGS_DISABLED_BIT);
600}
601
602
603/*
604 *
605 * Move the following to a separate file, consider using the enumerator.
606 *
607 */
608
609RTDECL(int) RTTraceBufDumpToLog(RTTRACEBUF hTraceBuf)
610{
611 uint32_t iBase;
612 uint32_t cLeft;
613 PCRTTRACEBUFINT pThis;
614 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
615
616 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
617 cLeft = pThis->cEntries;
618 while (cLeft--)
619 {
620 PRTTRACEBUFENTRY pEntry;
621
622 iBase %= pThis->cEntries;
623 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
624 if (pEntry->NanoTS)
625 RTLogPrintf("%04u/%'llu/%02x: %s\n", cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg);
626
627 /* next */
628 iBase += 1;
629 }
630
631 RTTRACEBUF_DROP_REFERENCE(pThis);
632 return VINF_SUCCESS;
633}
634
635
636RTDECL(int) RTTraceBufDumpToAssert(RTTRACEBUF hTraceBuf)
637{
638 uint32_t iBase;
639 uint32_t cLeft;
640 PCRTTRACEBUFINT pThis;
641 RTTRACEBUF_RESOLVE_VALIDATE_RETAIN_RETURN(hTraceBuf, pThis);
642
643 iBase = ASMAtomicReadU32(&RTTRACEBUF_TO_VOLATILE(pThis)->iEntry);
644 cLeft = pThis->cEntries;
645 while (cLeft--)
646 {
647 PRTTRACEBUFENTRY pEntry;
648
649 iBase %= pThis->cEntries;
650 pEntry = RTTRACEBUF_TO_ENTRY(pThis, iBase);
651 if (pEntry->NanoTS)
652 RTAssertMsg2AddWeak("%u/%'llu/%02x: %s\n", cLeft, pEntry->NanoTS, pEntry->idCpu, pEntry->szMsg);
653
654 /* next */
655 iBase += 1;
656 }
657
658 RTTRACEBUF_DROP_REFERENCE(pThis);
659 return VINF_SUCCESS;
660}
661
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