"Fossies" - the Fresh Open Source Software Archive

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

    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_SETTIME)
   31 static volatile uint64_t *timer_counter;
   32 static uint64_t max_ops;
   33 static timer_t timerid;
   34 static double start;
   35 
   36 #define PROCS_MAX   (32)
   37 
   38 /*
   39  *  stress_hrtimers_set()
   40  *  set timer, ensure it is never zero
   41  */
   42 static void stress_hrtimers_set(struct itimerspec *timer)
   43 {
   44     timer->it_value.tv_sec = 0;
   45     timer->it_value.tv_nsec = (mwc64() % 50000) + 1;
   46     timer->it_interval.tv_sec = timer->it_value.tv_sec;
   47     timer->it_interval.tv_nsec = timer->it_value.tv_nsec;
   48 }
   49 
   50 /*
   51  *  stress_hrtimers_keep_stressing()
   52  *      returns true if we can keep on running a stressor
   53  */
   54 static bool HOT OPTIMIZE3 stress_hrtimers_keep_stressing(void)
   55 {
   56         return (LIKELY(g_keep_stressing_flag) &&
   57                 LIKELY(!max_ops || ((*timer_counter) < max_ops)));
   58 }
   59 
   60 /*
   61  *  stress_hrtimers_handler()
   62  *  catch timer signal and cancel if no more runs flagged
   63  */
   64 static void MLOCKED_TEXT stress_hrtimers_handler(int sig)
   65 {
   66     struct itimerspec timer;
   67     sigset_t mask;
   68 
   69     (void)sig;
   70 
   71     if (!stress_hrtimers_keep_stressing())
   72         goto cancel;
   73     (*timer_counter)++;
   74 
   75     if (sigpending(&mask) == 0)
   76         if (sigismember(&mask, SIGINT))
   77             goto cancel;
   78     /* High freq timer, check periodically for timeout */
   79     if (((*timer_counter) & 65535) == 0)
   80         if ((time_now() - start) > (double)g_opt_timeout)
   81             goto cancel;
   82     stress_hrtimers_set(&timer);
   83     return;
   84 
   85 cancel:
   86     g_keep_stressing_flag = false;
   87     /* Cancel timer if we detect no more runs */
   88     (void)memset(&timer, 0, sizeof(timer));
   89     (void)timer_settime(timerid, 0, &timer, NULL);
   90 }
   91 
   92 /*
   93  *  stress_hrtimer_process
   94  *  stress timer child process
   95  */
   96 static int stress_hrtimer_process(const args_t *args, uint64_t *counter)
   97 {
   98     struct sigevent sev;
   99     struct itimerspec timer;
  100     sigset_t mask;
  101     int ret;
  102 
  103     timer_counter = counter;
  104 
  105     (void)sigemptyset(&mask);
  106     (void)sigaddset(&mask, SIGINT);
  107     (void)sigprocmask(SIG_SETMASK, &mask, NULL);
  108 
  109     ret = stress_set_sched(getpid(), SCHED_RR, UNDEFINED, true);
  110     (void)ret;
  111 
  112     start = time_now();
  113     if (stress_sighandler(args->name, SIGRTMIN, stress_hrtimers_handler, NULL) < 0)
  114         return EXIT_FAILURE;
  115 
  116     sev.sigev_notify = SIGEV_SIGNAL;
  117     sev.sigev_signo = SIGRTMIN;
  118     sev.sigev_value.sival_ptr = &timerid;
  119     if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) {
  120         pr_fail_err("timer_create");
  121         return EXIT_FAILURE;
  122     }
  123 
  124     stress_hrtimers_set(&timer);
  125     if (timer_settime(timerid, 0, &timer, NULL) < 0) {
  126         pr_fail_err("timer_settime");
  127         return EXIT_FAILURE;
  128     }
  129 
  130     do {
  131         /* The sleep will be interrupted on each hrtimer tick */
  132         (void)sleep(1);
  133     } while (stress_hrtimers_keep_stressing());
  134 
  135     if (timer_delete(timerid) < 0) {
  136         pr_fail_err("timer_delete");
  137         return EXIT_FAILURE;
  138     }
  139     return EXIT_SUCCESS;
  140 }
  141 
  142 static int stress_hrtimers(const args_t *args)
  143 {
  144     pid_t pids[PROCS_MAX];
  145     const size_t page_size = args->page_size;
  146     const size_t counters_sz = sizeof(uint64_t) * PROCS_MAX;
  147         const size_t sz = (counters_sz + page_size) & ~(page_size - 1);
  148     size_t i;
  149     uint64_t *counters;
  150 
  151     max_ops = args->max_ops / PROCS_MAX;
  152 
  153     (void)memset(pids, 0, sizeof(pids));
  154         counters = (uint64_t *)mmap(NULL, sz, PROT_READ | PROT_WRITE,
  155                         MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  156         if (counters == MAP_FAILED) {
  157                 pr_fail_dbg("mmap");
  158                 return EXIT_NO_RESOURCE;
  159         }
  160 
  161     for (i = 0; i < PROCS_MAX && keep_stressing(); i++) {
  162         pids[i] = fork();
  163         if (pids[0] < 0)
  164             goto reap;
  165         else if (pids[i] == 0) {
  166             /* Child */
  167 
  168             (void)setpgid(0, g_pgrp);
  169             stress_parent_died_alarm();
  170             set_oom_adjustment(args->name, true);
  171             stress_hrtimer_process(args, &counters[i]);
  172             _exit(EXIT_SUCCESS);
  173         }
  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 
  183         set_counter(args, 0);
  184         for (i = 0; i < PROCS_MAX; i++)
  185             add_counter(args, counters[i]);
  186     } while (keep_stressing());
  187 
  188 
  189 reap:
  190     for (i = 0; i < PROCS_MAX; i++) {
  191         if (pids[i] > 0) {
  192             int status, ret;
  193 
  194             (void)kill(pids[i], SIGALRM);
  195             ret = waitpid(pids[i], &status, 0);
  196             (void)ret;
  197         }
  198     }
  199 
  200 
  201     (void)munmap((void *)counters, sz);
  202 
  203     return EXIT_SUCCESS;
  204 }
  205 
  206 stressor_info_t stress_hrtimers_info = {
  207     .stressor = stress_hrtimers,
  208     .class = CLASS_SCHEDULER
  209 };
  210 #else
  211 stressor_info_t stress_hrtimers_info = {
  212     .stressor = stress_not_implemented,
  213     .class = CLASS_SCHEDULER
  214 };
  215 #endif