11#ifndef O2_FRAMEWORK_SIGNPOST_H_
12#define O2_FRAMEWORK_SIGNPOST_H_
22 char const*
name =
nullptr;
32 std::array<char, N>
res = {};
35 for (
int i = 0;
i < N; ++
i) {
36 if (
src[
i] ==
'%' &&
src[
i + 1] ==
'{') {
38 while (
src[
i] !=
'}' &&
src[
i] != 0) {
58#ifdef O2_SIGNPOST_IMPLEMENTATION
63 static std::atomic<o2_log_handle_t*>
first =
nullptr;
78 bool cont = callback(current->
name, current->
log, context);
83 current = current->
next;
91#include <os/signpost.h>
93#define O2_LOG_DEBUG_MAC(log, format, ...) os_log_debug(private_o2_log_##log, format __VA_OPT__(, ) __VA_ARGS__)
94#define O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ...) os_signpost_event_emit(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
95#define O2_SIGNPOST_START_MAC(log, id, name, format, ...) os_signpost_interval_begin(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
96#define O2_SIGNPOST_END_MAC(log, id, name, format, ...) os_signpost_interval_end(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
97#define O2_SIGNPOST_ENABLED_MAC(log) os_signpost_enabled(private_o2_log_##log->os_log)
100#define O2_DECLARE_LOG_MAC(x, category)
101#define O2_LOG_DEBUG_MAC(log, ...)
102#define O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ...)
103#define O2_SIGNPOST_START_MAC(log, id, name, format, ...)
104#define O2_SIGNPOST_END_MAC(log, id, name, format, ...)
105#define O2_SIGNPOST_ENABLED_MAC(log) false
109#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
110#define O2_LOG_ENABLED(log) private_o2_log_##log->stacktrace
112#define O2_LOG_ENABLED(log) false
115#if !defined(O2_LOG_MACRO_RAW) && __has_include("Framework/Logger.h")
117#define O2_LOG_MACRO_RAW(level, ...) LOGF(level, __VA_ARGS__)
118#elif !defined(O2_LOG_MACRO_RAW)
121#define O2_LOG_MACRO_RAW(level, format, ...) \
123 printf(#level ":" #format, __VA_ARGS__); \
127#define O2_LOG_MACRO_RAW(...)
130#if !defined(O2_LOG_MACRO) && __has_include("Framework/Logger.h")
132#define O2_LOG_MACRO(...) LOGF(info, __VA_ARGS__)
133#elif !defined(O2_LOG_MACRO)
136#define O2_LOG_MACRO(...) \
138 printf(__VA_ARGS__); \
142#define O2_LOG_MACRO(...)
154 static constexpr size_t N = 1024;
155 std::atomic<size_t>
top = 0;
177 os_log_t os_log =
nullptr;
182 std::array<_o2_signpost_id_t, 256>
ids = {};
225 assert(((int64_t)
pointer & 1) != 1);
232#ifdef O2_SIGNPOST_IMPLEMENTATION
245 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
251#if defined(__x86_64__) || defined(__i386__)
252 __asm__ __volatile__(
"pause" ::
254#elif defined(__aarch64__)
255 __asm__ __volatile__(
"yield" ::
261 if (
stack.top.compare_exchange_weak(currentTop, currentTop + 1,
262 std::memory_order_release,
263 std::memory_order_relaxed)) {
272 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
274 if (currentTop == 0 && spin ==
false) {
276 }
else if (currentTop == 0) {
278#if defined(__x86_64__) || defined(__i386__)
279 __asm__ __volatile__(
"pause" ::
281#elif defined(__aarch64__)
282 __asm__ __volatile__(
"yield" ::
288 if (
stack.top.compare_exchange_weak(currentTop, currentTop - 1,
289 std::memory_order_acquire,
290 std::memory_order_relaxed)) {
302 char const*
name = (
char const*)context;
303 if (strcmp(
name, currentName) == 0) {
319 for (
int i = 0;
i <
n;
i++) {
323 log->defaultStacktrace = defaultStacktrace;
325 newHandle->log = log;
329 if (defaultStacktrace > 1) {
330 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_STACK_TRACING);
332 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_TRACING);
335 newHandle->name = strdup(
name);
340 while (!
o2_get_logs_tail().compare_exchange_weak(newHandle->next, newHandle,
341 std::memory_order_release,
342 std::memory_order_relaxed)) {
362 for (
i = 0;
i < log->
ids.size(); ++
i) {
363 if (log->
ids[
i].value ==
id.value) {
369 if (
i != log->
ids.size()) {
376 char prebuffer[4096];
377 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16s*>%*c",
id.
value,
name, leading,
' ');
378 vsnprintf(prebuffer + s, 4096 - s,
format, args);
399 log->
ids[signpost_index].value =
id.value;
400 auto* activity = &log->
activities[signpost_index];
402 activity->name =
name;
403 int leading = activity->indentation * 2;
404 char prebuffer[4096];
405 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sS>%*c",
id.
value,
name, leading,
' ');
406 vsnprintf(prebuffer + s, 4096 - s,
format, args);
418 for (
i = 0;
i < log->
ids.size(); ++
i) {
419 if (log->
ids[
i].value ==
id.value) {
426 if (
i == log->
ids.size()) {
433 char prebuffer[4096];
434 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sE>%*c",
id.
value,
name, leading,
' ');
435 vsnprintf(prebuffer + s, 4096 - s,
format, args);
439 activity->
name =
nullptr;
440 log->
ids[
i].value = -1;
452 _o2_signpost_interval_end_v(log,
id,
name,
format, args);
463void o2_debug_log_set_stacktrace(
_o2_log_t* log,
int stacktrace)
470#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
473#define O2_DECLARE_DYNAMIC_LOG(name) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 1)
475#define O2_DECLARE_DYNAMIC_STACKTRACE_LOG(name) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 64)
476#define O2_DECLARE_LOG(name, category) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 1)
478#define O2_LOG_ENABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, private_o2_log_##log->defaultStacktrace)
479#define O2_LOG_DISABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, 0)
482#define O2_LOG_DEBUG(log, ...) __extension__({ \
483 if (O2_BUILTIN_UNLIKELY(O2_LOG_ENABLED(log))) { \
484 O2_LOG_MACRO(__VA_ARGS__); \
485 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
486 O2_LOG_MACRO(__VA_ARGS__); \
489#define O2_SIGNPOST_ID_FROM_POINTER(name, log, pointer) _o2_signpost_id_t name = _o2_signpost_id_make_with_pointer(private_o2_log_##log, pointer)
490#define O2_SIGNPOST_ID_GENERATE(name, log) _o2_signpost_id_t name = _o2_signpost_id_generate_local(private_o2_log_##log)
495#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...) __extension__({ \
496 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
497 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
498 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
499 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
504#define O2_SIGNPOST_EVENT_EMIT_INFO(log, id, name, format, ...) __extension__({ \
505 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
506 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
507 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
508 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
510 O2_LOG_MACRO_RAW(info, remove_engineering_type(format).data(), ##__VA_ARGS__); \
515#define O2_SIGNPOST_EVENT_EMIT_ERROR(log, id, name, format, ...) __extension__({ \
516 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
517 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
518 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
519 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
521 O2_LOG_MACRO_RAW(error, remove_engineering_type(format).data(), ##__VA_ARGS__); \
525#define O2_SIGNPOST_EVENT_EMIT_WARN(log, id, name, format, ...) __extension__({ \
526 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
527 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
528 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
529 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
531 O2_LOG_MACRO_RAW(warn, remove_engineering_type(format).data(), ##__VA_ARGS__); \
534#define O2_SIGNPOST_START(log, id, name, format, ...) \
535 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
536 O2_SIGNPOST_START_MAC(log, id, name, format, ##__VA_ARGS__); \
537 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
538 _o2_signpost_interval_begin(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
540#define O2_SIGNPOST_END(log, id, name, format, ...) \
541 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
542 O2_SIGNPOST_END_MAC(log, id, name, format, ##__VA_ARGS__); \
543 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
544 _o2_signpost_interval_end(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
547#define O2_DECLARE_DYNAMIC_LOG(x)
548#define O2_DECLARE_DYNAMIC_STACKTRACE_LOG(x)
549#define O2_DECLARE_LOG(x, category)
550#define O2_LOG_ENABLE(log)
551#define O2_LOG_DISABLE(log)
552#define O2_LOG_DEBUG(log, ...)
553#define O2_SIGNPOST_ID_FROM_POINTER(name, log, pointer)
554#define O2_SIGNPOST_ID_GENERATE(name, log)
555#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...)
556#define O2_SIGNPOST_START(log, id, name, format, ...)
557#define O2_SIGNPOST_END(log, id, name, format, ...)
o2_log_handle_t * o2_walk_logs(bool(*callback)(char const *name, void *log, void *context), void *context=nullptr)
bool _o2_lock_free_stack_push(_o2_lock_free_stack &stack, const int &value, bool spin=false)
void _o2_signpost_interval_end(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
void _o2_log_set_stacktrace(_o2_log_t *log, int stacktrace)
void _o2_signpost_event_emit(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
bool _o2_lock_free_stack_pop(_o2_lock_free_stack &stack, int &value, bool spin=false)
_o2_signpost_id_t _o2_signpost_id_generate_local(_o2_log_t *log)
std::atomic< o2_log_handle_t * > & o2_get_logs_tail()
consteval auto remove_engineering_type(char const (&src)[N])
#define O2_LOG_MACRO(...)
_o2_signpost_id_t _o2_signpost_id_make_with_pointer(_o2_log_t *log, void const *pointer)
void _o2_signpost_interval_begin(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
void * _o2_log_create(char const *name, int stacktrace)
GLdouble GLdouble GLdouble GLdouble top
GLuint const GLchar * name
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum format
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
unsigned char indentation
static constexpr size_t N
std::atomic< int64_t > current_indentation
_o2_lock_free_stack slots
std::array< _o2_signpost_id_t, 256 > ids
std::array< _o2_activity_t, 256 > activities
std::atomic< int64_t > unique_signpost
static void demangled_backtrace_symbols(void **backtrace, unsigned int total, int fd)
static constexpr unsigned int MAX_BACKTRACE_SIZE