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 orig_dscr_default = get_default_dscr(); 67 68 /* Initial DSCR default */ 69 dscr = 1; 70 set_default_dscr(dscr); 71 72 /* Spawn all testing threads */ 73 for (i = 0; i < THREADS; i++) { 74 if (pthread_create(&threads[i], NULL, do_test, (void *)i)) { 75 perror("pthread_create() failed"); 76 goto fail; 77 } 78 } 79 80 srand(getpid()); 81 82 /* Keep changing the DSCR default */ 83 for (i = 0; i < COUNT; i++) { 84 double ret = uniform_deviate(rand()); 85 86 if (ret < 0.0001) { 87 sequence++; 88 wmb(); 89 90 dscr++; 91 if (dscr > DSCR_MAX) 92 dscr = 0; 93 94 set_default_dscr(dscr); 95 96 wmb(); 97 sequence++; 98 } 99 } 100 101 /* Individual testing thread exit status */ 102 for (i = 0; i < THREADS; i++) { 103 if (pthread_join(threads[i], (void **)&(status[i]))) { 104 perror("pthread_join() failed"); 105 goto fail; 106 } 107 108 if (*status[i]) { 109 printf("%ldth thread failed to join with %ld status\n", 110 i, *status[i]); 111 goto fail; 112 } 113 } 114 set_default_dscr(orig_dscr_default); 115 return 0; 116 fail: 117 set_default_dscr(orig_dscr_default); 118 return 1; 119 } 120 121 int main(int argc, char *argv[]) 122 { 123 return test_harness(dscr_default, "dscr_default_test"); 124 } 125