1/* 2 * POWER Data Stream Control Register (DSCR) default test 3 * 4 * This test modifies the system wide default DSCR through 5 * it's sysfs interface and then verifies that all threads 6 * see the correct changed DSCR value immediately. 7 * 8 * Copyright 2012, Anton Blanchard, IBM Corporation. 9 * Copyright 2015, Anshuman Khandual, IBM Corporation. 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 as published 13 * by the Free Software Foundation. 14 */ 15#include "dscr.h" 16 17static unsigned long dscr; /* System DSCR default */ 18static unsigned long sequence; 19static unsigned long result[THREADS]; 20 21static void *do_test(void *in) 22{ 23 unsigned long thread = (unsigned long)in; 24 unsigned long i; 25 26 for (i = 0; i < COUNT; i++) { 27 unsigned long d, cur_dscr, cur_dscr_usr; 28 unsigned long s1, s2; 29 30 s1 = ACCESS_ONCE(sequence); 31 if (s1 & 1) 32 continue; 33 rmb(); 34 35 d = dscr; 36 cur_dscr = get_dscr(); 37 cur_dscr_usr = get_dscr_usr(); 38 39 rmb(); 40 s2 = sequence; 41 42 if (s1 != s2) 43 continue; 44 45 if (cur_dscr != d) { 46 fprintf(stderr, "thread %ld kernel DSCR should be %ld " 47 "but is %ld\n", thread, d, cur_dscr); 48 result[thread] = 1; 49 pthread_exit(&result[thread]); 50 } 51 52 if (cur_dscr_usr != d) { 53 fprintf(stderr, "thread %ld user DSCR should be %ld " 54 "but is %ld\n", thread, d, cur_dscr_usr); 55 result[thread] = 1; 56 pthread_exit(&result[thread]); 57 } 58 } 59 result[thread] = 0; 60 pthread_exit(&result[thread]); 61} 62 63int dscr_default(void) 64{ 65 pthread_t threads[THREADS]; 66 unsigned long i, *status[THREADS]; 67 unsigned long orig_dscr_default; 68 69 orig_dscr_default = get_default_dscr(); 70 71 /* Initial DSCR default */ 72 dscr = 1; 73 set_default_dscr(dscr); 74 75 /* Spawn all testing threads */ 76 for (i = 0; i < THREADS; i++) { 77 if (pthread_create(&threads[i], NULL, do_test, (void *)i)) { 78 perror("pthread_create() failed"); 79 goto fail; 80 } 81 } 82 83 srand(getpid()); 84 85 /* Keep changing the DSCR default */ 86 for (i = 0; i < COUNT; i++) { 87 double ret = uniform_deviate(rand()); 88 89 if (ret < 0.0001) { 90 sequence++; 91 wmb(); 92 93 dscr++; 94 if (dscr > DSCR_MAX) 95 dscr = 0; 96 97 set_default_dscr(dscr); 98 99 wmb(); 100 sequence++; 101 } 102 } 103 104 /* Individual testing thread exit status */ 105 for (i = 0; i < THREADS; i++) { 106 if (pthread_join(threads[i], (void **)&(status[i]))) { 107 perror("pthread_join() failed"); 108 goto fail; 109 } 110 111 if (*status[i]) { 112 printf("%ldth thread failed to join with %ld status\n", 113 i, *status[i]); 114 goto fail; 115 } 116 } 117 set_default_dscr(orig_dscr_default); 118 return 0; 119fail: 120 set_default_dscr(orig_dscr_default); 121 return 1; 122} 123 124int main(int argc, char *argv[]) 125{ 126 return test_harness(dscr_default, "dscr_default_test"); 127} 128