~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/powerpc/math/fpu_signal.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright 2015, Cyril Bur, IBM Corp.
  4  *
  5  * This test attempts to see if the FPU registers are correctly reported in a
  6  * signal context. Each worker just spins checking its FPU registers, at some
  7  * point a signal will interrupt it and C code will check the signal context
  8  * ensuring it is also the same.
  9  */
 10 
 11 #include <stdio.h>
 12 #include <unistd.h>
 13 #include <sys/syscall.h>
 14 #include <sys/time.h>
 15 #include <sys/types.h>
 16 #include <sys/wait.h>
 17 #include <stdlib.h>
 18 #include <pthread.h>
 19 
 20 #include "utils.h"
 21 #include "fpu.h"
 22 
 23 /* Number of times each thread should receive the signal */
 24 #define ITERATIONS 10
 25 /*
 26  * Factor by which to multiply number of online CPUs for total number of
 27  * worker threads
 28  */
 29 #define THREAD_FACTOR 8
 30 
 31 __thread double darray[32];
 32 
 33 bool bad_context;
 34 int threads_starting;
 35 int running;
 36 
 37 extern long preempt_fpu(double *darray, int *threads_starting, int *running);
 38 
 39 void signal_fpu_sig(int sig, siginfo_t *info, void *context)
 40 {
 41         int i;
 42         ucontext_t *uc = context;
 43         mcontext_t *mc = &uc->uc_mcontext;
 44 
 45         // Don't check f30/f31, they're used as scratches in check_all_fprs()
 46         for (i = 0; i < 30; i++) {
 47                 if (mc->fp_regs[i] != darray[i]) {
 48                         bad_context = true;
 49                         break;
 50                 }
 51         }
 52 }
 53 
 54 void *signal_fpu_c(void *p)
 55 {
 56         long rc;
 57         struct sigaction act;
 58         act.sa_sigaction = signal_fpu_sig;
 59         act.sa_flags = SA_SIGINFO;
 60         rc = sigaction(SIGUSR1, &act, NULL);
 61         if (rc)
 62                 return p;
 63 
 64         srand(pthread_self());
 65         randomise_darray(darray, ARRAY_SIZE(darray));
 66         rc = preempt_fpu(darray, &threads_starting, &running);
 67 
 68         return (void *) rc;
 69 }
 70 
 71 int test_signal_fpu(void)
 72 {
 73         int i, j, rc, threads;
 74         void *rc_p;
 75         pthread_t *tids;
 76 
 77         threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
 78         tids = malloc(threads * sizeof(pthread_t));
 79         FAIL_IF(!tids);
 80 
 81         running = true;
 82         threads_starting = threads;
 83         for (i = 0; i < threads; i++) {
 84                 rc = pthread_create(&tids[i], NULL, signal_fpu_c, NULL);
 85                 FAIL_IF(rc);
 86         }
 87 
 88         setbuf(stdout, NULL);
 89         printf("\tWaiting for all workers to start...");
 90         while (threads_starting)
 91                 asm volatile("": : :"memory");
 92         printf("done\n");
 93 
 94         printf("\tSending signals to all threads %d times...", ITERATIONS);
 95         for (i = 0; i < ITERATIONS; i++) {
 96                 for (j = 0; j < threads; j++) {
 97                         pthread_kill(tids[j], SIGUSR1);
 98                 }
 99                 sleep(1);
100         }
101         printf("done\n");
102 
103         printf("\tStopping workers...");
104         running = 0;
105         for (i = 0; i < threads; i++) {
106                 pthread_join(tids[i], &rc_p);
107 
108                 /*
109                  * Harness will say the fail was here, look at why signal_fpu
110                  * returned
111                  */
112                 if ((long) rc_p || bad_context)
113                         printf("oops\n");
114                 if (bad_context)
115                         fprintf(stderr, "\t!! bad_context is true\n");
116                 FAIL_IF((long) rc_p || bad_context);
117         }
118         printf("done\n");
119 
120         free(tids);
121         return 0;
122 }
123 
124 int main(int argc, char *argv[])
125 {
126         return test_harness(test_signal_fpu, "fpu_signal");
127 }
128 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php