linux/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
<<
>>
Prefs
   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