; ; RTEMS Trace Linker Trace Buffer ; ; Copyright 2015 Chris Johns ; ; ; 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 " header = "#include " header = "#include " header = "#include " [trace-buffer-tracers] code = <<Object.id; } static inline uint32_t __rtld_tbg_executing_status(void) { /* @fixme Add the current CPU for SMP. */ Thread_Control* tc = _Thread_Get_executing(); return (_Thread_Get_priority(tc) << 8) | tc->Real_priority.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