Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * POWER Data Stream Control Register (DSCR) default test
0004  *
0005  * This test modifies the system wide default DSCR through
0006  * it's sysfs interface and then verifies that all threads
0007  * see the correct changed DSCR value immediately.
0008  *
0009  * Copyright 2012, Anton Blanchard, IBM Corporation.
0010  * Copyright 2015, Anshuman Khandual, IBM Corporation.
0011  */
0012 #include "dscr.h"
0013 
0014 static unsigned long dscr;      /* System DSCR default */
0015 static unsigned long sequence;
0016 static unsigned long result[THREADS];
0017 
0018 static void *do_test(void *in)
0019 {
0020     unsigned long thread = (unsigned long)in;
0021     unsigned long i;
0022 
0023     for (i = 0; i < COUNT; i++) {
0024         unsigned long d, cur_dscr, cur_dscr_usr;
0025         unsigned long s1, s2;
0026 
0027         s1 = READ_ONCE(sequence);
0028         if (s1 & 1)
0029             continue;
0030         rmb();
0031 
0032         d = dscr;
0033         cur_dscr = get_dscr();
0034         cur_dscr_usr = get_dscr_usr();
0035 
0036         rmb();
0037         s2 = sequence;
0038 
0039         if (s1 != s2)
0040             continue;
0041 
0042         if (cur_dscr != d) {
0043             fprintf(stderr, "thread %ld kernel DSCR should be %ld "
0044                 "but is %ld\n", thread, d, cur_dscr);
0045             result[thread] = 1;
0046             pthread_exit(&result[thread]);
0047         }
0048 
0049         if (cur_dscr_usr != d) {
0050             fprintf(stderr, "thread %ld user DSCR should be %ld "
0051                 "but is %ld\n", thread, d, cur_dscr_usr);
0052             result[thread] = 1;
0053             pthread_exit(&result[thread]);
0054         }
0055     }
0056     result[thread] = 0;
0057     pthread_exit(&result[thread]);
0058 }
0059 
0060 int dscr_default(void)
0061 {
0062     pthread_t threads[THREADS];
0063     unsigned long i, *status[THREADS];
0064     unsigned long orig_dscr_default;
0065 
0066     SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
0067 
0068     orig_dscr_default = get_default_dscr();
0069 
0070     /* Initial DSCR default */
0071     dscr = 1;
0072     set_default_dscr(dscr);
0073 
0074     /* Spawn all testing threads */
0075     for (i = 0; i < THREADS; i++) {
0076         if (pthread_create(&threads[i], NULL, do_test, (void *)i)) {
0077             perror("pthread_create() failed");
0078             goto fail;
0079         }
0080     }
0081 
0082     srand(getpid());
0083 
0084     /* Keep changing the DSCR default */
0085     for (i = 0; i < COUNT; i++) {
0086         double ret = uniform_deviate(rand());
0087 
0088         if (ret < 0.0001) {
0089             sequence++;
0090             wmb();
0091 
0092             dscr++;
0093             if (dscr > DSCR_MAX)
0094                 dscr = 0;
0095 
0096             set_default_dscr(dscr);
0097 
0098             wmb();
0099             sequence++;
0100         }
0101     }
0102 
0103     /* Individual testing thread exit status */
0104     for (i = 0; i < THREADS; i++) {
0105         if (pthread_join(threads[i], (void **)&(status[i]))) {
0106             perror("pthread_join() failed");
0107             goto fail;
0108         }
0109 
0110         if (*status[i]) {
0111             printf("%ldth thread failed to join with %ld status\n",
0112                                 i, *status[i]);
0113             goto fail;
0114         }
0115     }
0116     set_default_dscr(orig_dscr_default);
0117     return 0;
0118 fail:
0119     set_default_dscr(orig_dscr_default);
0120     return 1;
0121 }
0122 
0123 int main(int argc, char *argv[])
0124 {
0125     return test_harness(dscr_default, "dscr_default_test");
0126 }