| /* TODO(gvdl): Who holds the copyright? |
| * Godfrey van der Linden <gvdl@google.com> |
| * See LICENSE for details. |
| * |
| * Timed tracing. |
| * Kernel header |
| * TODO(gvdl): Documentation goes here. */ |
| #ifndef INC_TTRACE_H |
| #define INC_TTRACE_H |
| |
| #define TTRACE_NULL_STATEMENT do { } while(0) |
| |
| #ifndef CONFIG_TTRACE |
| |
| // If the TTRACE is not configured then null out the initters |
| #define ttrace_init() TTRACE_NULL_STATEMENT |
| #define ttrace_cleanup() TTRACE_NULL_STATEMENT |
| |
| #else /* CONFIG_TTRACE */ |
| |
| #include <atomic.h> |
| #include <ros/ttrace.h> |
| |
| // Global data |
| |
| // Active tracepoint mask, see TTRACE_TYPE... enums in ros/ttrace.h |
| extern uint64_t ttrace_type_mask; |
| |
| // Two phase initialisation. Call ttrace_init() as soon as page memory |
| // allocation is possible so that we can trace very early in system boot. |
| // However, that early in boot we do not yet know how many cores we will |
| // manange, ttrace_cleanup() is called once we know and returns memory |
| // previously allocated for unused cores. |
| extern void ttrace_init(); |
| extern void ttrace_cleanup(); |
| |
| // devttrace accessor routines |
| struct trace_ring* get_ttrace_ring_for_core(uint32_t coreid); |
| void fill_ttrace_version(struct ttrace_version *versp); |
| const uint8_t *bufferp get_ttrace_aux_buffer(void) |
| void get_ttrace_aux_buffer_snapshot(ptrdiff_t *firstp, ptrdiff_t *lastp); |
| |
| // Low level data collection apis, do not use directly but rather use the macro |
| // wrappers, such as TTRACE_PROC_ALLOC() below. |
| extern uint64_t _ttrace_point(uint64_t type_start_stop, |
| uintptr_t d0, uintptr_t d1, uintptr_t d2, |
| uintptr_t d3, uintptr_t d4); |
| extern void _ttrace_point_cont(uint64_t timestamp, uintptr_t d0, uintptr_t d1, |
| uintptr_t d2, uintptr_t d3, uintptr_t d4, |
| uintptr_t d5, uintptr_t d6); |
| // Slow takes rwlock, updates auxillary buffer, call this rarely |
| extern void _ttrace_point_string(uint8_t tag, uintptr_t ident, const char *str); |
| |
| static inline uintptr_t __attribute__((always_inline)) |
| take_tracepoint(uintptr_t type_start_stop) |
| { |
| uintptr_t cur_mask = atomic_read((atomic_t *) &ttrace_type_mask); |
| return cur_mask & type_start_stop & TTRACE_TYPE_MASK; |
| } |
| |
| static inline uint64_t _ttrace_point5(uint64_t type_start_stop, |
| uintptr_t d0, uintptr_t d1, uintptr_t d2, |
| uintptr_t d3, uintptr_t d4) |
| { |
| if (take_tracepoint(type_start_stop)) |
| return _ttrace_point(type_start_stop, d0, d1, d2, d3, d4); |
| return 0; |
| } |
| #define TTRACE_POINT5(type, start_stop, data...) do { \ |
| static_assert(type & TTRACE_TYPE_MASK); \ |
| _ttrace_point5(type | start_stop, data); \ |
| } while(false) |
| |
| static inline uint64_t _ttrace_point12(uint64_t type_start_stop, |
| uintptr_t d0, uintptr_t d1, uintptr_t d2, |
| uintptr_t d3, uintptr_t d4, uintptr_t d5, |
| uintptr_t d6, uintptr_t d7, uintptr_t d8, |
| uintptr_t d9, uintptr_t da, uintptr_t db) |
| { |
| if (take_tracepoint(type_start_stop)) { |
| const uint64_t tsc = _ttrace_point(type_start_stop, d0, d1, d2, d3, d4); |
| _ttrace_point_cont(tsc, d5, d6, d7, d8, d9, da, db); |
| return tsc; |
| } else |
| return 0; |
| } |
| #define TTRACE_POINT12(type, start_stop, data...) do { \ |
| static_assert(type & TTRACE_TYPE_MASK); \ |
| _ttrace_point12(type | start_stop, data); \ |
| } while(false) |
| |
| static inline void _ttrace_string(uint64_t type, uint8_t tag, |
| uintptr_t ident, const char* str) |
| { |
| if (take_tracepoint(type)) |
| _ttrace_point_string(tag, ident, str); |
| } |
| // string len < TTRACE_AUX_ENTRY_MAXSTRLEN |
| #define TTRACE_STRING(type, tag, ident, str) do { \ |
| static_assert(type & TTRACE_TYPE_MASK); \ |
| static_assert(tag & TTRACEH_TAG_MASK); \ |
| _ttrace_string(type, tag, ident, str); |
| } while(false) |
| |
| // |
| // CONFIG_TTRACE macros |
| // |
| // These macros are the data collection side of ttrace. Each CONFIG_TTRACE type |
| // has its own group of macros which are empty if the group is not configured. |
| |
| // CONFIG_TTRACE_PROCESS trace point macros. |
| #ifdef CONFIG_TTRACE_PROCESS |
| #define TTRACE_PROC_ALLOC(pid, ppid) TTRACE_POINT5( \ |
| TTRACE_TYPE_PROCESS, TTRACE_ENTRY_START, pid, ppid, 0, 0, 0); |
| #define TTRACE_PROC_FREE(pid, cpid) TTRACE_POINT5( \ |
| TTRACE_TYPE_PROCESS, TTRACE_ENTRY_STOP, pid, cpid, 0, 0, 0); |
| #define TTRACE_PROC_READY(pid) TTRACE_POINT5( \ |
| TTRACE_TYPE_PROCESS, TTRACE_ENTRY_ENTRY, pid, 0, 0, 0, 0); |
| #define TTRACE_PROC_SETSTATE(pid, state, curstate) TTRACE_POINT5( \ |
| TTRACE_TYPE_PROCESS, TTRACE_ENTRY_EXIT, pid, state, curstate, 0, 0); |
| #define TTRACE_PROC_SETNAME(pid, name) \ |
| TTRACE_STRING(TTRACE_TYPE_PROCESS, TTRACEH_TAG_PROC, pid, name) |
| #else /* !CONFIG_TTRACE_PROCESS */ |
| #define TTRACE_PROC_ALLOC(pid, ppid) TTRACE_NULL_STATEMENT |
| #define TTRACE_PROC_FREE(pid, cpid) TTRACE_NULL_STATEMENT |
| #define TTRACE_PROC_READY(pid) TTRACE_NULL_STATEMENT |
| #define TTRACE_PROC_SETSTATE(pid, state, curstate) TTRACE_NULL_STATEMENT |
| #define TTRACE_PROC_SETNAME(pid, name) TTRACE_NULL_STATEMENT |
| #endif /* CONFIG_TTRACE_PROCESS */ |
| |
| #endif /* !CONFIG_TTRACE */ |
| #endif /* INC_TTRACE_H */ |