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