All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: linux-kernel@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>,
	"Paul E . McKenney" <paulmck@kernel.org>,
	Boqun Feng <boqun.feng@gmail.com>,
	"H . Peter Anvin" <hpa@zytor.com>, Paul Turner <pjt@google.com>,
	linux-api@vger.kernel.org,
	Christian Brauner <christian.brauner@ubuntu.com>,
	Florian Weimer <fw@deneb.enyo.de>,
	David.Laight@ACULAB.COM, carlos@redhat.com,
	Peter Oskolkov <posk@posk.io>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Subject: [PATCH v3 23/23] selftests/rseq: Implement numa node id vs vm_vcpu_id invariant test
Date: Fri, 29 Jul 2022 15:02:25 -0400	[thread overview]
Message-ID: <20220729190225.12726-24-mathieu.desnoyers@efficios.com> (raw)
In-Reply-To: <20220729190225.12726-1-mathieu.desnoyers@efficios.com>

On all architectures except Power, the NUMA topology is never
reconfigured after a CPU has been associated with a NUMA node in the
system lifetime.

Even on Power, we can assume that NUMA topology reconfiguration happens
rarely, and therefore we do not expect it to happen while the NUMA test
is running.

This test validates that the mapping between a vm_vcpu_id and a numa
node id remains valid for the process lifetime. In other words, it
validates that if any thread within the process running on behalf of a
vm_vcpu_id N observes a NUMA node id M, all threads within this process
will always observe the same NUMA node id value when running on behalf
of that same vm_vcpu_id.

This characteristic is important for NUMA locality.

This test is skipped on architectures that do not implement
rseq_load_u32_u32.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
---
 tools/testing/selftests/rseq/.gitignore       |   1 +
 tools/testing/selftests/rseq/Makefile         |   2 +-
 .../testing/selftests/rseq/basic_numa_test.c  | 117 ++++++++++++++++++
 3 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/rseq/basic_numa_test.c

diff --git a/tools/testing/selftests/rseq/.gitignore b/tools/testing/selftests/rseq/.gitignore
index db5c1a124c6c..9231abed69cc 100644
--- a/tools/testing/selftests/rseq/.gitignore
+++ b/tools/testing/selftests/rseq/.gitignore
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+basic_numa_test
 basic_percpu_ops_test
 basic_percpu_ops_vm_vcpu_id_test
 basic_test
diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile
index 3eec8e166385..4bf5b7202254 100644
--- a/tools/testing/selftests/rseq/Makefile
+++ b/tools/testing/selftests/rseq/Makefile
@@ -12,7 +12,7 @@ LDLIBS += -lpthread -ldl
 # still track changes to header files and depend on shared object.
 OVERRIDE_TARGETS = 1
 
-TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_vm_vcpu_id_test param_test \
+TEST_GEN_PROGS = basic_test basic_numa_test basic_percpu_ops_test basic_percpu_ops_vm_vcpu_id_test param_test \
 		param_test_benchmark param_test_compare_twice param_test_vm_vcpu_id \
 		param_test_vm_vcpu_id_benchmark param_test_vm_vcpu_id_compare_twice
 
