From 5229a147c1a41fbe7b969b8bd5d4f05353b91cd9 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Thu, 1 Sep 2022 22:22:31 +0800 Subject: [PATCH] util: getting get_tracefile in u_trace.c to be thread safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the usage of DEBUG_GET_ONCE_FILE_OPTION because it's not a truly once function, it's return a new FILE* object when calling to it when the conditions are satisfied. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7151 Signed-off-by: Yonggang Luo Acked-by: Marek Olšák Reviewed-by: Chia-I Wu Part-of: --- src/util/perf/u_trace.c | 60 ++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) 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;