"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-timer.c" (15 Mar 2019, 5400 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-timer.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.50_vs_0.09.51.

    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(HAVE_LIB_RT) &&         \
   28     defined(HAVE_TIMER_CREATE) &&   \
   29     defined(HAVE_TIMER_DELETE) &&   \
   30     defined(HAVE_TIMER_GETOVERRUN) &&   \
   31     defined(HAVE_TIMER_SETTIME)
   32 static volatile uint64_t timer_counter = 0;
   33 static uint64_t max_ops;
   34 static timer_t timerid;
   35 static uint64_t overruns = 0;
   36 static double rate_ns;
   37 static double start;
   38 #endif
   39 
   40 /*
   41  *  stress_set_timer_freq()
   42  *  set timer frequency from given option
   43  */
   44 int stress_set_timer_freq(const char *opt)
   45 {
   46     uint64_t timer_freq;
   47 
   48     timer_freq = get_uint64(opt);
   49     check_range("timer-freq", timer_freq,
   50         MIN_TIMER_FREQ, MAX_TIMER_FREQ);
   51     return set_setting("timer-freq", TYPE_ID_UINT64, &timer_freq);
   52 }
   53 
   54 #if defined(HAVE_LIB_RT) &&     \
   55     defined(HAVE_TIMER_CREATE) &&   \
   56     defined(HAVE_TIMER_DELETE) &&   \
   57     defined(HAVE_TIMER_GETOVERRUN) &&   \
   58     defined(HAVE_TIMER_SETTIME)
   59 
   60 /*
   61  *  stress_timer_set()
   62  *  set timer, ensure it is never zero
   63  */
   64 static void stress_timer_set(struct itimerspec *timer)
   65 {
   66     double rate;
   67 
   68     if (g_opt_flags & OPT_FLAGS_TIMER_RAND) {
   69         /* Mix in some random variation */
   70         double r = ((double)(mwc32() % 10000) - 5000.0) / 40000.0;
   71         rate = rate_ns + (rate_ns * r);
   72     } else {
   73         rate = rate_ns;
   74     }
   75 
   76     timer->it_value.tv_sec = (time_t)rate / 1000000000;
   77     timer->it_value.tv_nsec = (suseconds_t)rate % 1000000000;
   78     if (timer->it_value.tv_sec == 0 &&
   79         timer->it_value.tv_nsec < 1)
   80         timer->it_value.tv_nsec = 1;
   81 
   82     timer->it_interval.tv_sec = timer->it_value.tv_sec;
   83     timer->it_interval.tv_nsec = timer->it_value.tv_nsec;
   84 }
   85 
   86 /*
   87  *  stress_timer_keep_stressing()
   88  *      returns true if we can keep on running a stressor
   89  */
   90 static bool HOT OPTIMIZE3 stress_timer_keep_stressing(void)
   91 {
   92         return (LIKELY(g_keep_stressing_flag) &&
   93                 LIKELY(!max_ops || (timer_counter < max_ops)));
   94 }
   95 
   96 /*
   97  *  stress_timer_handler()
   98  *  catch timer signal and cancel if no more runs flagged
   99  */
  100 static void MLOCKED_TEXT stress_timer_handler(int sig)
  101 {
  102     struct itimerspec timer;
  103     sigset_t mask;
  104 
  105     (void)sig;
  106 
  107     if (!stress_timer_keep_stressing())
  108         goto cancel;
  109     timer_counter++;
  110 
  111     if (sigpending(&mask) == 0)
  112         if (sigismember(&mask, SIGINT))
  113             goto cancel;
  114     /* High freq timer, check periodically for timeout */
  115     if ((timer_counter & 65535) == 0)
  116         if ((time_now() - start) > (double)g_opt_timeout)
  117             goto cancel;
  118     if (g_keep_stressing_flag) {
  119         int ret = timer_getoverrun(timerid);
  120         if (ret > 0)
  121             overruns += ret;
  122         stress_timer_set(&timer);
  123         return;
  124     }
  125 
  126 cancel:
  127     g_keep_stressing_flag = false;
  128     /* Cancel timer if we detect no more runs */
  129     (void)memset(&timer, 0, sizeof(timer));
  130     (void)timer_settime(timerid, 0, &timer, NULL);
  131 }
  132 
  133 /*
  134  *  stress_timer
  135  *  stress timers
  136  */
  137 static int stress_timer(const args_t *args)
  138 {
  139     struct sigevent sev;
  140     struct itimerspec timer;
  141     sigset_t mask;
  142     uint64_t timer_freq = DEFAULT_TIMER_FREQ;
  143 
  144     (void)sigemptyset(&mask);
  145     (void)sigaddset(&mask, SIGINT);
  146     (void)sigprocmask(SIG_SETMASK, &mask, NULL);
  147 
  148     max_ops = args->max_ops;
  149     start = time_now();
  150 
  151     if (!get_setting("timer-freq", &timer_freq)) {
  152         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  153             timer_freq = MAX_TIMER_FREQ;
  154         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  155             timer_freq = MIN_TIMER_FREQ;
  156     }
  157     rate_ns = timer_freq ? 1000000000.0 / timer_freq : 1000000000.0;
  158 
  159     if (stress_sighandler(args->name, SIGRTMIN, stress_timer_handler, NULL) < 0)
  160         return EXIT_FAILURE;
  161 
  162     sev.sigev_notify = SIGEV_SIGNAL;
  163     sev.sigev_signo = SIGRTMIN;
  164     sev.sigev_value.sival_ptr = &timerid;
  165     if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) {
  166         pr_fail_err("timer_create");
  167         return EXIT_FAILURE;
  168     }
  169 
  170     stress_timer_set(&timer);
  171     if (timer_settime(timerid, 0, &timer, NULL) < 0) {
  172         pr_fail_err("timer_settime");
  173         return EXIT_FAILURE;
  174     }
  175 
  176     do {
  177         struct timespec req;
  178 
  179         req.tv_sec = 0;
  180         req.tv_nsec = 10000000;
  181         (void)nanosleep(&req, NULL);
  182         set_counter(args, timer_counter);
  183     } while (keep_stressing());
  184 
  185     if (timer_delete(timerid) < 0) {
  186         pr_fail_err("timer_delete");
  187         return EXIT_FAILURE;
  188     }
  189     pr_dbg("%s: %" PRIu64 " timer overruns (instance %" PRIu32 ")\n",
  190         args->name, overruns, args->instance);
  191 
  192     return EXIT_SUCCESS;
  193 }
  194 
  195 stressor_info_t stress_timer_info = {
  196     .stressor = stress_timer,
  197     .class = CLASS_INTERRUPT | CLASS_OS
  198 };
  199 #else
  200 stressor_info_t stress_timer_info = {
  201     .stressor = stress_not_implemented,
  202     .class = CLASS_INTERRUPT | CLASS_OS
  203 };
  204 #endif