Home | History | Annotate | Download | only in dscr
      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 
     17 static unsigned long dscr;		/* System DSCR default */
     18 static unsigned long sequence;
     19 static unsigned long result[THREADS];
     20 
     21 static 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 = READ_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 
     63 int 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;
    119 fail:
    120 	set_default_dscr(orig_dscr_default);
    121 	return 1;
    122 }
    123 
    124 int main(int argc, char *argv[])
    125 {
    126 	return test_harness(dscr_default, "dscr_default_test");
    127 }
    128