All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: fam@euphon.net, berrange@redhat.com, f4bug@amsat.org,
	aurelien@aurel32.net, pbonzini@redhat.com, stefanha@redhat.com,
	crosa@redhat.com, "Alex Bennée" <alex.bennee@linaro.org>,
	"Idan Horowitz" <idan.horowitz@gmail.com>,
	"Alexandre Iooss" <erdnaxe@crans.org>,
	"Mahmoud Mandour" <ma.mandourr@gmail.com>
Subject: [PATCH v2 09/12] tests/plugins: add a new vcpu state tracking plugin
Date: Fri, 11 Nov 2022 14:55:26 +0000	[thread overview]
Message-ID: <20221111145529.4020801-10-alex.bennee@linaro.org> (raw)
In-Reply-To: <20221111145529.4020801-1-alex.bennee@linaro.org>

Although we call qemu_plugin_register_vcpu_idle_cb() in the bb test we
don't really exercise the rest of the state change callbacks. Add a
new test that tests the whole API.

[AJB: I wrote this in an attempt to flush out a reproducer for #1195
although so far no joy.]

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Cc: Idan Horowitz <idan.horowitz@gmail.com>

----
v2
  - and min max tracking
  - fix { style on get_timestamp
---
 tests/plugin/vcpu.c      | 153 +++++++++++++++++++++++++++++++++++++++
 tests/plugin/meson.build |   2 +-
 2 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 tests/plugin/vcpu.c

diff --git a/tests/plugin/vcpu.c b/tests/plugin/vcpu.c
new file mode 100644
index 0000000000..f4fa518420
--- /dev/null
+++ b/tests/plugin/vcpu.c
@@ -0,0 +1,153 @@
+/*
+ * Test plugin for exercising the vcpu event callbacks. These exist
+ * for when vcpus are created and destroyed (especially in linux-user
+ * where vcpu ~= thread) and when they pause and restart (generally
+ * for wfi and the like in system emulation).
+ *
+ * Copyright (c) 2022 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <inttypes.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include <qemu-plugin.h>
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+typedef struct {
+    uint64_t start_time_ns;
+    uint64_t idle_count;
+    uint64_t last_idle_ts;
+    uint64_t min_idle_ns;
+    uint64_t max_idle_ns;
+    uint64_t total_idle_ns;
+    uint64_t exit_time_ns;
+} VCPUData;
+
+static GMutex expand_counts_lock;
+static GArray *counts; /* array of VCPUData */
+static bool sys_emu;
+
+/*
+ * Fetch VCPU data for a given index, allocate if required.
+ */
+static VCPUData *get_vcpu_data(int cpu_index)
+{
+    if (cpu_index >= counts->len) {
+        g_mutex_lock(&expand_counts_lock);
+        counts = g_array_set_size(counts, cpu_index + 1);
+        g_mutex_unlock(&expand_counts_lock);
+    }
+    /* race if set size re-allocs? */
+    return &g_array_index(counts, VCPUData, cpu_index);
+}
+
+static uint64_t get_timestamp(void)
+{
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+}
+
+static void vcpu_init(qemu_plugin_id_t id, unsigned int cpu_index)
+{
+    VCPUData *d = get_vcpu_data(cpu_index);
+    d->start_time_ns = get_timestamp();
+    d->min_idle_ns = UINT64_MAX;
+}
+
+static void vcpu_idle(qemu_plugin_id_t id, unsigned int cpu_index)
+{
+    VCPUData *d = get_vcpu_data(cpu_index);
+    d->last_idle_ts = get_timestamp();
+    d->idle_count++;
+}
+
+static void vcpu_resume(qemu_plugin_id_t id, unsigned int cpu_index)
+{
+    VCPUData *d = get_vcpu_data(cpu_index);
+    uint64_t now = get_timestamp();
+    uint64_t delta = now - d->last_idle_ts;
+    d->total_idle_ns += delta;
+    if (delta > d->max_idle_ns) {
+        d->max_idle_ns = delta;
+    } else if (delta < d->min_idle_ns) {
+        d->min_idle_ns = delta;
+    }
+}
+
+static void vcpu_exit(qemu_plugin_id_t id, unsigned int cpu_index)
+{
+    VCPUData *d = get_vcpu_data(cpu_index);
+    d->exit_time_ns = get_timestamp();
+}
+
+/*
+ * Report our final stats
+ */
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+    g_autoptr(GString) report = g_string_new("");
+    const char *vcpu_or_thread = sys_emu ? "vcpu" : "thread";
+    int i;
+
+    g_string_printf(report, "Exit: we had a total of %d %ss\n",
+                    counts->len, vcpu_or_thread);
+
+    for (i = 0; i < counts->len; i++) {
+        VCPUData *d = &g_array_index(counts, VCPUData, i);
+
+        /* FIXME: we never see vcpu_exit for the main thread */
+        if (!d->exit_time_ns) {
+            d->exit_time_ns = get_timestamp();
+        }
+
+        g_string_append_printf(report, "%s %d: %"PRId64" µs lifetime",
+                               vcpu_or_thread, i,
+                               (d->exit_time_ns - d->start_time_ns) / 1000);
+        if (d->idle_count) {
+            uint64_t idle_us = d->total_idle_ns / 1000;
+            uint64_t idle_avg = d->total_idle_ns / d->idle_count;
+            g_string_append_printf(report, ", %"PRId64" idles, %"
+                                   PRId64 " µs total idle time, %"
+                                   PRId64 " ns min, %"
+                                   PRId64 " ns max, %"
+                                   PRId64 " ns per idle",
+                                   d->idle_count, idle_us,
+                                   d->min_idle_ns, d->max_idle_ns, idle_avg);
+        }
+        g_string_append_printf(report, "\n");
+    }
+    qemu_plugin_outs(report->str);
+}
+
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
+                                           const qemu_info_t *info,
+                                           int argc, char **argv)
+{
+    int entries = 2;
+
+    if (info->system_emulation) {
+        entries = info->system.max_vcpus;
+        sys_emu = true;
+    }
+
+    counts = g_array_sized_new(true, true, sizeof(VCPUData), entries);
+    g_mutex_init(&expand_counts_lock);
+
+    qemu_plugin_register_vcpu_init_cb(id, vcpu_init);
+    qemu_plugin_register_vcpu_idle_cb(id, vcpu_idle);
+    qemu_plugin_register_vcpu_resume_cb(id, vcpu_resume);
+    qemu_plugin_register_vcpu_exit_cb(id, vcpu_exit);
+
+    qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
+    return 0;
+}
diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build
index 2bbfc4b19e..8c6b232183 100644
--- a/tests/plugin/meson.build
+++ b/tests/plugin/meson.build
@@ -1,5 +1,5 @@
 t = []
