170 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * POWER Data Stream Control Register (DSCR) default test4 *5 * This test modifies the system wide default DSCR through6 * it's sysfs interface and then verifies that all threads7 * 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_SOURCE14 15#include "dscr.h"16 17#include <pthread.h>18#include <semaphore.h>19#include <unistd.h>20 21static 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 39int 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 72struct 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 79static 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 119int 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 154int 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