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 #include "dscr.h" 13 14 static unsigned long dscr; /* System DSCR default */ 15 static unsigned long sequence; 16 static unsigned long result[THREADS]; 17 18 static void *do_test(void *in) 19 { 20 unsigned long thread = (unsigned long)in; 21 unsigned long i; 22 23 for (i = 0; i < COUNT; i++) { 24 unsigned long d, cur_dscr, cur_dscr_usr; 25 unsigned long s1, s2; 26 27 s1 = READ_ONCE(sequence); 28 if (s1 & 1) 29 continue; 30 rmb(); 31 32 d = dscr; 33 cur_dscr = get_dscr(); 34 cur_dscr_usr = get_dscr_usr(); 35 36 rmb(); 37 s2 = sequence; 38 39 if (s1 != s2) 40 continue; 41 42 if (cur_dscr != d) { 43 fprintf(stderr, "thread %ld kernel DSCR should be %ld " 44 "but is %ld\n", thread, d, cur_dscr); 45 result[thread] = 1; 46 pthread_exit(&result[thread]); 47 } 48 49 if (cur_dscr_usr != d) { 50 fprintf(stderr, "thread %ld user DSCR should be %ld " 51 "but is %ld\n", thread, d, cur_dscr_usr); 52 result[thread] = 1; 53 pthread_exit(&result[thread]); 54 } 55 } 56 result[thread] = 0; 57 pthread_exit(&result[thread]); 58 } 59 60 int dscr_default(void) 61 { 62 pthread_t threads[THREADS]; 63 unsigned long i, *status[THREADS]; 64 unsigned long orig_dscr_default; 65 66 SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR)); 67 68 orig_dscr_default = get_default_dscr(); 69 70 /* Initial DSCR default */ 71 dscr = 1; 72 set_default_dscr(dscr); 73 74 /* Spawn all testing threads */ 75 for (i = 0; i < THREADS; i++) { 76 if (pthread_create(&threads[i], NULL, do_test, (void *)i)) { 77 perror("pthread_create() failed"); 78 goto fail; 79 } 80 } 81 82 srand(getpid()); 83 84 /* Keep changing the DSCR default */ 85 for (i = 0; i < COUNT; i++) { 86 double ret = uniform_deviate(rand()); 87 88 if (ret < 0.0001) { 89 sequence++; 90 wmb(); 91 92 dscr++; 93 if (dscr > DSCR_MAX) 94 dscr = 0; 95 96 set_default_dscr(dscr); 97 98 wmb(); 99 sequence++; 100 } 101 } 102 103 /* Individual testing thread exit status */ 104 for (i = 0; i < THREADS; i++) { 105 if (pthread_join(threads[i], (void **)&(status[i]))) { 106 perror("pthread_join() failed"); 107 goto fail; 108 } 109 110 if (*status[i]) { 111 printf("%ldth thread failed to join with %ld status\n", 112 i, *status[i]); 113 goto fail; 114 } 115 } 116 set_default_dscr(orig_dscr_default); 117 return 0; 118 fail: 119 set_default_dscr(orig_dscr_default); 120 return 1; 121 } 122 123 int main(int argc, char *argv[]) 124 { 125 return test_harness(dscr_default, "dscr_default_test"); 126 } 127