mirror of
https://git.rtems.org/rtems-tools/
synced 2025-06-10 16:12:09 +08:00
177 lines
5.3 KiB
INI
177 lines
5.3 KiB
INI
;
|
|
; RTEMS Trace Linker Trace Buffer
|
|
;
|
|
; Copyright 2015 Chris Johns <chrisj@rtems.org>
|
|
;
|
|
|
|
;
|
|
; A trace buffer generator buffers records to a buffer that can be extracted
|
|
; latter.
|
|
;
|
|
[trace-buffer-generator]
|
|
headers = trace-buffer-generator-headers
|
|
code-blocks = trace-buffer-tracers
|
|
lock-local = " rtems_interrupt_lock_context lcontext;"
|
|
lock-acquire = " rtems_interrupt_lock_acquire(&__rtld_tbg_lock, &lcontext);"
|
|
lock-release = " rtems_interrupt_lock_release(&__rtld_tbg_lock, &lcontext);"
|
|
entry-trace = "__rtld_tbg_buffer_entry(&in, @FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_ENTRY_SIZE@);"
|
|
entry-alloc = "in = __rtld_tbg_buffer_alloc(@FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_ENTRY_SIZE@);"
|
|
arg-trace = "__rtld_tbg_buffer_arg(&in, @ARG_SIZE@, (void*) &@ARG_LABEL@);"
|
|
exit-trace = "__rtld_tbg_buffer_exit(&in, @FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_RET_SIZE@);"
|
|
exit-alloc = "in = __rtld_tbg_buffer_alloc(@FUNC_INDEX@, RTLD_TBG_REC_OVERHEAD + @FUNC_DATA_RET_SIZE@);"
|
|
ret-trace = "__rtld_tbg_buffer_ret(in, @RET_SIZE@, (void*) &@RET_LABEL@);"
|
|
buffer-local = " uint8_t* in;"
|
|
|
|
[trace-buffer-generator-headers]
|
|
header = "#include <stdint.h>"
|
|
header = "#include <rtems.h>"
|
|
header = "#include <rtems/rtems/tasksimpl.h>"
|
|
|
|
[trace-buffer-tracers]
|
|
code = <<<CODE
|
|
/*
|
|
* Mode bits.
|
|
*/
|
|
#define RTLD_TRACE_BUFFER_VERSION 0 /* data format version, lower 8bits */
|
|
#if RTLD_TRACE_BUFFER_TIMESTAMP
|
|
#undef RTLD_TRACE_BUFFER_TIMESTAMP
|
|
#define RTLD_TRACE_BUFFER_TIMESTAMP (1 << 8)
|
|
#else
|
|
#define RTLD_TRACE_BUFFER_TIMESTAMP 0
|
|
#endif
|
|
#if defined(RTLD_TRACE_BUFFER_THREAD)
|
|
#undef RTLD_TRACE_BUFFER_THREAD
|
|
#define RTLD_TRACE_BUFFER_THREAD (1 << 9)
|
|
#else
|
|
#define RTLD_TRACE_BUFFER_THREAD 0
|
|
#endif
|
|
#define RTLD_TRACE_BUFFER_MODE RTLD_TRACE_BUFFER_VERSION | \
|
|
RTLD_TRACE_BUFFER_TIMESTAMP | \
|
|
RTLD_TRACE_BUFFER_THREAD
|
|
/*
|
|
* The number of word in the buffer.
|
|
*/
|
|
#define RTLD_TRACE_BUFFER_WORDS (RTLD_TRACE_BUFFER_SIZE / sizeof(uint32_t))
|
|
/*
|
|
* We log the header record and then a 64bit timestamp.
|
|
*/
|
|
#define RTLD_TBG_REC_OVERHEAD (6 * sizeof(uint32_t))
|
|
/*
|
|
* Symbols are public to allow external access to the buffers.
|
|
*/
|
|
const bool __rtld_tbg_present = true;
|
|
const uint32_t __rtld_tbg_mode = RTLD_TRACE_BUFFER_MODE;
|
|
const uint32_t __rtld_tbg_buffer_size = RTLD_TRACE_BUFFER_WORDS;
|
|
uint32_t __rtld_tbg_buffer[RTLD_TRACE_BUFFER_WORDS];
|
|
volatile uint32_t __rtld_tbg_buffer_in;
|
|
volatile bool __rtld_tbg_finished;
|
|
volatile bool __rtld_tbg_triggered;
|
|
/*
|
|
* Lock the access.
|
|
*/
|
|
RTEMS_INTERRUPT_LOCK_DEFINE(static, __rtld_tbg_lock, "rtld-trace-buffer");
|
|
|
|
static inline uint32_t __rtld_tbg_in_irq(void)
|
|
{
|
|
return rtems_interrupt_is_in_progress() ? (1 << 31) : 0;
|
|
}
|
|
|
|
static inline uint32_t __rtld_tbg_executing_id(void)
|
|
{
|
|
return _Thread_Get_executing()->Object.id;
|
|
}
|
|
|
|
static inline uint32_t __rtld_tbg_executing_status(void)
|
|
{
|
|
/* @fixme Add the current CPU for SMP. */
|
|
struct Thread_Control* tc = _Thread_Get_executing();
|
|
return (tc->current_priority << 8) | tc->real_priority;
|
|
}
|
|
|
|
static inline uint32_t __rtld_tbg_executing_state(void)
|
|
{
|
|
return _Thread_Get_executing()->current_state;
|
|
}
|
|
|
|
static inline bool __rtld_tbg_is_enabled(const uint32_t index)
|
|
{
|
|
return (__rtld_trace_enables[index / 32] & (1 << (index & (32 - 1)))) != 0 ? true : false;
|
|
}
|
|
|
|
static inline bool __rtld_tbg_has_triggered(const uint32_t index)
|
|
{
|
|
if (!__rtld_tbg_triggered)
|
|
__rtld_tbg_triggered =
|
|
(__rtld_trace_triggers[index / 32] & (1 << (index & (32 - 1)))) != 0 ? true : false;
|
|
return __rtld_tbg_triggered;
|
|
}
|
|
|
|
static inline uint8_t* __rtld_tbg_buffer_alloc(const uint32_t index, const uint32_t size)
|
|
{
|
|
uint8_t* in = NULL;
|
|
if (!__rtld_tbg_finished && __rtld_tbg_has_triggered(index) && __rtld_tbg_is_enabled(index))
|
|
{
|
|
const uint32_t slots = ((size - 1) / sizeof(uint32_t)) + 1;
|
|
if (__rtld_tbg_buffer_in >= ((RTLD_TRACE_BUFFER_WORDS - slots)))
|
|
{
|
|
__rtld_tbg_finished = true;
|
|
}
|
|
else
|
|
{
|
|
in = (uint8_t*) &__rtld_tbg_buffer[__rtld_tbg_buffer_in];
|
|
__rtld_tbg_buffer_in += slots;
|
|
}
|
|
}
|
|
return in;
|
|
}
|
|
|
|
static inline void __rtld_tbg_buffer_entry(uint8_t** in, uint32_t func_index, uint32_t size)
|
|
{
|
|
if (*in)
|
|
{
|
|
uint32_t* in32 = (uint32_t*) *in;
|
|
uint64_t now = rtems_clock_get_uptime_nanoseconds();
|
|
*in32++ = func_index | (size << 16) | __rtld_tbg_in_irq();
|
|
*in32++ = __rtld_tbg_executing_id();
|
|
*in32++ = __rtld_tbg_executing_status();
|
|
*in32++ = __rtld_tbg_executing_state();
|
|
*in32++ = now >> 32;
|
|
*in32 = now;
|
|
*in += sizeof(func_index) + (3 * sizeof(uint32_t)) + sizeof(uint64_t);
|
|
}
|
|
}
|
|
|
|
static inline void __rtld_tbg_buffer_arg(uint8_t** in, int arg_size, void* arg)
|
|
{
|
|
if (*in)
|
|
{
|
|
memcpy(*in, arg, arg_size);
|
|
*in += arg_size;
|
|
}
|
|
}
|
|
|
|
static inline void __rtld_tbg_buffer_exit(uint8_t** in, uint32_t func_index, uint32_t size)
|
|
{
|
|
if (*in)
|
|
{
|
|
uint32_t* in32 = (uint32_t*) *in;
|
|
uint64_t now = rtems_clock_get_uptime_nanoseconds();
|
|
*in32++ = (1 << 30) | func_index | (size << 16) | __rtld_tbg_in_irq();
|
|
*in32++ = __rtld_tbg_executing_id();
|
|
*in32++ = __rtld_tbg_executing_status();
|
|
*in32++ = __rtld_tbg_executing_state();
|
|
*in32++ = now >> 32;
|
|
*in32 = now;
|
|
*in += sizeof(func_index) + (3 * sizeof(uint32_t)) + sizeof(uint64_t);
|
|
}
|
|
}
|
|
|
|
static inline void __rtld_tbg_buffer_ret(uint8_t* in, int ret_size, void* ret)
|
|
{
|
|
if (in)
|
|
{
|
|
memcpy(in, ret, ret_size);
|
|
}
|
|
}
|
|
CODE
|