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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2998>
This commit is contained in:
Jonas Ådahl 2022-10-26 11:52:02 +02:00 committed by Marge Bot
parent 604aeba9b3
commit dd3c1046c1

View File

@ -43,6 +43,7 @@
struct _CoglTraceContext struct _CoglTraceContext
{ {
gatomicrefcount ref_count;
SysprofCaptureWriter *writer; SysprofCaptureWriter *writer;
}; };
@ -51,23 +52,24 @@ typedef struct _CoglTraceThreadContext
int cpu_id; int cpu_id;
GPid pid; GPid pid;
char *group; char *group;
CoglTraceContext *trace_context;
} CoglTraceThreadContext; } CoglTraceThreadContext;
typedef struct typedef struct
{ {
int fd;
char *filename;
char *group; char *group;
CoglTraceContext *trace_context;
} TraceData; } TraceData;
static void cogl_trace_context_unref (CoglTraceContext *trace_context);
static void static void
trace_data_free (gpointer user_data) trace_data_free (gpointer user_data)
{ {
TraceData *data = user_data; TraceData *data = user_data;
data->fd = -1;
g_clear_pointer (&data->group, g_free); 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); g_free (data);
} }
@ -102,27 +104,42 @@ cogl_trace_context_new (int fd,
context = g_new0 (CoglTraceContext, 1); context = g_new0 (CoglTraceContext, 1);
context->writer = writer; context->writer = writer;
g_atomic_ref_count_init (&context->ref_count);
return context; return context;
} }
static void 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); if (g_atomic_ref_count_dec (&trace_context->ref_count))
g_free (trace_context); {
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 static void
ensure_trace_context (TraceData *data) ensure_trace_context (int fd,
const char *filename)
{ {
g_mutex_lock (&cogl_trace_mutex); g_mutex_lock (&cogl_trace_mutex);
if (!cogl_trace_context) 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); g_mutex_unlock (&cogl_trace_mutex);
} }
static CoglTraceThreadContext * static CoglTraceThreadContext *
cogl_trace_thread_context_new (const char *group) cogl_trace_thread_context_new (const char *group,
CoglTraceContext *trace_context)
{ {
CoglTraceThreadContext *thread_context; CoglTraceThreadContext *thread_context;
pid_t tid; pid_t tid;
@ -134,6 +151,7 @@ cogl_trace_thread_context_new (const char *group)
thread_context->pid = getpid (); thread_context->pid = getpid ();
thread_context->group = thread_context->group =
group ? g_strdup (group) : g_strdup_printf ("t:%d", tid); group ? g_strdup (group) : g_strdup_printf ("t:%d", tid);
thread_context->trace_context = cogl_trace_context_ref (trace_context);
return thread_context; return thread_context;
} }
@ -145,15 +163,14 @@ enable_tracing_idle_callback (gpointer user_data)
g_private_get (&cogl_trace_thread_data); g_private_get (&cogl_trace_thread_data);
TraceData *data = user_data; TraceData *data = user_data;
ensure_trace_context (data);
if (thread_context) if (thread_context)
{ {
g_warning ("Tracing already enabled"); g_warning ("Tracing already enabled");
return G_SOURCE_REMOVE; 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); g_private_set (&cogl_trace_thread_data, thread_context);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
@ -176,7 +193,6 @@ disable_tracing_idle_callback (gpointer user_data)
{ {
CoglTraceThreadContext *thread_context = CoglTraceThreadContext *thread_context =
g_private_get (&cogl_trace_thread_data); g_private_get (&cogl_trace_thread_data);
CoglTraceContext *trace_context;
if (!thread_context) if (!thread_context)
{ {
@ -186,14 +202,6 @@ disable_tracing_idle_callback (gpointer user_data)
g_private_replace (&cogl_trace_thread_data, NULL); 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; return G_SOURCE_REMOVE;
} }
@ -205,10 +213,11 @@ set_tracing_enabled_on_thread (GMainContext *main_context,
{ {
TraceData *data; TraceData *data;
ensure_trace_context (fd, filename);
data = g_new0 (TraceData, 1); data = g_new0 (TraceData, 1);
data->fd = fd;
data->group = group ? strdup (group) : NULL; 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 ()) if (main_context == g_main_context_get_thread_default ())
{ {
@ -249,6 +258,10 @@ cogl_set_tracing_enabled_on_thread (GMainContext *main_context,
void void
cogl_set_tracing_disabled_on_thread (GMainContext *main_context) 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) if (g_main_context_get_thread_default () == main_context)
{ {
disable_tracing_idle_callback (NULL); disable_tracing_idle_callback (NULL);
@ -275,8 +288,8 @@ cogl_trace_end_with_description (CoglTraceHead *head,
CoglTraceThreadContext *trace_thread_context; CoglTraceThreadContext *trace_thread_context;
end_time = g_get_monotonic_time () * 1000; end_time = g_get_monotonic_time () * 1000;
trace_context = cogl_trace_context;
trace_thread_context = g_private_get (&cogl_trace_thread_data); trace_thread_context = g_private_get (&cogl_trace_thread_data);
trace_context = trace_thread_context->trace_context;
g_mutex_lock (&cogl_trace_mutex); g_mutex_lock (&cogl_trace_mutex);
if (!sysprof_capture_writer_add_mark (trace_context->writer, if (!sysprof_capture_writer_add_mark (trace_context->writer,