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,