qemu-devel.nongnu.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).