-foreach i : ['bb', 'empty', 'insn', 'mem', 'syscall']
+foreach i : ['bb', 'empty', 'insn', 'mem', 'syscall', 'vcpu']
   t += shared_module(i, files(i + '.c'),
                      include_directories: '../../include/qemu',
                      dependencies: glib)
-- 
2.34.1



  parent reply	other threads:[~2022-11-11 14:57 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-11 14:55 [PATCH for 7.2-rc1 v2 00/12] testing, docs, plugins, arm pre-PR Alex Bennée
2022-11-11 14:55 ` [PATCH v2 01/12] Run docker probe only if docker or podman are available Alex Bennée
2022-11-11 16:50   ` Thomas Huth
2022-11-11 14:55 ` [PATCH v2 02/12] tests/avocado: improve behaviour waiting for login prompts Alex Bennée
2022-11-14 16:28   ` Peter Maydell
2022-11-14 22:15     ` Philippe Mathieu-Daudé
2022-11-17 13:38   ` Cédric Le Goater
2022-11-17 13:50     ` Peter Maydell
2022-11-17 14:04     ` Alex Bennée
2022-11-17 17:14       ` Cédric Le Goater
2022-11-11 14:55 ` [PATCH v2 03/12] tests/avocado/machine_aspeed.py: Reduce noise on the console for SDK tests Alex Bennée
2022-11-11 14:55 ` [PATCH v2 04/12] tests/docker: allow user to override check target Alex Bennée
2022-11-11 17:12   ` Philippe Mathieu-Daudé
2022-11-11 14:55 ` [PATCH v2 05/12] docs/devel: add a maintainers section to development process Alex Bennée
2022-11-11 14:55 ` [PATCH v2 06/12] docs/devel: make language a little less code centric Alex Bennée
2022-11-11 14:55 ` [PATCH v2 07/12] docs/devel: simplify the minimal checklist Alex Bennée
2022-11-11 14:55 ` [PATCH v2 08/12] docs/devel: try and improve the language around patch review Alex Bennée
2022-11-11 14:55 ` Alex Bennée [this message]
2022-11-11 14:55 ` [PATCH v2 10/12] tests/avocado: Raise timeout for boot_linux.py:BootLinuxPPC64.test_pseries_tcg Alex Bennée
2022-11-11 14:55 ` [PATCH v2 11/12] gitlab: integrate coverage report Alex Bennée
2022-11-11 19:35   ` Philippe Mathieu-Daudé
2022-11-11 14:55 ` [PATCH v2 12/12] hw/intc: add implementation of GICD_IIDR to Arm GIC Alex Bennée
2022-11-14 13:18   ` Peter Maydell
2022-11-14 12:47 ` [PATCH for 7.2-rc1 v2 00/12] testing, docs, plugins, arm pre-PR Alex Bennée

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221111145529.4020801-10-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=aurelien@aurel32.net \
    --cc=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=erdnaxe@crans.org \
    --cc=f4bug@amsat.org \
    --cc=fam@euphon.net \
    --cc=idan.horowitz@gmail.com \
    --cc=ma.mandourr@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.