"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-sigfpe.c" (15 Mar 2019, 5523 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-sigfpe.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if !defined(__UCLIBC__) && \
   28     defined(HAVE_FENV_H) &&     \
   29     defined(HAVE_FLOAT_H) 
   30 
   31 #define SNG_INTDIV  (0x40000000)
   32 #define SNG_FLTDIV  (0x80000000)
   33 
   34 static sigjmp_buf jmp_env;
   35 #if defined(SA_SIGINFO)
   36 static volatile siginfo_t siginfo;
   37 #endif
   38 
   39 /*
   40  *  stress_fpehandler()
   41  *  SIGFPE handler
   42  */
   43 #if defined(SA_SIGINFO)
   44 static void MLOCKED_TEXT stress_fpehandler(int num, siginfo_t *info, void *ucontext)
   45 {
   46     (void)num;
   47     (void)ucontext;
   48 
   49     (void)feclearexcept(FE_ALL_EXCEPT);
   50     siginfo = *info;
   51 
   52     siglongjmp(jmp_env, 1);     /* Ugly, bounce back */
   53 }
   54 #else
   55 static void MLOCKED_TEXT stress_fpehandler(int num)
   56 {
   57     (void)num;
   58     (void)feclearexcept(FE_ALL_EXCEPT);
   59 
   60     siglongjmp(jmp_env, 1);     /* Ugly, bounce back */
   61 }
   62 #endif
   63 
   64 #if defined(SA_SIGINFO)
   65 /*
   66  *  stress_sigfpe_errstr()
   67  *  convert sigfpe error code to string
   68  */
   69 static char *stress_sigfpe_errstr(const int err)
   70 {
   71     switch (err) {
   72 #if defined(FPE_INTDIV)
   73     case FPE_INTDIV:
   74         return "FPE_INTDEV";
   75 #endif
   76 #if defined(FPE_INTOVF)
   77     case FPE_INTOVF:
   78         return "FPE_INTOVF";
   79 #endif
   80 #if defined(FPE_FLTDIV)
   81     case FPE_FLTDIV:
   82         return "FPE_FLTDIV";
   83 #endif
   84 #if defined(FPE_FLTOVF)
   85     case FPE_FLTOVF:
   86         return "FPE_FLTOVF";
   87 #endif
   88 #if defined(FPE_FLTUND)
   89     case FPE_FLTUND:
   90         return "FPE_FLTUND";
   91 #endif
   92 #if defined(FPE_FLTRES)
   93     case FPE_FLTRES:
   94         return "FPE_FLTRES";
   95 #endif
   96 #if defined(FPE_FLTINV)
   97     case FPE_FLTINV:
   98         return "FPE_FLTINV";
   99 #endif
  100 #if defined(FPE_FLTSUB)
  101     case FPE_FLTSUB:
  102         return "FPE_FLTSUB";
  103 #endif
  104     default:
  105         break;
  106     }
  107     return "FPE_UNKNOWN";
  108 }
  109 #endif
  110 
  111 /*
  112  *  stress_sigfpe
  113  *  stress by generating floating point errors
  114  */
  115 static int stress_sigfpe(const args_t *args)
  116 {
  117     struct sigaction action;
  118     static int i = 0;
  119     int ret;
  120     const uint64_t zero = stress_uint64_zero();
  121 
  122     typedef struct {
  123         int exception;
  124         int err_code;
  125     } fpe_err_t;
  126 
  127     /*
  128      *  FPE errors to raise
  129      */
  130     static const fpe_err_t fpe_errs[] = {
  131 #if defined(FPE_INTDIV)
  132         { SNG_INTDIV,   FPE_INTDIV },
  133 #endif
  134 #if defined(FPE_FLTDIV)
  135         { SNG_FLTDIV,   FPE_FLTDIV },
  136 #endif
  137 #if defined(FE_DIVBYZERO) && defined(FPE_FLTDIV)
  138         { FE_DIVBYZERO, FPE_FLTDIV },
  139 #endif
  140 #if defined(FE_INEXACT) && defined(FPE_FLTRES)
  141         { FE_INEXACT,   FPE_FLTRES },
  142 #endif
  143 #if defined(FE_INVALID) && defined(FPE_FLTINV)
  144         { FE_INVALID,   FPE_FLTINV },
  145 #endif
  146 #if defined(FE_OVERFLOW) && defined(FPE_FLTOVF)
  147         { FE_OVERFLOW,  FPE_FLTOVF },
  148 #endif
  149 #if defined(FE_UNDERFLOW) && defined(FPE_FLTUND)
  150         { FE_UNDERFLOW, FPE_FLTUND },
  151 #endif
  152     };
  153 
  154     (void)memset(&action, 0, sizeof action);
  155 
  156 #if defined(SA_SIGINFO)
  157     action.sa_sigaction = stress_fpehandler;
  158 #else
  159     action.sa_handler = stress_fpehandler;
  160 #endif
  161     (void)sigemptyset(&action.sa_mask);
  162 #if defined(SA_SIGINFO)
  163     action.sa_flags = SA_SIGINFO;
  164 #endif
  165 
  166     ret = sigaction(SIGFPE, &action, NULL);
  167     if (ret < 0) {
  168         pr_fail("%s: sigaction SIGFPE: errno=%d (%s)\n",
  169             args->name, errno, strerror(errno));
  170         return EXIT_FAILURE;
  171     }
  172 
  173     for (;;) {
  174 #if defined(SA_SIGINFO)
  175         static int expected_err_code;
  176         int code;
  177 #endif
  178         int exception;
  179 
  180 #if defined(SA_SIGINFO)
  181         code = fpe_errs[i].err_code;
  182         expected_err_code = code;
  183 #endif
  184         exception = fpe_errs[i].exception;
  185 
  186         ret = sigsetjmp(jmp_env, 1);
  187         /*
  188          * We return here if we get SIGFPE, so
  189          * first check if we need to terminate
  190          */
  191         if (!keep_stressing())
  192             break;
  193 
  194         if (ret) {
  195             /*
  196              *  A SIGFPE occurred, check the error code
  197              *  matches the expected code
  198              */
  199             (void)feclearexcept(FE_ALL_EXCEPT);
  200 
  201 #if defined(SA_SIGINFO)
  202             if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  203                 (siginfo.si_code >= 0) &&
  204                 (siginfo.si_code != expected_err_code)) {
  205                 pr_fail("%s: got SIGFPE error %d (%s), expecting %d (%s)\n",
  206                     args->name,
  207                     siginfo.si_code, stress_sigfpe_errstr(siginfo.si_code),
  208                     expected_err_code, stress_sigfpe_errstr(expected_err_code));
  209             }
  210 #endif
  211             inc_counter(args);
  212         } else {
  213 #if defined(SA_SIGINFO)
  214             siginfo.si_code = 0;
  215 #endif
  216 
  217             switch(exception) {
  218             case SNG_FLTDIV:
  219                 float_put(1.0 / (float)zero);
  220                 break;
  221             case SNG_INTDIV:
  222                 uint64_put(1 / zero);
  223                 break;
  224             default:
  225                 /* Raise fault otherwise */
  226                 (void)feraiseexcept(exception);
  227                 break;
  228             }
  229         }
  230         i++;
  231         i %= SIZEOF_ARRAY(fpe_errs);
  232     }
  233     (void)feclearexcept(FE_ALL_EXCEPT);
  234 
  235     return EXIT_SUCCESS;
  236 }
  237 
  238 stressor_info_t stress_sigfpe_info = {
  239     .stressor = stress_sigfpe,
  240     .class = CLASS_INTERRUPT | CLASS_OS
  241 };
  242 #else
  243 stressor_info_t stress_sigfpe_info = {
  244     .stressor = stress_not_implemented,
  245     .class = CLASS_INTERRUPT | CLASS_OS
  246 };
  247 #endif