linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Update DSCR tests
@ 2023-03-07  0:55 Benjamin Gray
  2023-03-07  0:55 ` [PATCH 1/5] selftests/powerpc/dscr: Correct typos Benjamin Gray
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

The randomness based DSCR tests currently have a low probability of doing
any writes to the DSCR, making them inefficient in uncovering bugs.

This series adds lockstep variants to these RNG tests, to ensure the happy
path is always tested, and improves the randomness and size of the RNG
tests.

It also removes many iterations of the sysfs DSCR test, allowing the default
timeout to be re-enabled.

Benjamin Gray (5):
  selftests/powerpc/dscr: Correct typos
  selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests
  selftests/powerpc/dscr: Improve DSCR explicit random test case
  selftests/powerpc/dscr: Speed up DSCR sysfs tests
  selftests/powerpc/dscr: Restore timeout to DSCR selftests

 tools/testing/selftests/powerpc/dscr/Makefile |   3 +-
 tools/testing/selftests/powerpc/dscr/dscr.h   |  22 +-
 .../powerpc/dscr/dscr_default_test.c          | 223 +++++++++++-------
 .../powerpc/dscr/dscr_explicit_test.c         | 173 +++++++++++---
 .../powerpc/dscr/dscr_inherit_test.c          |   4 +-
 .../selftests/powerpc/dscr/dscr_sysfs_test.c  |  11 +-
 .../selftests/powerpc/dscr/dscr_user_test.c   |   4 +-
 tools/testing/selftests/powerpc/dscr/settings |   1 -
 8 files changed, 300 insertions(+), 141 deletions(-)
 delete mode 100644 tools/testing/selftests/powerpc/dscr/settings


base-commit: 422fbcbf91303706823bc3babceb1df1a42112bf
--
2.39.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] selftests/powerpc/dscr: Correct typos
  2023-03-07  0:55 [PATCH 0/5] Update DSCR tests Benjamin Gray
@ 2023-03-07  0:55 ` Benjamin Gray
  2023-03-07  0:55 ` [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests Benjamin Gray
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

Correct a couple of typos while working on other improvements to the
DSCR tests.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c | 4 ++--
 tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c  | 4 ++--
 tools/testing/selftests/powerpc/dscr/dscr_user_test.c     | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
index 32fcf2b324b1..5659d98cf340 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
@@ -7,8 +7,8 @@
  * privilege state SPR and the problem state SPR for this purpose.
  *
  * When using the privilege state SPR, the instructions such as
- * mfspr or mtspr are priviledged and the kernel emulates them
- * for us. Instructions using problem state SPR can be exuecuted
+ * mfspr or mtspr are privileged and the kernel emulates them
+ * for us. Instructions using problem state SPR can be executed
  * directly without any emulation if the HW supports them. Else
  * they also get emulated by the kernel.
  *
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
index f9dfd3d3c2d5..68ce328e813e 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
@@ -7,8 +7,8 @@
  * value using mfspr.
  *
  * When using the privilege state SPR, the instructions such as
- * mfspr or mtspr are priviledged and the kernel emulates them
- * for us. Instructions using problem state SPR can be exuecuted
+ * mfspr or mtspr are privileged and the kernel emulates them
+ * for us. Instructions using problem state SPR can be executed
  * directly without any emulation if the HW supports them. Else
  * they also get emulated by the kernel.
  *
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_user_test.c b/tools/testing/selftests/powerpc/dscr/dscr_user_test.c
index e09072446dd3..67bb872a246a 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_user_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_user_test.c
@@ -8,8 +8,8 @@
  * numbers.
  *
  * When using the privilege state SPR, the instructions such as
- * mfspr or mtspr are priviledged and the kernel emulates them
- * for us. Instructions using problem state SPR can be exuecuted
+ * mfspr or mtspr are privileged and the kernel emulates them
+ * for us. Instructions using problem state SPR can be executed
  * directly without any emulation if the HW supports them. Else
  * they also get emulated by the kernel.
  *
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests
  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
  2023-03-07  9:59   ` Michael Ellerman
  2023-03-07  0:55 ` [PATCH 3/5] selftests/powerpc/dscr: Improve DSCR explicit random test case Benjamin Gray
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

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


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] selftests/powerpc/dscr: Improve DSCR explicit random test case
  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 ` [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests Benjamin Gray
@ 2023-03-07  0:55 ` 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
  4 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

The tests currently have a single writer thread updating the system
DSCR with a 1/1000 chance looped only 100 times. So only around one in
10 runs actually do anything.

* Add multiple threads to the dscr_explicit_random_test case.
* Use a barrier to make all the threads start work as simultaneously as
  possible.
* Use a rwlock and make all threads have a reasonable chance to write to
  the DSCR on each iteration.
  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is used to prevent
  writers from starving while all the other threads keep reading.
  Logging the reads/writes shows a decent mix across the whole test.
* Allow all threads a chance to write.
* Make the chance of writing more likely.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 tools/testing/selftests/powerpc/dscr/dscr.h   |   5 -
 .../powerpc/dscr/dscr_default_test.c          | 132 ++++++++----------
 .../powerpc/dscr/dscr_explicit_test.c         |  94 ++++++++-----
 3 files changed, 114 insertions(+), 117 deletions(-)

diff --git a/tools/testing/selftests/powerpc/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h
index 903ee0c83fac..9cd5488ab7c2 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr.h
+++ b/tools/testing/selftests/powerpc/dscr/dscr.h
@@ -88,11 +88,6 @@ void set_default_dscr(unsigned long val)
 	}
 }
 
-double uniform_deviate(int seed)
-{
-	return seed * (1.0 / (RAND_MAX + 1.0));
-}
-
 int restrict_to_one_cpu(void)
 {
 	cpu_set_t cpus;
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
index 8b7d0ff8a20a..758823d59daa 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
@@ -69,105 +69,85 @@ int dscr_default_lockstep_test(void)
 	return 0;
 }
 
-static unsigned long dscr;		/* System DSCR default */
-static unsigned long sequence;
-static unsigned long result[THREADS];
+struct random_thread_args {
+	pthread_t thread_id;
+	unsigned long *expected_system_dscr;
+	pthread_rwlock_t *rw_lock;
+	pthread_barrier_t *barrier;
+};
 
-static void *do_test(void *in)
+static void *dscr_default_random_thread(void *in)
 {
-	unsigned long thread = (unsigned long)in;
-	unsigned long i;
+	struct random_thread_args *args = (struct random_thread_args *)in;
+	unsigned long *expected_dscr_p = args->expected_system_dscr;
+	pthread_rwlock_t *rw_lock = args->rw_lock;
+	int err;
 
-	for (i = 0; i < COUNT; i++) {
-		unsigned long d, cur_dscr, cur_dscr_usr;
-		unsigned long s1, s2;
+	srand(gettid());
 
-		s1 = READ_ONCE(sequence);
-		if (s1 & 1)
-			continue;
-		rmb();
+	err = pthread_barrier_wait(args->barrier);
+	FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
 
-		d = dscr;
-		cur_dscr = get_dscr();
-		cur_dscr_usr = get_dscr_usr();
+	for (int i = 0; i < COUNT; i++) {
+		unsigned long expected_dscr;
+		unsigned long current_dscr;
+		unsigned long current_dscr_usr;
 
-		rmb();
-		s2 = sequence;
+		FAIL_IF_EXIT(pthread_rwlock_rdlock(rw_lock));
+		expected_dscr = *expected_dscr_p;
+		current_dscr = get_dscr();
+		current_dscr_usr = get_dscr_usr();
+		FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
 
-		if (s1 != s2)
-			continue;
+		FAIL_IF_EXIT(current_dscr != expected_dscr);
+		FAIL_IF_EXIT(current_dscr_usr != expected_dscr);
 
-		if (cur_dscr != d) {
-			fprintf(stderr, "thread %ld kernel DSCR should be %ld "
-				"but is %ld\n", thread, d, cur_dscr);
-			result[thread] = 1;
-			pthread_exit(&result[thread]);
-		}
+		if (rand() % 10 == 0) {
+			unsigned long next_dscr;
 
-		if (cur_dscr_usr != d) {
-			fprintf(stderr, "thread %ld user DSCR should be %ld "
-				"but is %ld\n", thread, d, cur_dscr_usr);
-			result[thread] = 1;
-			pthread_exit(&result[thread]);
+			FAIL_IF_EXIT(pthread_rwlock_wrlock(rw_lock));
+			next_dscr = (*expected_dscr_p + 1) % DSCR_MAX;
+			set_default_dscr(next_dscr);
+			*expected_dscr_p = next_dscr;
+			FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
 		}
 	}
-	result[thread] = 0;
-	pthread_exit(&result[thread]);
+
+	pthread_exit((void *)0);
 }
 
 int dscr_default_random_test(void)
 {
-	pthread_t threads[THREADS];
-	unsigned long i, *status[THREADS];
+	struct random_thread_args threads[THREADS];
+	unsigned long expected_system_dscr = 0;
+	pthread_rwlockattr_t rwlock_attr;
+	pthread_rwlock_t rw_lock;
+	pthread_barrier_t barrier;
 
 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
 
-	/* Initial DSCR default */
-	dscr = 1;
-	set_default_dscr(dscr);
+	FAIL_IF(pthread_rwlockattr_setkind_np(&rwlock_attr,
+					      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP));
+	FAIL_IF(pthread_rwlock_init(&rw_lock, &rwlock_attr));
+	FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
 
-	/* Spawn all testing threads */
-	for (i = 0; i < THREADS; i++) {
-		if (pthread_create(&threads[i], NULL, do_test, (void *)i)) {
-			perror("pthread_create() failed");
-			return 1;
-		}
+	set_default_dscr(expected_system_dscr);
+
+	for (int i = 0; i < THREADS; i++) {
+		threads[i].expected_system_dscr = &expected_system_dscr;
+		threads[i].rw_lock = &rw_lock;
+		threads[i].barrier = &barrier;
+
+		FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
+				       dscr_default_random_thread, (void *)&threads[i]));
 	}
 
-	srand(getpid());
+	for (int i = 0; i < THREADS; i++)
+		FAIL_IF(pthread_join(threads[i].thread_id, NULL));
 
-	/* Keep changing the DSCR default */
-	for (i = 0; i < COUNT; i++) {
-		double ret = uniform_deviate(rand());
+	FAIL_IF(pthread_barrier_destroy(&barrier));
+	FAIL_IF(pthread_rwlock_destroy(&rw_lock));
 
-		if (ret < 0.0001) {
-			sequence++;
-			wmb();
-
-			dscr++;
-			if (dscr > DSCR_MAX)
-				dscr = 0;
-
-			set_default_dscr(dscr);
-
-			wmb();
-			sequence++;
-		}
-	}
-
-	/* Individual testing thread exit status */
-	for (i = 0; i < THREADS; i++) {
-		if (pthread_join(threads[i], (void **)&(status[i]))) {
-			perror("pthread_join() failed");
-			return 1;
-		}
-
-		if (*status[i]) {
-			printf("%ldth thread failed to join with %ld status\n",
-								i, *status[i]);
-			return 1;
-		}
-	}
 	return 0;
 }
 
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
index 28b1ea23e469..9930533730ae 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
@@ -86,50 +86,72 @@ int dscr_explicit_lockstep_test(void)
 	return 0;
 }
 
+struct random_thread_args {
+	pthread_t thread_id;
+	bool do_yields;
+	pthread_barrier_t *barrier;
+};
+
+void *dscr_explicit_random_thread(void *in)
+{
+	struct random_thread_args *args = (struct random_thread_args *)in;
+	unsigned long expected_dscr = 0;
+	int err;
+
+	srand(gettid());
+
+	err = pthread_barrier_wait(args->barrier);
+	FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
+
+	for (int i = 0; i < COUNT; i++) {
+		expected_dscr = rand() % DSCR_MAX;
+		set_dscr(expected_dscr);
+
+		for (int j = rand() % 5; j > 0; --j) {
+			FAIL_IF_EXIT(get_dscr() != expected_dscr);
+			FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
+
+			if (args->do_yields && rand() % 2)
+				sched_yield();
+		}
+
+		expected_dscr = rand() % DSCR_MAX;
+		set_dscr_usr(expected_dscr);
+
+		for (int j = rand() % 5; j > 0; --j) {
+			FAIL_IF_EXIT(get_dscr() != expected_dscr);
+			FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
+
+			if (args->do_yields && rand() % 2)
+				sched_yield();
+		}
+	}
+
+	return NULL;
+}
+
 int dscr_explicit_random_test(void)
 {
-	unsigned long i, dscr = 0;
+	struct random_thread_args threads[THREADS];
+	pthread_barrier_t barrier;
 
 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
 
-	srand(getpid());
-	set_dscr(dscr);
+	FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
 
-	for (i = 0; i < COUNT; i++) {
-		unsigned long cur_dscr, cur_dscr_usr;
-		double ret = uniform_deviate(rand());
+	for (int i = 0; i < THREADS; i++) {
+		threads[i].do_yields = i % 2 == 0;
+		threads[i].barrier = &barrier;
 
-		if (ret < 0.001) {
-			dscr++;
-			if (dscr > DSCR_MAX)
-				dscr = 0;
-
-			set_dscr(dscr);
-		}
-
-		cur_dscr = get_dscr();
-		if (cur_dscr != dscr) {
-			fprintf(stderr, "Kernel DSCR should be %ld but "
-					"is %ld\n", dscr, cur_dscr);
-			return 1;
-		}
-
-		ret = uniform_deviate(rand());
-		if (ret < 0.001) {
-			dscr++;
-			if (dscr > DSCR_MAX)
-				dscr = 0;
-
-			set_dscr_usr(dscr);
-		}
-
-		cur_dscr_usr = get_dscr_usr();
-		if (cur_dscr_usr != dscr) {
-			fprintf(stderr, "User DSCR should be %ld but "
-					"is %ld\n", dscr, cur_dscr_usr);
-			return 1;
-		}
+		FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
+				       dscr_explicit_random_thread, (void *)&threads[i]));
 	}
+
+	for (int i = 0; i < THREADS; i++)
+		FAIL_IF(pthread_join(threads[i].thread_id, NULL));
+
+	FAIL_IF(pthread_barrier_destroy(&barrier));
+
 	return 0;
 }
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] selftests/powerpc/dscr: Speed up DSCR sysfs tests
  2023-03-07  0:55 [PATCH 0/5] Update DSCR tests Benjamin Gray
                   ` (2 preceding siblings ...)
  2023-03-07  0:55 ` [PATCH 3/5] selftests/powerpc/dscr: Improve DSCR explicit random test case Benjamin Gray
@ 2023-03-07  0:55 ` Benjamin Gray
  2023-03-07  0:55 ` [PATCH 5/5] selftests/powerpc/dscr: Restore timeout to DSCR selftests Benjamin Gray
  4 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

This test case is extremely slow, taking around a minute compared to
most of the other DSCR tests taking a second at most. Perf shows most
time is spent by the kernel switching to each CPU it reads in
/sys/devices/system/cpu. This switching is an unavoidable consequnce
of reading all the .../cpuN/dscr values.

Remove the outer iteration loop from this test case, reducing the reads
from 1600 to 16. This still updates the DSCR 16 times and verifies on
every CPU each time, so I do not expect the lower coverage to be
meaningful. The speedup is significant: back down to ~1 second like the
other tests.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 .../testing/selftests/powerpc/dscr/dscr_sysfs_test.c  | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
index 4f1fef6198fc..e7cd0d6b1fad 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
@@ -67,17 +67,14 @@ static int check_all_cpu_dscr_defaults(unsigned long val)
 int dscr_sysfs(void)
 {
 	unsigned long orig_dscr_default;
-	int i, j;
 
 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
 
 	orig_dscr_default = get_default_dscr();
-	for (i = 0; i < COUNT; i++) {
-		for (j = 0; j < DSCR_MAX; j++) {
-			set_default_dscr(j);
-			if (check_all_cpu_dscr_defaults(j))
-				goto fail;
-		}
+	for (int i = 0; i < DSCR_MAX; i++) {
+		set_default_dscr(i);
+		if (check_all_cpu_dscr_defaults(i))
+			goto fail;
 	}
 	set_default_dscr(orig_dscr_default);
 	return 0;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] selftests/powerpc/dscr: Restore timeout to DSCR selftests
  2023-03-07  0:55 [PATCH 0/5] Update DSCR tests Benjamin Gray
                   ` (3 preceding siblings ...)
  2023-03-07  0:55 ` [PATCH 4/5] selftests/powerpc/dscr: Speed up DSCR sysfs tests Benjamin Gray
@ 2023-03-07  0:55 ` Benjamin Gray
  4 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-03-07  0:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Gray

Reducing the time taken by dscr_sysfs_test.c allows restoring the
default timeout, which was removed in
commit 850507f30c38 ("selftests/powerpc: Turn off timeout setting for
benchmarks, dscr, signal, tm") because that test took too long.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 tools/testing/selftests/powerpc/dscr/Makefile | 2 --
 tools/testing/selftests/powerpc/dscr/settings | 1 -
 2 files changed, 3 deletions(-)
 delete mode 100644 tools/testing/selftests/powerpc/dscr/settings

diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile
index b29a8863a734..9289d5febe1e 100644
--- a/tools/testing/selftests/powerpc/dscr/Makefile
+++ b/tools/testing/selftests/powerpc/dscr/Makefile
@@ -3,8 +3,6 @@ TEST_GEN_PROGS := dscr_default_test dscr_explicit_test dscr_user_test	\
 	      dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test	\
 	      dscr_sysfs_thread_test
 
-TEST_FILES := settings
-
 top_srcdir = ../../../../..
 include ../../lib.mk
 
diff --git a/tools/testing/selftests/powerpc/dscr/settings b/tools/testing/selftests/powerpc/dscr/settings
deleted file mode 100644
index e7b9417537fb..000000000000
--- a/tools/testing/selftests/powerpc/dscr/settings
+++ /dev/null
@@ -1 +0,0 @@
-timeout=0
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests
  2023-03-07  0:55 ` [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests Benjamin Gray
@ 2023-03-07  9:59   ` Michael Ellerman
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2023-03-07  9:59 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev; +Cc: Benjamin Gray

Benjamin Gray <bgray@linux.ibm.com> writes:
> 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/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
> @@ -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;
> +}

We have pick_online_cpu() in utils.c, can you use that?

You probably also need to move bind_to_cpu() from pmu/lib.c to utils.c
so you can use it.

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-03-07 10:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 2/5] selftests/powerpc/dscr: Add lockstep test cases to DSCR explicit tests Benjamin Gray
2023-03-07  9:59   ` 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

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