On 9/8/25 00:05, Pierrick Bouvier wrote:
On 8/8/25 2:45 PM, Philippe Mathieu-Daudé wrote:
On 8/8/25 22:41, Pierrick Bouvier wrote:
We implement tracing, following uftrace format.
Trace is flushed every 32 MB, so file operations don't impact
performance at runtime.

A different trace is generated per cpu, and we ensure they have a unique
name, based on vcpu_index, while keeping room for privilege level coming
in next commit.

Uftrace format is not officially documented, but it can be found here:
https://github.com/namhyung/uftrace/blob/v0.18/libmcount/record.c#L909

Signed-off-by: Pierrick Bouvier <pierrick.bouv...@linaro.org>
---
   contrib/plugins/uftrace.c | 150 ++++++++++++++++++++++++++++++++++ +++-
   1 file changed, 149 insertions(+), 1 deletion(-)


@@ -297,6 +432,16 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index)
       cpu->ops.init(cpu);
       cpu->buf = g_byte_array_new();
+    g_assert(vcpu_index < UINT32_MAX / 100);
+    /* trace_id is: cpu_number * 100 */
+    uint32_t trace_id = (vcpu_index + 1) * 100;
+
+    g_autoptr(GString) trace_name = g_string_new(NULL);
+    g_string_append_printf(trace_name, "cpu%u", vcpu_index);

    g_autofree char *trace_name = g_strdup_printf("cpu%u", vcpu_index);

and pass (const?) char * to trace_new().


I tried to do something clean with GString everywhere for dynamic/ mutable strings, and const char* for immutable ones, favoring readability and clear memory ownership over C char pointer soup. It does not optimize anything important in this context since it's called only once during the program execution.

Thus, I would prefer to keep it as it is if that's acceptable for you.

No problem.

+    cpu->trace = trace_new(trace_id, trace_name);
+    /* create/truncate trace file */
+    trace_flush(cpu->trace, false);
+
       cpu->cs = callstack_new();
   }

Reviewed-by: Philippe Mathieu-Daudé <phi...@linaro.org>




Reply via email to