linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Gray <bgray@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: Benjamin Gray <bgray@linux.ibm.com>
Subject: [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests
Date: Tue,  7 Mar 2023 11:55:12 +1100	[thread overview]
Message-ID: <20230307005515.174362-3-bgray@linux.ibm.com> (raw)
In-Reply-To: <20230307005515.174362-1-bgray@linux.ibm.com>

Add new cases to the relevant tests that use explicitly synchronized
threads to test the behaviour across context switches with less
randomness. By locking the participants to the same CPU we guarantee a
context switch occurs each time they make progress, which is a likely
failure point if the kernel is not tracking the thread local DSCR
correctly.

The random case is left in to keep exercising potential edge cases.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 tools/testing/selftests/powerpc/dscr/Makefile |  1 +
 tools/testing/selftests/powerpc/dscr/dscr.h   | 23 +++++
 .../powerpc/dscr/dscr_default_test.c          | 87 ++++++++++++++++---
 .../powerpc/dscr/dscr_explicit_test.c         | 87 ++++++++++++++++++-
 4 files changed, 183 insertions(+), 15 deletions(-)

diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile
index 845db6273a1b..b29a8863a734 100644
--- a/tools/testing/selftests/powerpc/dscr/Makefile
+++ b/tools/testing/selftests/powerpc/dscr/Makefile
@@ -9,5 +9,6 @@ top_srcdir = ../../../../..
 include ../../lib.mk
 
 $(OUTPUT)/dscr_default_test: LDLIBS += -lpthread
+$(OUTPUT)/dscr_explicit_test: LDLIBS += -lpthread
 
 $(TEST_GEN_PROGS): ../harness.c ../utils.c
diff --git a/tools/testing/selftests/powerpc/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h
index 2c54998d4715..903ee0c83fac 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr.h
+++ b/tools/testing/selftests/powerpc/dscr/dscr.h
@@ -11,6 +11,8 @@
 #ifndef _SELFTESTS_POWERPC_DSCR_DSCR_H
 #define _SELFTESTS_POWERPC_DSCR_DSCR_H
 
+#define _GNU_SOURCE
+
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -90,4 +92,25 @@ double uniform_deviate(int seed)
 {
 	return seed * (1.0 / (RAND_MAX + 1.0));
 }
+
+int restrict_to_one_cpu(void)
+{
+	cpu_set_t cpus;
+	int cpu;
+
+	FAIL_IF(sched_getaffinity(0, sizeof(cpu_set_t), &cpus));
+
+	for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
+		if (CPU_ISSET(cpu, &cpus))
+			break;
+
+	FAIL_IF(cpu == CPU_SETSIZE);
+
+	CPU_ZERO(&cpus);
+	CPU_SET(cpu, &cpus);
+	FAIL_IF(sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
+
+	return 0;
+}
+
 #endif	/* _SELFTESTS_POWERPC_DSCR_DSCR_H */
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
index e76611e608af..8b7d0ff8a20a 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
@@ -9,8 +9,66 @@
  * Copyright 2012, Anton Blanchard, IBM Corporation.
  * Copyright 2015, Anshuman Khandual, IBM Corporation.
  */
+
+#define _GNU_SOURCE
+
 #include "dscr.h"
 
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+
+static void *dscr_default_lockstep_writer(void *arg)
+{
+	sem_t *reader_sem = (sem_t *)arg;
+	sem_t *writer_sem = (sem_t *)arg + 1;
+	unsigned long expected_dscr = 0;
+
+	for (int i = 0; i < COUNT; i++) {
+		FAIL_IF_EXIT(sem_wait(writer_sem));
+
+		set_default_dscr(expected_dscr);
+		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
+
+		FAIL_IF_EXIT(sem_post(reader_sem));
+	}
+
+	return NULL;
+}
+
+int dscr_default_lockstep_test(void)
+{
+	pthread_t writer;
+	sem_t rw_semaphores[2];
+	sem_t *reader_sem = &rw_semaphores[0];
+	sem_t *writer_sem = &rw_semaphores[1];
+	unsigned long expected_dscr = 0;
+
+	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
+
+	FAIL_IF(sem_init(reader_sem, 0, 0));
+	FAIL_IF(sem_init(writer_sem, 0, 1));  /* writer starts first */
+	FAIL_IF(restrict_to_one_cpu());
+	FAIL_IF(pthread_create(&writer, NULL, dscr_default_lockstep_writer, (void *)rw_semaphores));
+
+	for (int i = 0; i < COUNT ; i++) {
+		FAIL_IF(sem_wait(reader_sem));
+
+		FAIL_IF(get_dscr() != expected_dscr);
+		FAIL_IF(get_dscr_usr() != expected_dscr);
+
+		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
+
+		FAIL_IF(sem_post(writer_sem));
+	}
+
+	FAIL_IF(pthread_join(writer, NULL));
+	FAIL_IF(sem_destroy(reader_sem));
+	FAIL_IF(sem_destroy(writer_sem));
+
+	return 0;
+}
+
 static unsigned long dscr;		/* System DSCR default */
 static unsigned long sequence;
 static unsigned long result[THREADS];
@@ -57,16 +115,13 @@ static void *do_test(void *in)
 	pthread_exit(&result[thread]);
 }
 
-int dscr_default(void)
+int dscr_default_random_test(void)
 {
 	pthread_t threads[THREADS];
 	unsigned long i, *status[THREADS];
-	unsigned long orig_dscr_default;
 
 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
 
-	orig_dscr_default = get_default_dscr();
-
 	/* Initial DSCR default */
 	dscr = 1;
 	set_default_dscr(dscr);
@@ -75,7 +130,7 @@ int dscr_default(void)
 	for (i = 0; i < THREADS; i++) {
 		if (pthread_create(&threads[i], NULL, do_test, (void *)i)) {
 			perror("pthread_create() failed");
-			goto fail;
+			return 1;
 		}
 	}
 
@@ -104,23 +159,31 @@ int dscr_default(void)
 	for (i = 0; i < THREADS; i++) {
 		if (pthread_join(threads[i], (void **)&(status[i]))) {
 			perror("pthread_join() failed");
-			goto fail;
+			return 1;
 		}
 
 		if (*status[i]) {
 			printf("%ldth thread failed to join with %ld status\n",
 								i, *status[i]);
-			goto fail;
+			return 1;
 		}
 	}
-	set_default_dscr(orig_dscr_default);
 	return 0;
-fail:
-	set_default_dscr(orig_dscr_default);
-	return 1;
 }
 
 int main(int argc, char *argv[])
 {
-	return test_harness(dscr_default, "dscr_default_test");
+	unsigned long orig_dscr_default = 0;
+	int err = 0;
+
+	if (have_hwcap2(PPC_FEATURE2_DSCR))
+		orig_dscr_default = get_default_dscr();
+
+	err |= test_harness(dscr_default_lockstep_test, "dscr_default_lockstep_test");
+	err |= test_harness(dscr_default_random_test, "dscr_default_random_test");
+
+	if (have_hwcap2(PPC_FEATURE2_DSCR))
+		set_default_dscr(orig_dscr_default);
+
+	return err;
 }
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
index 5659d98cf340..28b1ea23e469 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
@@ -15,9 +15,78 @@
  * Copyright 2012, Anton Blanchard, IBM Corporation.
  * Copyright 2015, Anshuman Khandual, IBM Corporation.
  */
-#include "dscr.h"
 
-int dscr_explicit(void)
+#define _GNU_SOURCE
+
+#include "dscr.h"
+#include "utils.h"
+
+#include <pthread.h>
+#include <sched.h>
+#include <semaphore.h>
+
+void *dscr_explicit_lockstep_thread(void *args)
+{
+	sem_t *prev = (sem_t *)args;
+	sem_t *next = (sem_t *)args + 1;
+	unsigned long expected_dscr = 0;
+
+	set_dscr(expected_dscr);
+	srand(gettid());
+
+	for (int i = 0; i < COUNT; i++) {
+		FAIL_IF_EXIT(sem_wait(prev));
+
+		FAIL_IF_EXIT(expected_dscr != get_dscr());
+		FAIL_IF_EXIT(expected_dscr != get_dscr_usr());
+
+		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
+		set_dscr(expected_dscr);
+
+		FAIL_IF_EXIT(sem_post(next));
+	}
+
+	return NULL;
+}
+
+int dscr_explicit_lockstep_test(void)
+{
+	pthread_t thread;
+	sem_t semaphores[2];
+	sem_t *prev = &semaphores[1];  /* reversed prev/next than for the other thread */
+	sem_t *next = &semaphores[0];
+	unsigned long expected_dscr = 0;
+
+	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
+
+	srand(gettid());
+	set_dscr(expected_dscr);
+
+	FAIL_IF(sem_init(prev, 0, 0));
+	FAIL_IF(sem_init(next, 0, 1));  /* other thread starts first */
+	FAIL_IF(restrict_to_one_cpu());
+	FAIL_IF(pthread_create(&thread, NULL, dscr_explicit_lockstep_thread, (void *)semaphores));
+
+	for (int i = 0; i < COUNT; i++) {
+		FAIL_IF(sem_wait(prev));
+
+		FAIL_IF(expected_dscr != get_dscr());
+		FAIL_IF(expected_dscr != get_dscr_usr());
+
+		expected_dscr = (expected_dscr - 1) % DSCR_MAX;
+		set_dscr(expected_dscr);
+
+		FAIL_IF(sem_post(next));
+	}
+
+	FAIL_IF(pthread_join(thread, NULL));
+	FAIL_IF(sem_destroy(prev));
+	FAIL_IF(sem_destroy(next));
+
+	return 0;
+}
+
+int dscr_explicit_random_test(void)
 {
 	unsigned long i, dscr = 0;
 
@@ -66,5 +135,17 @@ int dscr_explicit(void)
 
 int main(int argc, char *argv[])
 {
-	return test_harness(dscr_explicit, "dscr_explicit_test");
+	unsigned long orig_dscr_default = 0;
+	int err = 0;
+
+	if (have_hwcap2(PPC_FEATURE2_DSCR))
+		orig_dscr_default = get_default_dscr();
+
+	err |= test_harness(dscr_explicit_lockstep_test, "dscr_explicit_lockstep_test");
+	err |= test_harness(dscr_explicit_random_test, "dscr_explicit_random_test");
+
+	if (have_hwcap2(PPC_FEATURE2_DSCR))
+		set_default_dscr(orig_dscr_default);
+
+	return err;
 }
-- 
2.39.2


  parent reply	other threads:[~2023-03-07  0:59 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-07  0:55 [PATCH 0/5] Update DSCR tests Benjamin Gray
2023-03-07  0:55 ` [PATCH 1/5] selftests/powerpc/dscr: Correct typos Benjamin Gray
2023-03-07  0:55 ` Benjamin Gray [this message]
2023-03-07  9:59   ` [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests Michael Ellerman
2023-03-07  0:55 ` [PATCH 3/5] selftests/powerpc/dscr: Improve DSCR explicit random test case Benjamin Gray
2023-03-07  0:55 ` [PATCH 4/5] selftests/powerpc/dscr: Speed up DSCR sysfs tests Benjamin Gray
2023-03-07  0:55 ` [PATCH 5/5] selftests/powerpc/dscr: Restore timeout to DSCR selftests Benjamin Gray

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=20230307005515.174362-3-bgray@linux.ibm.com \
    --to=bgray@linux.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /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).