~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/powerpc/dscr/dscr_default_test.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * POWER Data Stream Control Register (DSCR) default test
  4  *
  5  * This test modifies the system wide default DSCR through
  6  * it's sysfs interface and then verifies that all threads
  7  * see the correct changed DSCR value immediately.
  8  *
  9  * Copyright 2012, Anton Blanchard, IBM Corporation.
 10  * Copyright 2015, Anshuman Khandual, IBM Corporation.
 11  */
 12 
 13 #define _GNU_SOURCE
 14 
 15 #include "dscr.h"
 16 
 17 #include <pthread.h>
 18 #include <semaphore.h>
 19 #include <unistd.h>
 20 
 21 static void *dscr_default_lockstep_writer(void *arg)
 22 {
 23         sem_t *reader_sem = (sem_t *)arg;
 24         sem_t *writer_sem = (sem_t *)arg + 1;
 25         unsigned long expected_dscr = 0;
 26 
 27         for (int i = 0; i < COUNT; i++) {
 28                 FAIL_IF_EXIT(sem_wait(writer_sem));
 29 
 30                 set_default_dscr(expected_dscr);
 31                 expected_dscr = (expected_dscr + 1) % DSCR_MAX;
 32 
 33                 FAIL_IF_EXIT(sem_post(reader_sem));
 34         }
 35 
 36         return NULL;
 37 }
 38 
 39 int dscr_default_lockstep_test(void)
 40 {
 41         pthread_t writer;
 42         sem_t rw_semaphores[2];
 43         sem_t *reader_sem = &rw_semaphores[0];
 44         sem_t *writer_sem = &rw_semaphores[1];
 45         unsigned long expected_dscr = 0;
 46 
 47         SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
 48 
 49         FAIL_IF(sem_init(reader_sem, 0, 0));
 50         FAIL_IF(sem_init(writer_sem, 0, 1));  /* writer starts first */
 51         FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
 52         FAIL_IF(pthread_create(&writer, NULL, dscr_default_lockstep_writer, (void *)rw_semaphores));
 53 
 54         for (int i = 0; i < COUNT ; i++) {
 55                 FAIL_IF(sem_wait(reader_sem));
 56 
 57                 FAIL_IF(get_dscr() != expected_dscr);
 58                 FAIL_IF(get_dscr_usr() != expected_dscr);
 59 
 60                 expected_dscr = (expected_dscr + 1) % DSCR_MAX;
 61 
 62                 FAIL_IF(sem_post(writer_sem));
 63         }
 64 
 65         FAIL_IF(pthread_join(writer, NULL));
 66         FAIL_IF(sem_destroy(reader_sem));
 67         FAIL_IF(sem_destroy(writer_sem));
 68 
 69         return 0;
 70 }
 71 
 72 struct random_thread_args {
 73         pthread_t thread_id;
 74         unsigned long *expected_system_dscr;
 75         pthread_rwlock_t *rw_lock;
 76         pthread_barrier_t *barrier;
 77 };
 78 
 79 static void *dscr_default_random_thread(void *in)
 80 {
 81         struct random_thread_args *args = (struct random_thread_args *)in;
 82         unsigned long *expected_dscr_p = args->expected_system_dscr;
 83         pthread_rwlock_t *rw_lock = args->rw_lock;
 84         int err;
 85 
 86         srand(gettid());
 87 
 88         err = pthread_barrier_wait(args->barrier);
 89         FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
 90 
 91         for (int i = 0; i < COUNT; i++) {
 92                 unsigned long expected_dscr;
 93                 unsigned long current_dscr;
 94                 unsigned long current_dscr_usr;
 95 
 96                 FAIL_IF_EXIT(pthread_rwlock_rdlock(rw_lock));
 97                 expected_dscr = *expected_dscr_p;
 98                 current_dscr = get_dscr();
 99                 current_dscr_usr = get_dscr_usr();
100                 FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
101 
102                 FAIL_IF_EXIT(current_dscr != expected_dscr);
103                 FAIL_IF_EXIT(current_dscr_usr != expected_dscr);
104 
105                 if (rand() % 10 == 0) {
106                         unsigned long next_dscr;
107 
108                         FAIL_IF_EXIT(pthread_rwlock_wrlock(rw_lock));
109                         next_dscr = (*expected_dscr_p + 1) % DSCR_MAX;
110                         set_default_dscr(next_dscr);
111                         *expected_dscr_p = next_dscr;
112                         FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
113                 }
114         }
115 
116         pthread_exit((void *)0);
117 }
118 
119 int dscr_default_random_test(void)
120 {
121         struct random_thread_args threads[THREADS];
122         unsigned long expected_system_dscr = 0;
123         pthread_rwlockattr_t rwlock_attr;
124         pthread_rwlock_t rw_lock;
125         pthread_barrier_t barrier;
126 
127         SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
128 
129         FAIL_IF(pthread_rwlockattr_setkind_np(&rwlock_attr,
130                                               PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP));
131         FAIL_IF(pthread_rwlock_init(&rw_lock, &rwlock_attr));
132         FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
133 
134         set_default_dscr(expected_system_dscr);
135 
136         for (int i = 0; i < THREADS; i++) {
137                 threads[i].expected_system_dscr = &expected_system_dscr;
138                 threads[i].rw_lock = &rw_lock;
139                 threads[i].barrier = &barrier;
140 
141                 FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
142                                        dscr_default_random_thread, (void *)&threads[i]));
143         }
144 
145         for (int i = 0; i < THREADS; i++)
146                 FAIL_IF(pthread_join(threads[i].thread_id, NULL));
147 
148         FAIL_IF(pthread_barrier_destroy(&barrier));
149         FAIL_IF(pthread_rwlock_destroy(&rw_lock));
150 
151         return 0;
152 }
153 
154 int main(int argc, char *argv[])
155 {
156         unsigned long orig_dscr_default = 0;
157         int err = 0;
158 
159         if (have_hwcap2(PPC_FEATURE2_DSCR))
160                 orig_dscr_default = get_default_dscr();
161 
162         err |= test_harness(dscr_default_lockstep_test, "dscr_default_lockstep_test");
163         err |= test_harness(dscr_default_random_test, "dscr_default_random_test");
164 
165         if (have_hwcap2(PPC_FEATURE2_DSCR))
166                 set_default_dscr(orig_dscr_default);
167 
168         return err;
169 }
170 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php