xref: /openbmc/linux/tools/testing/selftests/powerpc/dscr/dscr_default_test.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24c6315f8SAnshuman Khandual /*
34c6315f8SAnshuman Khandual  * POWER Data Stream Control Register (DSCR) default test
44c6315f8SAnshuman Khandual  *
54c6315f8SAnshuman Khandual  * This test modifies the system wide default DSCR through
64c6315f8SAnshuman Khandual  * it's sysfs interface and then verifies that all threads
74c6315f8SAnshuman Khandual  * see the correct changed DSCR value immediately.
84c6315f8SAnshuman Khandual  *
94c6315f8SAnshuman Khandual  * Copyright 2012, Anton Blanchard, IBM Corporation.
104c6315f8SAnshuman Khandual  * Copyright 2015, Anshuman Khandual, IBM Corporation.
114c6315f8SAnshuman Khandual  */
12fda81588SBenjamin Gray 
13fda81588SBenjamin Gray #define _GNU_SOURCE
14fda81588SBenjamin Gray 
154c6315f8SAnshuman Khandual #include "dscr.h"
164c6315f8SAnshuman Khandual 
17fda81588SBenjamin Gray #include <pthread.h>
18fda81588SBenjamin Gray #include <semaphore.h>
19fda81588SBenjamin Gray #include <unistd.h>
20fda81588SBenjamin Gray 
dscr_default_lockstep_writer(void * arg)21fda81588SBenjamin Gray static void *dscr_default_lockstep_writer(void *arg)
22fda81588SBenjamin Gray {
23fda81588SBenjamin Gray 	sem_t *reader_sem = (sem_t *)arg;
24fda81588SBenjamin Gray 	sem_t *writer_sem = (sem_t *)arg + 1;
25fda81588SBenjamin Gray 	unsigned long expected_dscr = 0;
26fda81588SBenjamin Gray 
27fda81588SBenjamin Gray 	for (int i = 0; i < COUNT; i++) {
28fda81588SBenjamin Gray 		FAIL_IF_EXIT(sem_wait(writer_sem));
29fda81588SBenjamin Gray 
30fda81588SBenjamin Gray 		set_default_dscr(expected_dscr);
31fda81588SBenjamin Gray 		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
32fda81588SBenjamin Gray 
33fda81588SBenjamin Gray 		FAIL_IF_EXIT(sem_post(reader_sem));
34fda81588SBenjamin Gray 	}
35fda81588SBenjamin Gray 
36fda81588SBenjamin Gray 	return NULL;
37fda81588SBenjamin Gray }
38fda81588SBenjamin Gray 
dscr_default_lockstep_test(void)39fda81588SBenjamin Gray int dscr_default_lockstep_test(void)
40fda81588SBenjamin Gray {
41fda81588SBenjamin Gray 	pthread_t writer;
42fda81588SBenjamin Gray 	sem_t rw_semaphores[2];
43fda81588SBenjamin Gray 	sem_t *reader_sem = &rw_semaphores[0];
44fda81588SBenjamin Gray 	sem_t *writer_sem = &rw_semaphores[1];
45fda81588SBenjamin Gray 	unsigned long expected_dscr = 0;
46fda81588SBenjamin Gray 
47fda81588SBenjamin Gray 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
48fda81588SBenjamin Gray 
49fda81588SBenjamin Gray 	FAIL_IF(sem_init(reader_sem, 0, 0));
50fda81588SBenjamin Gray 	FAIL_IF(sem_init(writer_sem, 0, 1));  /* writer starts first */
51fda81588SBenjamin Gray 	FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
52fda81588SBenjamin Gray 	FAIL_IF(pthread_create(&writer, NULL, dscr_default_lockstep_writer, (void *)rw_semaphores));
53fda81588SBenjamin Gray 
54fda81588SBenjamin Gray 	for (int i = 0; i < COUNT ; i++) {
55fda81588SBenjamin Gray 		FAIL_IF(sem_wait(reader_sem));
56fda81588SBenjamin Gray 
57fda81588SBenjamin Gray 		FAIL_IF(get_dscr() != expected_dscr);
58fda81588SBenjamin Gray 		FAIL_IF(get_dscr_usr() != expected_dscr);
59fda81588SBenjamin Gray 
60fda81588SBenjamin Gray 		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
61fda81588SBenjamin Gray 
62fda81588SBenjamin Gray 		FAIL_IF(sem_post(writer_sem));
63fda81588SBenjamin Gray 	}
64fda81588SBenjamin Gray 
65fda81588SBenjamin Gray 	FAIL_IF(pthread_join(writer, NULL));
66fda81588SBenjamin Gray 	FAIL_IF(sem_destroy(reader_sem));
67fda81588SBenjamin Gray 	FAIL_IF(sem_destroy(writer_sem));
68fda81588SBenjamin Gray 
69fda81588SBenjamin Gray 	return 0;
70fda81588SBenjamin Gray }
71fda81588SBenjamin Gray 
72*3067b89aSBenjamin Gray struct random_thread_args {
73*3067b89aSBenjamin Gray 	pthread_t thread_id;
74*3067b89aSBenjamin Gray 	unsigned long *expected_system_dscr;
75*3067b89aSBenjamin Gray 	pthread_rwlock_t *rw_lock;
76*3067b89aSBenjamin Gray 	pthread_barrier_t *barrier;
77*3067b89aSBenjamin Gray };
784c6315f8SAnshuman Khandual 
dscr_default_random_thread(void * in)79*3067b89aSBenjamin Gray static void *dscr_default_random_thread(void *in)
804c6315f8SAnshuman Khandual {
81*3067b89aSBenjamin Gray 	struct random_thread_args *args = (struct random_thread_args *)in;
82*3067b89aSBenjamin Gray 	unsigned long *expected_dscr_p = args->expected_system_dscr;
83*3067b89aSBenjamin Gray 	pthread_rwlock_t *rw_lock = args->rw_lock;
84*3067b89aSBenjamin Gray 	int err;
854c6315f8SAnshuman Khandual 
86*3067b89aSBenjamin Gray 	srand(gettid());
874c6315f8SAnshuman Khandual 
88*3067b89aSBenjamin Gray 	err = pthread_barrier_wait(args->barrier);
89*3067b89aSBenjamin Gray 	FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
904c6315f8SAnshuman Khandual 
91*3067b89aSBenjamin Gray 	for (int i = 0; i < COUNT; i++) {
92*3067b89aSBenjamin Gray 		unsigned long expected_dscr;
93*3067b89aSBenjamin Gray 		unsigned long current_dscr;
94*3067b89aSBenjamin Gray 		unsigned long current_dscr_usr;
954c6315f8SAnshuman Khandual 
96*3067b89aSBenjamin Gray 		FAIL_IF_EXIT(pthread_rwlock_rdlock(rw_lock));
97*3067b89aSBenjamin Gray 		expected_dscr = *expected_dscr_p;
98*3067b89aSBenjamin Gray 		current_dscr = get_dscr();
99*3067b89aSBenjamin Gray 		current_dscr_usr = get_dscr_usr();
100*3067b89aSBenjamin Gray 		FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
1014c6315f8SAnshuman Khandual 
102*3067b89aSBenjamin Gray 		FAIL_IF_EXIT(current_dscr != expected_dscr);
103*3067b89aSBenjamin Gray 		FAIL_IF_EXIT(current_dscr_usr != expected_dscr);
1044c6315f8SAnshuman Khandual 
105*3067b89aSBenjamin Gray 		if (rand() % 10 == 0) {
106*3067b89aSBenjamin Gray 			unsigned long next_dscr;
1074c6315f8SAnshuman Khandual 
108*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(pthread_rwlock_wrlock(rw_lock));
109*3067b89aSBenjamin Gray 			next_dscr = (*expected_dscr_p + 1) % DSCR_MAX;
110*3067b89aSBenjamin Gray 			set_default_dscr(next_dscr);
111*3067b89aSBenjamin Gray 			*expected_dscr_p = next_dscr;
112*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
1134c6315f8SAnshuman Khandual 		}
1144c6315f8SAnshuman Khandual 	}
115*3067b89aSBenjamin Gray 
116*3067b89aSBenjamin Gray 	pthread_exit((void *)0);
1174c6315f8SAnshuman Khandual }
1184c6315f8SAnshuman Khandual 
dscr_default_random_test(void)119fda81588SBenjamin Gray int dscr_default_random_test(void)
1204c6315f8SAnshuman Khandual {
121*3067b89aSBenjamin Gray 	struct random_thread_args threads[THREADS];
122*3067b89aSBenjamin Gray 	unsigned long expected_system_dscr = 0;
123*3067b89aSBenjamin Gray 	pthread_rwlockattr_t rwlock_attr;
124*3067b89aSBenjamin Gray 	pthread_rwlock_t rw_lock;
125*3067b89aSBenjamin Gray 	pthread_barrier_t barrier;
1264c6315f8SAnshuman Khandual 
1274c3c3c50SMichael Ellerman 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
1284c3c3c50SMichael Ellerman 
129*3067b89aSBenjamin Gray 	FAIL_IF(pthread_rwlockattr_setkind_np(&rwlock_attr,
130*3067b89aSBenjamin Gray 					      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP));
131*3067b89aSBenjamin Gray 	FAIL_IF(pthread_rwlock_init(&rw_lock, &rwlock_attr));
132*3067b89aSBenjamin Gray 	FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
1334c6315f8SAnshuman Khandual 
134*3067b89aSBenjamin Gray 	set_default_dscr(expected_system_dscr);
135*3067b89aSBenjamin Gray 
136*3067b89aSBenjamin Gray 	for (int i = 0; i < THREADS; i++) {
137*3067b89aSBenjamin Gray 		threads[i].expected_system_dscr = &expected_system_dscr;
138*3067b89aSBenjamin Gray 		threads[i].rw_lock = &rw_lock;
139*3067b89aSBenjamin Gray 		threads[i].barrier = &barrier;
140*3067b89aSBenjamin Gray 
141*3067b89aSBenjamin Gray 		FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
142*3067b89aSBenjamin Gray 				       dscr_default_random_thread, (void *)&threads[i]));
1434c6315f8SAnshuman Khandual 	}
1444c6315f8SAnshuman Khandual 
145*3067b89aSBenjamin Gray 	for (int i = 0; i < THREADS; i++)
146*3067b89aSBenjamin Gray 		FAIL_IF(pthread_join(threads[i].thread_id, NULL));
1474c6315f8SAnshuman Khandual 
148*3067b89aSBenjamin Gray 	FAIL_IF(pthread_barrier_destroy(&barrier));
149*3067b89aSBenjamin Gray 	FAIL_IF(pthread_rwlock_destroy(&rw_lock));
1504c6315f8SAnshuman Khandual 
151fda81588SBenjamin Gray 	return 0;
152fda81588SBenjamin Gray }
1534c6315f8SAnshuman Khandual 
main(int argc,char * argv[])1544c6315f8SAnshuman Khandual int main(int argc, char *argv[])
1554c6315f8SAnshuman Khandual {
156fda81588SBenjamin Gray 	unsigned long orig_dscr_default = 0;
157fda81588SBenjamin Gray 	int err = 0;
158fda81588SBenjamin Gray 
159fda81588SBenjamin Gray 	if (have_hwcap2(PPC_FEATURE2_DSCR))
160fda81588SBenjamin Gray 		orig_dscr_default = get_default_dscr();
161fda81588SBenjamin Gray 
162fda81588SBenjamin Gray 	err |= test_harness(dscr_default_lockstep_test, "dscr_default_lockstep_test");
163fda81588SBenjamin Gray 	err |= test_harness(dscr_default_random_test, "dscr_default_random_test");
164fda81588SBenjamin Gray 
165fda81588SBenjamin Gray 	if (have_hwcap2(PPC_FEATURE2_DSCR))
166fda81588SBenjamin Gray 		set_default_dscr(orig_dscr_default);
167fda81588SBenjamin Gray 
168fda81588SBenjamin Gray 	return err;
1694c6315f8SAnshuman Khandual }
170