From dd3c1046c1dc7e5b64557fb475f674f9913dbd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 26 Oct 2022 11:52:02 +0200 Subject: [PATCH] cogl/trace: Make each thread have its own trace context ref This means that when we disable tracing, the writer will be kept alive until the last thread using it is disabled. Part-of: --- cogl/cogl/cogl-trace.c | 63 +++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/cogl/cogl/cogl-trace.c b/cogl/cogl/cogl-trace.c index 22aff2892..e74a116b5 100644 --- a/cogl/cogl/cogl-trace.c +++ b/cogl/cogl/cogl-trace.c @@ -43,6 +43,7 @@ struct _CoglTraceContext { + gatomicrefcount ref_count; SysprofCaptureWriter *writer; }; @@ -51,23 +52,24 @@ typedef struct _CoglTraceThreadContext int cpu_id; GPid pid; char *group; + CoglTraceContext *trace_context; } CoglTraceThreadContext; typedef struct { - int fd; - char *filename; char *group; + CoglTraceContext *trace_context; } TraceData; +static void cogl_trace_context_unref (CoglTraceContext *trace_context); + static void trace_data_free (gpointer user_data) { TraceData *data = user_data; - data->fd = -1; g_clear_pointer (&data->group, g_free); - g_clear_pointer (&data->filename, g_free); + g_clear_pointer (&data->trace_context, cogl_trace_context_unref); g_free (data); } @@ -102,27 +104,42 @@ cogl_trace_context_new (int fd, context = g_new0 (CoglTraceContext, 1); context->writer = writer; + g_atomic_ref_count_init (&context->ref_count); return context; } static void -cogl_trace_context_free (CoglTraceContext *trace_context) +cogl_trace_context_unref (CoglTraceContext *trace_context) { - g_clear_pointer (&trace_context->writer, sysprof_capture_writer_unref); - g_free (trace_context); + if (g_atomic_ref_count_dec (&trace_context->ref_count)) + { + if (trace_context->writer) + sysprof_capture_writer_flush (trace_context->writer); + g_clear_pointer (&trace_context->writer, sysprof_capture_writer_unref); + g_free (trace_context); + } +} + +static CoglTraceContext * +cogl_trace_context_ref (CoglTraceContext *trace_context) +{ + g_atomic_ref_count_inc (&trace_context->ref_count); + return trace_context; } static void -ensure_trace_context (TraceData *data) +ensure_trace_context (int fd, + const char *filename) { g_mutex_lock (&cogl_trace_mutex); if (!cogl_trace_context) - cogl_trace_context = cogl_trace_context_new (data->fd, data->filename); + cogl_trace_context = cogl_trace_context_new (fd, filename); g_mutex_unlock (&cogl_trace_mutex); } static CoglTraceThreadContext * -cogl_trace_thread_context_new (const char *group) +cogl_trace_thread_context_new (const char *group, + CoglTraceContext *trace_context) { CoglTraceThreadContext *thread_context; pid_t tid; @@ -134,6 +151,7 @@ cogl_trace_thread_context_new (const char *group) thread_context->pid = getpid (); thread_context->group = group ? g_strdup (group) : g_strdup_printf ("t:%d", tid); + thread_context->trace_context = cogl_trace_context_ref (trace_context); return thread_context; } @@ -145,15 +163,14 @@ enable_tracing_idle_callback (gpointer user_data) g_private_get (&cogl_trace_thread_data); TraceData *data = user_data; - ensure_trace_context (data); - if (thread_context) { g_warning ("Tracing already enabled"); return G_SOURCE_REMOVE; } - thread_context = cogl_trace_thread_context_new (data->group); + thread_context = cogl_trace_thread_context_new (data->group, + data->trace_context); g_private_set (&cogl_trace_thread_data, thread_context); return G_SOURCE_REMOVE; @@ -176,7 +193,6 @@ disable_tracing_idle_callback (gpointer user_data) { CoglTraceThreadContext *thread_context = g_private_get (&cogl_trace_thread_data); - CoglTraceContext *trace_context; if (!thread_context) { @@ -186,14 +202,6 @@ disable_tracing_idle_callback (gpointer user_data) g_private_replace (&cogl_trace_thread_data, NULL); - g_mutex_lock (&cogl_trace_mutex); - trace_context = cogl_trace_context; - sysprof_capture_writer_flush (trace_context->writer); - - g_clear_pointer (&cogl_trace_context, cogl_trace_context_free); - - g_mutex_unlock (&cogl_trace_mutex); - return G_SOURCE_REMOVE; } @@ -205,10 +213,11 @@ set_tracing_enabled_on_thread (GMainContext *main_context, { TraceData *data; + ensure_trace_context (fd, filename); + data = g_new0 (TraceData, 1); - data->fd = fd; data->group = group ? strdup (group) : NULL; - data->filename = filename ? strdup (filename) : NULL; + data->trace_context = cogl_trace_context_ref (cogl_trace_context); if (main_context == g_main_context_get_thread_default ()) { @@ -249,6 +258,10 @@ cogl_set_tracing_enabled_on_thread (GMainContext *main_context, void cogl_set_tracing_disabled_on_thread (GMainContext *main_context) { + g_mutex_lock (&cogl_trace_mutex); + g_clear_pointer (&cogl_trace_context, cogl_trace_context_unref); + g_mutex_unlock (&cogl_trace_mutex); + if (g_main_context_get_thread_default () == main_context) { disable_tracing_idle_callback (NULL); @@ -275,8 +288,8 @@ cogl_trace_end_with_description (CoglTraceHead *head, CoglTraceThreadContext *trace_thread_context; end_time = g_get_monotonic_time () * 1000; - trace_context = cogl_trace_context; trace_thread_context = g_private_get (&cogl_trace_thread_data); + trace_context = trace_thread_context->trace_context; g_mutex_lock (&cogl_trace_mutex); if (!sysprof_capture_writer_add_mark (trace_context->writer,