tracebuf.cpp revision 5c47137ffdbcb823e83b3cfc93bf8ccd3318bec3
/*******************************************************************************
* Header Files *
*******************************************************************************/
#ifndef IN_RC
#endif
#else
# include <iprt/asm-amd64-x86.h>
#endif
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** Alignment used to place the trace buffer members, this should be a multiple
* of the cache line size if possible. (We should dynamically determine it.) */
#define RTTRACEBUF_ALIGNMENT 64
/** The maximum number of entries. */
#define RTTRACEBUF_MAX_ENTRIES _64K
/** The minimum number of entries. */
#define RTTRACEBUF_MIN_ENTRIES 4
/** The default number of entries. */
#define RTTRACEBUF_DEF_ENTRIES 256
/** The maximum entry size. */
#define RTTRACEBUF_MAX_ENTRY_SIZE _1M
/** The minimum entry size. */
/** The default entry size. */
#define RTTRACEBUF_DEF_ENTRY_SIZE 256
/**
* The volatile trace buffer members.
*/
typedef struct RTTRACEBUFVOLATILE
{
/** Reference counter. */
/** The next entry to make use of. */
/** Pointer to the volatile parts of a trace buffer. */
typedef RTTRACEBUFVOLATILE *PRTTRACEBUFVOLATILE;
/**
* Trace buffer entry.
*/
typedef struct RTTRACEBUFENTRY
{
/** The nano second entry time stamp. */
/** The ID of the CPU the event was recorded. */
/** The message. */
/** Pointer to a trace buffer entry. */
typedef RTTRACEBUFENTRY *PRTTRACEBUFENTRY;
/**
* Trace buffer structure.
*
* @remarks This structure must be context agnostic, i.e. no pointers or
*/
typedef struct RTTRACEBUFINT
{
/** Magic value (RTTRACEBUF_MAGIC). */
/** The entry size. */
/** The number of entries. */
/** Flags (always zero for now). */
/** The offset to the volatile members (RTTRACEBUFVOLATILE) (relative to
* the start of this structure). */
/** The offset to the entries (relative to the start of this structure). */
/** Reserved entries. */
/** Pointer to a const trace buffer. */
typedef RTTRACEBUFINT const *PCRTTRACEBUFINT;
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/**
* Get the current CPU Id.
*/
# define RTTRACEBUF_CUR_CPU() RTMpCpuId()
#else
# define RTTRACEBUF_CUR_CPU() ASMGetApicId()
#endif
/** Calculates the address of the volatile trace buffer members. */
#define RTTRACEBUF_TO_VOLATILE(a_pThis) ((PRTTRACEBUFVOLATILE)((uint8_t *)(a_pThis) + (a_pThis)->offVolatile))
/** Calculates the address of a trace buffer entry. */
((PRTTRACEBUFENTRY)( (uint8_t *)(a_pThis) + (a_pThis)->offEntries + (a_iEntry) * (a_pThis)->cbEntry ))
/** Validates a trace buffer handle and returns rc if not valid. */
do { \
} while (0)
/**
* Resolves and validates a trace buffer handle and returns rc if not valid.
*
* @param a_hTraceBuf The trace buffer handle passed by the user.
* @param a_pThis Where to store the trace buffer pointer.
*/
do { \
if ((a_hTraceBuf) == RTTRACEBUF_DEFAULT) \
{ \
(a_pThis) = RTTraceGetDefaultBuf(); \
if (!RT_VALID_PTR(a_pThis)) \
return VERR_NOT_FOUND; \
} \
else \
{ \
(a_pThis) = (a_hTraceBuf); \
} \
\
{ \
} \
} while (0)
/**
* Drops a trace buffer reference.
*
* @param a_pThis Pointer to the trace buffer.
*/
#define RTTRACEBUF_DROP_REFERENCE(a_pThis) \
do { \
if (!cRefs) \
} while (0)
/**
* The prologue code for a RTTraceAddSomething function.
*
* Resolves a trace buffer handle, grabs a reference to it and allocates the
* next entry. Return with an appropriate error status on failure.
*
* @param a_hTraceBuf The trace buffer handle passed by the user.
*
* @remarks This is kind of ugly, sorry.
*/
#define RTTRACEBUF_ADD_PROLOGUE(a_hTraceBuf) \
int rc; \
char *pszBuf; \
\
/* Resolve and validate the handle. */ \
if ((a_hTraceBuf) == RTTRACEBUF_DEFAULT) \
{ \
pThis = RTTraceGetDefaultBuf(); \
if (!RT_VALID_PTR(pThis)) \
return VERR_NOT_FOUND; \
} \
else if ((a_hTraceBuf) != NIL_RTTRACEBUF) \
{ \
pThis = (a_hTraceBuf); \
} \
else \
return VERR_INVALID_HANDLE; \
\
return VINF_SUCCESS; \
\
/* Grab a reference. */ \
{ \
} \
\
/* Grab the next entry and set the time stamp. */ \
*pszBuf = '\0'; \
/**
* Used by a RTTraceAddPosSomething to store the source position in the entry
* prior to adding the actual trace message text.
*
* Both pszBuf and cchBuf will be adjusted such that pszBuf points and the zero
* terminator after the source position part.
*/
#define RTTRACEBUF_ADD_STORE_SRC_POS() \
do { \
/* file(line): - no path */ \
} while (0)
/**
* The epilogue code for a RTTraceAddSomething function.
*
* This will release the trace buffer reference.
*/
#define RTTRACEBUF_ADD_EPILOGUE() \
if (!cRefs) \
return rc
#ifndef IN_RC /* Drop this in RC context (too lazy to split the file). */
RTDECL(int) RTTraceBufCreate(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags)
{
AssertReturn(!(fFlags & ~(RTTRACEBUF_FLAGS_MASK & ~ RTTRACEBUF_FLAGS_FREE_ME)), VERR_INVALID_PARAMETER);
/*
* Apply default and alignment adjustments.
*/
if (!cbEntry)
else
if (!cEntries)
else if (cEntries < RTTRACEBUF_MIN_ENTRIES)
/*
* Calculate the required buffer size, allocte it and hand it on to the
* carver API.
*/
{
}
int rc;
if (pvBlock)
{
if (RT_FAILURE(rc))
}
else
rc = VERR_NO_MEMORY;
return rc;
}
RTDECL(int) RTTraceBufCarve(PRTTRACEBUF phTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags,
{
/*
* Apply defaults, align sizes and check against available buffer space.
* This code can be made a bit more clever, if someone feels like it.
*/
if (cbEntry)
else
{
if (!cbEntryBuf)
{
}
else if (cEntries)
{
if (cbEntryZ > RTTRACEBUF_MAX_ENTRIES)
}
else
cbEntry = sizeof(RTTRACEBUFENTRY);
}
if (!cEntries)
{
if (cEntriesZ > RTTRACEBUF_MAX_ENTRIES)
}
if (cEntries < RTTRACEBUF_MIN_ENTRIES)
if (offVolatile < sizeof(RTTRACEBUFINT))
if (*pcbBlock < cbReqBlock)
{
*pcbBlock = cbReqBlock;
return VERR_BUFFER_OVERFLOW;
}
/*
* Do the carving.
*/
*phTraceBuf = pThis;
return VINF_SUCCESS;
}
#endif /* !IN_RC */
/**
* Destructor.
*
* @param pThis The trace buffer to destroy.
*/
{
{
#ifdef IN_RC
#else
#endif
}
}
{
}
{
if (hTraceBuf == NIL_RTTRACEBUF)
return 0;
if (!cRefs)
return cRefs;
}
{
}
{
}
{
int rc;
return rc;
}
{
}
{
}
{
}
RTDECL(int) RTTraceBufAddPosMsgEx(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg, size_t cbMaxMsg)
{
}
{
int rc;
return rc;
}
RTDECL(int) RTTraceBufAddPosMsgV(RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, va_list va)
{
}
RTDECL(int) RTTraceBufEnumEntries(RTTRACEBUF hTraceBuf, PFNRTTRACEBUFCALLBACK pfnCallback, void *pvUser)
{
int rc = VINF_SUCCESS;
while (cLeft--)
{
{
if (rc != VINF_SUCCESS)
break;
}
/* next */
iBase += 1;
}
return rc;
}
{
}
{
}
{
RTTRACEBUF_VALID_RETURN_RC(pThis, false);
}
{
RTTRACEBUF_VALID_RETURN_RC(pThis, false);
}
/*
*
* Move the following to a separate file, consider using the enumerator.
*
*/
{
while (cLeft--)
{
/* next */
iBase += 1;
}
return VINF_SUCCESS;
}
{
while (cLeft--)
{
/* next */
iBase += 1;
}
return VINF_SUCCESS;
}