"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-wait.c" (15 Mar 2019, 5100 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-wait.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 /*
   28  *  Disabled for GNU/Hurd because it this stressor breaks with
   29  *  the error:
   30  *    intr-msg.c:387: _hurd_intr_rpc_mach_msg: Assertion
   31  *    `m->header.msgh_id == msgid + 100'
   32  */
   33 #if !defined(__gnu_hurd__)
   34 
   35 #define ABORT_TIMEOUT   (1.0)
   36 
   37 static void MLOCKED_TEXT stress_usr1_handler(int signum)
   38 {
   39     (void)signum;
   40 }
   41 
   42 /*
   43  *  spawn()
   44  *  spawn a process
   45  */
   46 static pid_t spawn(
   47     const args_t *args,
   48     void (*func)(const args_t *args, const pid_t pid),
   49     pid_t pid_arg)
   50 {
   51     pid_t pid;
   52 
   53 again:
   54     pid = fork();
   55     if (pid < 0) {
   56         if (g_keep_stressing_flag && (errno == EAGAIN))
   57             goto again;
   58         return -1;
   59     }
   60     if (pid == 0) {
   61         stress_parent_died_alarm();
   62 
   63         func(args, pid_arg);
   64         _exit(EXIT_SUCCESS);
   65     }
   66     (void)setpgid(pid, g_pgrp);
   67     return pid;
   68 }
   69 
   70 /*
   71  *  runner()
   72  *  this process pauses, but is continually being
   73  *  stopped and continued by the killer process
   74  */
   75 static void runner(
   76     const args_t *args,
   77     const pid_t pid)
   78 {
   79     (void)pid;
   80 
   81     pr_dbg("%s: wait: runner started [%d]\n", args->name, (int)getpid());
   82 
   83     do {
   84         (void)pause();
   85     } while (keep_stressing());
   86 
   87     (void)kill(getppid(), SIGALRM);
   88     _exit(EXIT_SUCCESS);
   89 }
   90 
   91 /*
   92  *  killer()
   93  *  this continually stops and continues the runner process
   94  */
   95 static void killer(
   96     const args_t *args,
   97     const pid_t pid)
   98 {
   99     double start = time_now();
  100     uint64_t last_counter = get_counter(args);
  101     pid_t ppid = getppid();
  102 
  103     pr_dbg("%s: wait: killer started [%d]\n", args->name, (int)getpid());
  104 
  105     do {
  106         (void)kill(pid, SIGSTOP);
  107         (void)shim_sched_yield();
  108         (void)kill(pid, SIGCONT);
  109 
  110         /*
  111          *  The waits may be blocked and
  112          *  so the counter is not being updated.
  113          *  If it is blocked for too long bail out
  114          *  so we don't get stuck in the parent
  115          *  waiter indefinitely.
  116          */
  117         if (last_counter == get_counter(args)) {
  118             const double now = time_now();
  119             if (now - start > ABORT_TIMEOUT) {
  120                 /* unblock waiting parent */
  121                 (void)kill(ppid, SIGUSR1);
  122                 start = now;
  123             }
  124         } else {
  125             start = time_now();
  126             last_counter = get_counter(args);
  127         }
  128     } while (keep_stressing());
  129 
  130     /* forcefully kill runner, wait is in parent */
  131     (void)kill(pid, SIGKILL);
  132 
  133     /* tell parent to wake up! */
  134     (void)kill(getppid(), SIGALRM);
  135     _exit(EXIT_SUCCESS);
  136 }
  137 
  138 /*
  139  *  stress_wait
  140  *  stress wait*() family of calls
  141  */
  142 static int stress_wait(const args_t *args)
  143 {
  144     int status, ret = EXIT_SUCCESS;
  145     pid_t pid_r, pid_k, wret;
  146     int options = 0;
  147 
  148 #if defined(WUNTRACED)
  149     options |= WUNTRACED;
  150 #endif
  151 #if defined(WCONTINUED)
  152     options |= WCONTINUED;
  153 #endif
  154 
  155     pr_dbg("%s: waiter started [%d]\n",
  156         args->name, (int)args->pid);
  157 
  158     if (stress_sighandler(args->name, SIGUSR1, stress_usr1_handler, NULL) < 0)
  159         return EXIT_FAILURE;
  160 
  161     pid_r = spawn(args, runner, 0);
  162     if (pid_r < 0) {
  163         pr_fail_dbg("fork");
  164         return EXIT_FAILURE;
  165     }
  166 
  167     pid_k = spawn(args, killer, pid_r);
  168     if (pid_k < 0) {
  169         pr_fail_dbg("fork");
  170         ret = EXIT_FAILURE;
  171         goto tidy;
  172     }
  173 
  174     do {
  175         wret = waitpid(pid_r, &status, options);
  176         if ((wret < 0) && (errno != EINTR) && (errno != ECHILD)) {
  177             pr_fail_dbg("waitpid()");
  178             break;
  179         }
  180         if (!g_keep_stressing_flag)
  181             break;
  182 #if defined(WIFCONINUED)
  183         if (WIFCONTINUED(status))
  184             inc_counter(args);
  185 #else
  186         inc_counter(args);
  187 #endif
  188 
  189 #if defined(HAVE_WAITID)
  190         if (options) {
  191             siginfo_t info;
  192 
  193             wret = waitid(P_PID, pid_r, &info, options);
  194             if ((wret < 0) && (errno != EINTR) && (errno != ECHILD)) {
  195                 pr_fail_dbg("waitpid()");
  196                 break;
  197             }
  198             if (!g_keep_stressing_flag)
  199                 break;
  200 #if defined(WIFCONTINUED)
  201             if (WIFCONTINUED(status))
  202                 inc_counter(args);
  203 #else
  204             inc_counter(args);
  205 #endif
  206         }
  207 #endif
  208     } while (g_keep_stressing_flag && (!args->max_ops || get_counter(args) < args->max_ops));
  209 
  210     (void)kill(pid_k, SIGKILL);
  211     (void)waitpid(pid_k, &status, 0);
  212 tidy:
  213     (void)kill(pid_r, SIGKILL);
  214     (void)waitpid(pid_r, &status, 0);
  215 
  216     return ret;
  217 }
  218 
  219 stressor_info_t stress_wait_info = {
  220     .stressor = stress_wait,
  221     .class = CLASS_SCHEDULER | CLASS_OS
  222 };
  223 #else
  224 stressor_info_t stress_wait_info = {
  225     .stressor = stress_not_implemented,
  226     .class = CLASS_SCHEDULER | CLASS_OS
  227 };
  228 #endif