diff --git a/tools/testing/selftests/rseq/basic_numa_test.c b/tools/testing/selftests/rseq/basic_numa_test.c
new file mode 100644
index 000000000000..45cb714b135c
--- /dev/null
+++ b/tools/testing/selftests/rseq/basic_numa_test.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Basic rseq NUMA test. Validate that (vm_vcpu_id, numa_node_id) pairs are
+ * invariant. The only known scenario where this is untrue is on Power which
+ * can reconfigure the NUMA topology on CPU hotunplug/hotplug sequence.
+ */
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "rseq.h"
+
+#define NR_LOOPS	100000000
+#define NR_THREADS	16
+
+#ifdef RSEQ_ARCH_HAS_LOAD_U32_U32
+
+static
+int cpu_numa_id[CPU_SETSIZE];
+
+static
+void numa_id_init(void)
+{
+	int i;
+
+	for (i = 0; i < CPU_SETSIZE; i++)
+		cpu_numa_id[i] = -1;
+}
+
+static
+void *test_thread(void *arg)
+{
+	int i;
+
+	if (rseq_register_current_thread()) {
+		fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n",
+			errno, strerror(errno));
+		abort();
+	}
+
+	for (i = 0; i < NR_LOOPS; i++) {
+		uint32_t vm_vcpu_id, node;
+		int cached_node_id;
+
+		while (rseq_load_u32_u32(RSEQ_MO_RELAXED, &vm_vcpu_id, &rseq_get_abi()->vm_vcpu_id,
+					 &node, &rseq_get_abi()->node_id) != 0) {
+			/* Retry. */
+		}
+		cached_node_id = RSEQ_READ_ONCE(cpu_numa_id[vm_vcpu_id]);
+		if (cached_node_id == -1) {
+			RSEQ_WRITE_ONCE(cpu_numa_id[vm_vcpu_id], node);
+		} else {
+			if (node != cached_node_id) {
+				fprintf(stderr, "Error: NUMA node id discrepancy: vm_vcpu_id %u cached node id %d node id %u.\n",
+					vm_vcpu_id, cached_node_id, node);
+				fprintf(stderr, "This is likely a kernel bug, or caused by a concurrent NUMA topology reconfiguration.\n");
+				abort();
+			}
+		}
+	}
+
+	if (rseq_unregister_current_thread()) {
+		fprintf(stderr, "Error: rseq_unregister_current_thread(...) failed(%d): %s\n",
+			errno, strerror(errno));
+		abort();
+	}
+	return NULL;
+}
+
+static
+int test_numa(void)
+{
+        pthread_t tid[NR_THREADS];
+        int err, i;
+        void *tret;
+
+	numa_id_init();
+
+	printf("testing rseq (vm_vcpu_id, numa_node_id) invariant, single thread\n");
+
+	(void) test_thread(NULL);
+
+	printf("testing rseq (vm_vcpu_id, numa_node_id) invariant, multi-threaded\n");
+
+        for (i = 0; i < NR_THREADS; i++) {
+                err = pthread_create(&tid[i], NULL, test_thread, NULL);
+                if (err != 0)
+                        abort();
+        }
+
+        for (i = 0; i < NR_THREADS; i++) {
+                err = pthread_join(tid[i], &tret);
+                if (err != 0)
+                        abort();
+        }
+
+	return 0;
+}
+#else
+static
+int test_numa(void)
+{
+	fprintf(stderr, "rseq_load_u32_u32 is not implemented on this architecture. "
+			"Skipping numa test.\n");
+	return 0;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+	return test_numa();
+}
-- 
2.17.1


  parent reply	other threads:[~2022-07-29 19:04 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-29 19:02 [PATCH v3 00/23] RSEQ node id and virtual cpu id extensions Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 01/23] rseq: Introduce feature size and alignment ELF auxiliary vector entries Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 02/23] rseq: Introduce extensible rseq ABI Mathieu Desnoyers
2022-08-10  6:33   ` Florian Weimer
2022-08-10 13:27     ` Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 03/23] rseq: extend struct rseq with numa node id Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 04/23] selftests/rseq: Use ELF auxiliary vector for extensible rseq Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 05/23] selftests/rseq: Implement rseq numa node id field selftest Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 06/23] lib: invert _find_next_bit source arguments Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 07/23] lib: implement find_{first,next}_{zero,one}_and_zero_bit Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 08/23] cpumask: implement cpumask_{first,next}_{zero,one}_and_zero Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 09/23] sched: Introduce per memory space current virtual cpu id Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 10/23] rseq: extend struct rseq with per memory space vcpu id Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 11/23] selftests/rseq: Remove RSEQ_SKIP_FASTPATH code Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 12/23] selftests/rseq: Implement rseq vm_vcpu_id field support Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 13/23] selftests/rseq: x86: Template memory ordering and percpu access mode Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 14/23] selftests/rseq: arm: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 15/23] selftests/rseq: arm64: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 16/23] selftests/rseq: mips: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 17/23] selftests/rseq: ppc: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 18/23] selftests/rseq: s390: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 19/23] selftests/rseq: riscv: " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 20/23] selftests/rseq: basic percpu ops vm_vcpu_id test Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 21/23] selftests/rseq: parametrized " Mathieu Desnoyers
2022-07-29 19:02 ` [PATCH v3 22/23] selftests/rseq: x86: Implement rseq_load_u32_u32 Mathieu Desnoyers
2022-07-29 19:02 ` Mathieu Desnoyers [this message]
2022-08-01 17:07 ` [PATCH v3 00/23] RSEQ node id and virtual cpu id extensions Peter Oskolkov
2022-08-02 15:01   ` Mathieu Desnoyers
2022-08-02 17:06     ` Peter Oskolkov
2022-08-02 20:53       ` Mathieu Desnoyers
2022-08-04 16:18         ` Chris Kennelly

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=20220729190225.12726-24-mathieu.desnoyers@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=David.Laight@ACULAB.COM \
    --cc=boqun.feng@gmail.com \
    --cc=carlos@redhat.com \
    --cc=christian.brauner@ubuntu.com \
    --cc=fw@deneb.enyo.de \
    --cc=hpa@zytor.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=pjt@google.com \
    --cc=posk@posk.io \
    --cc=tglx@linutronix.de \
    /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.