Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2015, Cyril Bur, IBM Corp.
0004  *
0005  * This test attempts to see if the VSX registers change across preemption.
0006  * There is no way to be sure preemption happened so this test just
0007  * uses many threads and a long wait. As such, a successful test
0008  * doesn't mean much but a failure is bad.
0009  */
0010 
0011 #include <stdio.h>
0012 #include <string.h>
0013 #include <unistd.h>
0014 #include <sys/syscall.h>
0015 #include <sys/time.h>
0016 #include <sys/types.h>
0017 #include <sys/wait.h>
0018 #include <stdlib.h>
0019 #include <pthread.h>
0020 
0021 #include "utils.h"
0022 
0023 /* Time to wait for workers to get preempted (seconds) */
0024 #define PREEMPT_TIME 20
0025 /*
0026  * Factor by which to multiply number of online CPUs for total number of
0027  * worker threads
0028  */
0029 #define THREAD_FACTOR 8
0030 
0031 /*
0032  * Ensure there is twice the number of non-volatile VMX regs!
0033  * check_vmx() is going to use the other half as space to put the live
0034  * registers before calling vsx_memcmp()
0035  */
0036 __thread vector int varray[24] = {
0037     {1, 2, 3, 4 }, {5, 6, 7, 8 }, {9, 10,11,12},
0038     {13,14,15,16}, {17,18,19,20}, {21,22,23,24},
0039     {25,26,27,28}, {29,30,31,32}, {33,34,35,36},
0040     {37,38,39,40}, {41,42,43,44}, {45,46,47,48}
0041 };
0042 
0043 int threads_starting;
0044 int running;
0045 
0046 extern long preempt_vsx(vector int *varray, int *threads_starting, int *running);
0047 
0048 long vsx_memcmp(vector int *a) {
0049     vector int zero = {0, 0, 0, 0};
0050     int i;
0051 
0052     FAIL_IF(a != varray);
0053 
0054     for(i = 0; i < 12; i++) {
0055         if (memcmp(&a[i + 12], &zero, sizeof(vector int)) == 0) {
0056             fprintf(stderr, "Detected zero from the VSX reg %d\n", i + 12);
0057             return 2;
0058         }
0059     }
0060 
0061     if (memcmp(a, &a[12], 12 * sizeof(vector int))) {
0062         long *p = (long *)a;
0063         fprintf(stderr, "VSX mismatch\n");
0064         for (i = 0; i < 24; i=i+2)
0065             fprintf(stderr, "%d: 0x%08lx%08lx | 0x%08lx%08lx\n",
0066                     i/2 + i%2 + 20, p[i], p[i + 1], p[i + 24], p[i + 25]);
0067         return 1;
0068     }
0069     return 0;
0070 }
0071 
0072 void *preempt_vsx_c(void *p)
0073 {
0074     int i, j;
0075     long rc;
0076     srand(pthread_self());
0077     for (i = 0; i < 12; i++)
0078         for (j = 0; j < 4; j++) {
0079             varray[i][j] = rand();
0080             /* Don't want zero because it hides kernel problems */
0081             if (varray[i][j] == 0)
0082                 j--;
0083         }
0084     rc = preempt_vsx(varray, &threads_starting, &running);
0085     if (rc == 2)
0086         fprintf(stderr, "Caught zeros in VSX compares\n");
0087     return (void *)rc;
0088 }
0089 
0090 int test_preempt_vsx(void)
0091 {
0092     int i, rc, threads;
0093     pthread_t *tids;
0094 
0095     SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_VSX));
0096 
0097     threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
0098     tids = malloc(threads * sizeof(pthread_t));
0099     FAIL_IF(!tids);
0100 
0101     running = true;
0102     threads_starting = threads;
0103     for (i = 0; i < threads; i++) {
0104         rc = pthread_create(&tids[i], NULL, preempt_vsx_c, NULL);
0105         FAIL_IF(rc);
0106     }
0107 
0108     setbuf(stdout, NULL);
0109     /* Not really nessesary but nice to wait for every thread to start */
0110     printf("\tWaiting for %d workers to start...", threads_starting);
0111     while(threads_starting)
0112         asm volatile("": : :"memory");
0113     printf("done\n");
0114 
0115     printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
0116     sleep(PREEMPT_TIME);
0117     printf("done\n");
0118 
0119     printf("\tStopping workers...");
0120     /*
0121      * Working are checking this value every loop. In preempt_vsx 'cmpwi r5,0; bne 2b'.
0122      * r5 will have loaded the value of running.
0123      */
0124     running = 0;
0125     for (i = 0; i < threads; i++) {
0126         void *rc_p;
0127         pthread_join(tids[i], &rc_p);
0128 
0129         /*
0130          * Harness will say the fail was here, look at why preempt_vsx
0131          * returned
0132          */
0133         if ((long) rc_p)
0134             printf("oops\n");
0135         FAIL_IF((long) rc_p);
0136     }
0137     printf("done\n");
0138 
0139     return 0;
0140 }
0141 
0142 int main(int argc, char *argv[])
0143 {
0144     return test_harness(test_preempt_vsx, "vsx_preempt");
0145 }