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
next prev 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).