"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-fifo.c" (15 Mar 2019, 5553 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-fifo.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_SYS_SELECT_H)
   28 static const uint64_t wrap_mask = 0xffff000000000000ULL;
   29 #endif
   30 
   31 int stress_set_fifo_readers(const char *opt)
   32 {
   33     uint64_t fifo_readers;
   34 
   35     fifo_readers = get_uint64(opt);
   36     check_range("fifo-readers", fifo_readers,
   37         MIN_FIFO_READERS, MAX_FIFO_READERS);
   38     return set_setting("fifo-readers", TYPE_ID_UINT64, &fifo_readers);
   39 }
   40 
   41 #if defined(HAVE_SYS_SELECT_H)
   42 /*
   43  *  fifo_spawn()
   44  *  spawn a process
   45  */
   46 static pid_t fifo_spawn(
   47     const args_t *args,
   48     void (*func)(const args_t *args, const char *name, const char *fifoname),
   49     const char *name,
   50     const char *fifoname)
   51 {
   52     pid_t pid;
   53 
   54     pid = fork();
   55     if (pid < 0) {
   56         return -1;
   57     }
   58     if (pid == 0) {
   59         (void)setpgid(0, g_pgrp);
   60         stress_parent_died_alarm();
   61         func(args, name, fifoname);
   62         _exit(EXIT_SUCCESS);
   63     }
   64     (void)setpgid(pid, g_pgrp);
   65     return pid;
   66 }
   67 
   68 /*
   69  *  stress_fifo_readers()
   70  *  read fifo
   71  */
   72 static void stress_fifo_reader(
   73     const args_t *args,
   74     const char *name,
   75     const char *fifoname)
   76 {
   77     int fd;
   78     uint64_t val, lastval = 0;
   79 
   80     fd = open(fifoname, O_RDONLY | O_NONBLOCK);
   81     if (fd < 0) {
   82         pr_err("%s: fifo read open failed: errno=%d (%s)\n",
   83             name, errno, strerror(errno));
   84         return;
   85     }
   86     while (g_keep_stressing_flag) {
   87         ssize_t sz;
   88         int ret;
   89         struct timeval timeout;
   90         fd_set rdfds;
   91 
   92         FD_ZERO(&rdfds);
   93         FD_SET(fd, &rdfds);
   94 redo:
   95         timeout.tv_sec = 1;
   96         timeout.tv_usec = 0;
   97 
   98         ret = select(fd + 1, &rdfds, NULL, NULL, &timeout);
   99         if (ret < 0) {
  100             if ((errno == EAGAIN) || (errno == EINTR))
  101                 continue;
  102             pr_err("%s: select failed: errno=%d (%s)\n",
  103                 name, errno, strerror(errno));
  104             break;
  105         } else if (ret == 0) {
  106             /*
  107              * nothing to read, timed-out, retry
  108              * as this can happen on a highly
  109              * overloaded stressed system
  110              */
  111             if (keep_stressing())
  112                 goto redo;
  113             break;
  114         }
  115         sz = read(fd, &val, sizeof(val));
  116         if (sz < 0) {
  117             if ((errno == EAGAIN) || (errno == EINTR))
  118                 continue;
  119             pr_err("%s: fifo read failed: errno=%d (%s)\n",
  120                 name, errno, strerror(errno));
  121             break;
  122         }
  123         if (sz == 0)
  124             break;
  125         if (sz != sizeof(val)) {
  126             pr_err("%s: fifo read did not get uint64\n",
  127                 name);
  128             break;
  129         }
  130         if ((val < lastval) &&
  131             ((~val & wrap_mask) && (lastval & wrap_mask))) {
  132             pr_err("%s: fifo read did not get "
  133                 "expected value\n", name);
  134             break;
  135         }
  136         lastval = val;
  137     }
  138     (void)close(fd);
  139 }
  140 
  141 
  142 /*
  143  *  stress_fifo
  144  *  stress by heavy fifo I/O
  145  */
  146 static int stress_fifo(const args_t *args)
  147 {
  148     pid_t pids[MAX_FIFO_READERS];
  149     int fd;
  150     char fifoname[PATH_MAX];
  151     uint64_t i, val = 0ULL;
  152     uint64_t fifo_readers = DEFAULT_FIFO_READERS;
  153     int rc = EXIT_FAILURE;
  154 
  155     if (!get_setting("fifo-readers", &fifo_readers)) {
  156         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  157             fifo_readers = MAX_FIFO_READERS;
  158         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  159             fifo_readers = MIN_FIFO_READERS;
  160     }
  161 
  162     rc = stress_temp_dir_mk_args(args);
  163     if (rc < 0)
  164         return exit_status(-rc);
  165 
  166     (void)stress_temp_filename_args(args,
  167         fifoname, sizeof(fifoname), mwc32());
  168 
  169     if (mkfifo(fifoname, S_IRUSR | S_IWUSR) < 0) {
  170         rc = exit_status(errno);
  171         pr_err("%s: mkfifo failed: errno=%d (%s)\n",
  172             args->name, errno, strerror(errno));
  173         goto tidy;
  174     }
  175 
  176     (void)memset(pids, 0, sizeof(pids));
  177     for (i = 0; i < fifo_readers; i++) {
  178         pids[i] = fifo_spawn(args, stress_fifo_reader, args->name, fifoname);
  179         if (pids[i] < 0)
  180             goto reap;
  181         if (!g_keep_stressing_flag) {
  182             rc = EXIT_SUCCESS;
  183             goto reap;
  184         }
  185     }
  186 
  187     fd = open(fifoname, O_WRONLY);
  188     if (fd < 0) {
  189         if (errno == EINTR) {
  190             rc = 0;
  191         } else {
  192             rc = exit_status(fd);
  193             pr_err("%s: fifo write open failed: "
  194                 "errno=%d (%s)\n",
  195                 args->name, errno, strerror(errno));
  196         }
  197         goto reap;
  198     }
  199 
  200     do {
  201         ssize_t ret;
  202 
  203         ret = write(fd, &val, sizeof(val));
  204         if (ret <= 0) {
  205             if ((errno == EAGAIN) || (errno == EINTR))
  206                 continue;
  207             if (errno) {
  208                 pr_fail_dbg("write");
  209                 break;
  210             }
  211             continue;
  212         }
  213         val++;
  214         val &= ~wrap_mask;
  215         inc_counter(args);
  216     } while (keep_stressing());
  217 
  218     (void)close(fd);
  219     rc = EXIT_SUCCESS;
  220 reap:
  221     for (i = 0; i < fifo_readers; i++) {
  222         if (pids[i] > 0) {
  223             int status;
  224 
  225             (void)kill(pids[i], SIGKILL);
  226             (void)waitpid(pids[i], &status, 0);
  227         }
  228     }
  229 tidy:
  230     (void)unlink(fifoname);
  231     (void)stress_temp_dir_rm_args(args);
  232 
  233     return rc;
  234 }
  235 
  236 stressor_info_t stress_fifo_info = {
  237     .stressor = stress_fifo,
  238     .class = CLASS_PIPE_IO | CLASS_OS | CLASS_SCHEDULER
  239 };
  240 #else
  241 stressor_info_t stress_fifo_info = {
  242     .stressor = stress_not_implemented,
  243     .class = CLASS_PIPE_IO | CLASS_OS | CLASS_SCHEDULER
  244 };
  245 #endif