diff --git a/src/util/perf/u_trace.c b/src/util/perf/u_trace.c index ea0028ddcb0..a73cd1384ff 100644 --- a/src/util/perf/u_trace.c +++ b/src/util/perf/u_trace.c @@ -24,6 +24,7 @@ #include #include "util/list.h" +#include "util/u_call_once.h" #include "util/u_debug.h" #include "util/u_inlines.h" #include "util/u_fifo.h" @@ -40,6 +41,15 @@ int _u_trace_instrument; +struct u_trace_state { + util_once_flag once; + FILE *trace_file; + bool trace_format_json; +}; +static struct u_trace_state u_trace_state = { + .once = UTIL_ONCE_FLAG_INIT +}; + #ifdef HAVE_PERFETTO int ut_perfetto_enabled; @@ -354,28 +364,41 @@ get_chunk(struct u_trace *ut, size_t payload_size) DEBUG_GET_ONCE_BOOL_OPTION(trace_instrument, "GPU_TRACE_INSTRUMENT", false) DEBUG_GET_ONCE_BOOL_OPTION(trace, "GPU_TRACE", false) -DEBUG_GET_ONCE_FILE_OPTION(trace_file, "GPU_TRACEFILE", NULL, "w") +DEBUG_GET_ONCE_OPTION(trace_file, "GPU_TRACEFILE", NULL) DEBUG_GET_ONCE_OPTION(trace_format, "GPU_TRACE_FORMAT", "txt") -static FILE * -get_tracefile(void) +static void +trace_file_fini(void) { - static FILE *tracefile = NULL; - static bool firsttime = true; + fclose(u_trace_state.trace_file); + u_trace_state.trace_file = NULL; +} - if (firsttime) { - tracefile = debug_get_option_trace_file(); - if (!tracefile && debug_get_option_trace()) { - tracefile = stdout; +static void +u_trace_state_init_once(void) +{ + const char *tracefile_name = debug_get_option_trace_file(); + if (tracefile_name && !__check_suid()) { + u_trace_state.trace_file = fopen(tracefile_name, "w"); + if (u_trace_state.trace_file != NULL) { + atexit(trace_file_fini); } - - if (tracefile || debug_get_option_trace_instrument()) - p_atomic_inc(&_u_trace_instrument); - - firsttime = false; + } + if (!u_trace_state.trace_file && debug_get_option_trace()) { + u_trace_state.trace_file = stdout; } - return tracefile; + if (u_trace_state.trace_file || debug_get_option_trace_instrument()) + p_atomic_inc(&_u_trace_instrument); + + const char *trace_format = debug_get_option_trace_format(); + u_trace_state.trace_format_json = !strcmp(trace_format, "json"); +} + +static void +u_trace_state_init(void) +{ + util_call_once(&u_trace_state.once, u_trace_state_init_once); } static void @@ -402,6 +425,8 @@ u_trace_context_init(struct u_trace_context *utctx, u_trace_read_ts read_timestamp, u_trace_delete_flush_data delete_flush_data) { + u_trace_state_init(); + utctx->pctx = pctx; utctx->create_timestamp_buffer = create_timestamp_buffer; utctx->delete_timestamp_buffer = delete_timestamp_buffer; @@ -418,10 +443,9 @@ u_trace_context_init(struct u_trace_context *utctx, list_inithead(&utctx->flushed_trace_chunks); - utctx->out = get_tracefile(); + utctx->out = u_trace_state.trace_file; - const char *trace_format = debug_get_option_trace_format(); - if (strcmp(trace_format, "json") == 0) { + if (u_trace_state.trace_format_json) { utctx->out_printer = &json_printer; } else { utctx->out_printer = &txt_printer;