"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-poll.c" (15 Mar 2019, 6232 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-poll.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_POLL_H)
   28 
   29 #define MAX_PIPES   (5)
   30 #define POLL_BUF    (4)
   31 
   32 /*
   33  *  pipe_read()
   34  *  read a pipe with some verification and checking
   35  */
   36 static int pipe_read(const args_t *args, const int fd, const int n)
   37 {
   38     char buf[POLL_BUF];
   39     ssize_t ret;
   40 
   41 redo:
   42     if (!g_keep_stressing_flag)
   43         return -1;
   44     ret = read(fd, buf, sizeof(buf));
   45     if (g_opt_flags & OPT_FLAGS_VERIFY) {
   46         if (ret < 0) {
   47             if ((errno == EAGAIN) || (errno == EINTR))
   48                 goto redo;
   49             pr_fail("%s: pipe read error detected\n", args->name);
   50             return ret;
   51         }
   52         if (ret > 0) {
   53             ssize_t i;
   54 
   55             for (i = 0; i < ret; i++) {
   56                 if (buf[i] != '0' + n) {
   57                     pr_fail("%s: pipe read error, "
   58                         "expecting different data on "
   59                         "pipe\n", args->name);
   60                     return ret;
   61                 }
   62             }
   63         }
   64     }
   65     return ret;
   66 }
   67 
   68 /*
   69  *  stress_poll()
   70  *  stress system by rapid polling system calls
   71  */
   72 static int stress_poll(const args_t *args)
   73 {
   74     int pipefds[MAX_PIPES][2];
   75     int i;
   76     pid_t pid;
   77     int rc = EXIT_SUCCESS;
   78 
   79     for (i = 0; i < MAX_PIPES; i++) {
   80         if (pipe(pipefds[i]) < 0) {
   81             pr_fail_dbg("pipe");
   82             while (--i >= 0) {
   83                 (void)close(pipefds[i][0]);
   84                 (void)close(pipefds[i][1]);
   85             }
   86             return EXIT_FAILURE;
   87         }
   88     }
   89 
   90 again:
   91     pid = fork();
   92     if (pid < 0) {
   93         if (g_keep_stressing_flag && (errno == EAGAIN))
   94             goto again;
   95         pr_fail_dbg("fork");
   96         rc = EXIT_FAILURE;
   97         goto tidy;
   98     }
   99     else if (pid == 0) {
  100         /* Child writer */
  101 
  102         (void)setpgid(0, g_pgrp);
  103         stress_parent_died_alarm();
  104 
  105         for (i = 0; i < MAX_PIPES; i++)
  106             (void)close(pipefds[i][0]);
  107 
  108         do {
  109             char buf[POLL_BUF];
  110             ssize_t ret;
  111 
  112             /* Write on a randomly chosen pipe */
  113             i = (mwc32() >> 8) % MAX_PIPES;
  114             (void)memset(buf, '0' + i, sizeof(buf));
  115             ret = write(pipefds[i][1], buf, sizeof(buf));
  116             if (ret < (ssize_t)sizeof(buf)) {
  117                 if ((errno == EAGAIN) || (errno == EINTR))
  118                     continue;
  119                 pr_fail_dbg("write");
  120                 goto abort;
  121             }
  122          } while (keep_stressing());
  123 abort:
  124         for (i = 0; i < MAX_PIPES; i++)
  125             (void)close(pipefds[i][1]);
  126         exit(EXIT_SUCCESS);
  127     } else {
  128         /* Parent read */
  129 
  130         int maxfd = 0, status;
  131         struct pollfd fds[MAX_PIPES];
  132         fd_set rfds;
  133 #if defined(HAVE_PPOLL) || defined(HAVE_PSELECT)
  134         struct timespec ts;
  135         sigset_t sigmask;
  136 #endif
  137 
  138         (void)setpgid(pid, g_pgrp);
  139 
  140         FD_ZERO(&rfds);
  141         for (i = 0; i < MAX_PIPES; i++) {
  142             fds[i].fd = pipefds[i][0];
  143             fds[i].events = POLLIN;
  144             fds[i].revents = 0;
  145 
  146             FD_SET(pipefds[i][0], &rfds);
  147             if (pipefds[i][0] > maxfd)
  148                 maxfd = pipefds[i][0];
  149         }
  150 
  151         do {
  152             struct timeval tv;
  153             int ret;
  154 
  155             if (!keep_stressing())
  156                 break;
  157 
  158             /* stress out poll */
  159             ret = poll(fds, MAX_PIPES, 1);
  160             if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  161                 (ret < 0) && (errno != EINTR)) {
  162                 pr_fail_err("poll");
  163             }
  164             if (ret > 0) {
  165                 for (i = 0; i < MAX_PIPES; i++) {
  166                     if (fds[i].revents == POLLIN) {
  167                         if (pipe_read(args, fds[i].fd, i) < 0)
  168                             break;
  169                     }
  170                 }
  171                 inc_counter(args);
  172             }
  173 
  174             if (!keep_stressing())
  175                 break;
  176 
  177 #if defined(HAVE_PPOLL)
  178             /* stress out ppoll */
  179 
  180             ts.tv_sec = 0;
  181             ts.tv_nsec = 20000000;
  182 
  183             (void)sigemptyset(&sigmask);
  184             (void)sigaddset(&sigmask, SIGPIPE);
  185 
  186             ret = ppoll(fds, MAX_PIPES, &ts, &sigmask);
  187             if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  188                 (ret < 0) && (errno != EINTR)) {
  189                 pr_fail_err("ppoll");
  190             }
  191             if (ret > 0) {
  192                 for (i = 0; i < MAX_PIPES; i++) {
  193                     if (fds[i].revents == POLLIN) {
  194                         if (pipe_read(args, fds[i].fd, i) < 0)
  195                             break;
  196                     }
  197                 }
  198                 inc_counter(args);
  199             }
  200             if (!keep_stressing())
  201                 break;
  202 #endif
  203 
  204             /* stress out select */
  205             tv.tv_sec = 0;
  206             tv.tv_usec = 20000;
  207             ret = select(maxfd + 1, &rfds, NULL, NULL, &tv);
  208             if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  209                 (ret < 0) && (errno != EINTR)) {
  210                 pr_fail_err("select");
  211             }
  212             if (ret > 0) {
  213                 for (i = 0; i < MAX_PIPES; i++) {
  214                     if (FD_ISSET(pipefds[i][0], &rfds)) {
  215                         if (pipe_read(args, pipefds[i][0], i) < 0)
  216                             break;
  217                     }
  218                     FD_SET(pipefds[i][0], &rfds);
  219                 }
  220                 inc_counter(args);
  221             }
  222             if (!keep_stressing())
  223                 break;
  224 #if defined(HAVE_PSELECT)
  225             /* stress out pselect */
  226             ts.tv_sec = 0;
  227             ts.tv_nsec = 20000000;
  228 
  229             (void)sigemptyset(&sigmask);
  230             (void)sigaddset(&sigmask, SIGPIPE);
  231 
  232             ret = pselect(maxfd + 1, &rfds, NULL, NULL, &ts, &sigmask);
  233             if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  234                 (ret < 0) && (errno != EINTR)) {
  235                 pr_fail_err("pselect");
  236             }
  237             if (ret > 0) {
  238                 for (i = 0; i < MAX_PIPES; i++) {
  239                     if (FD_ISSET(pipefds[i][0], &rfds)) {
  240                         if (pipe_read(args, pipefds[i][0], i) < 0)
  241                             break;
  242                     }
  243                     FD_SET(pipefds[i][0], &rfds);
  244                 }
  245                 inc_counter(args);
  246             }
  247 #endif
  248             /*
  249              * stress zero sleep, this is like
  250              * a select zero timeout
  251              */
  252             (void)sleep(0);
  253         } while (keep_stressing());
  254 
  255         (void)kill(pid, SIGKILL);
  256         (void)waitpid(pid, &status, 0);
  257     }
  258 
  259 tidy:
  260     for (i = 0; i < MAX_PIPES; i++) {
  261         (void)close(pipefds[i][0]);
  262         (void)close(pipefds[i][1]);
  263     }
  264 
  265     return rc;
  266 }
  267 
  268 stressor_info_t stress_poll_info = {
  269     .stressor = stress_poll,
  270     .class = CLASS_SCHEDULER | CLASS_OS
  271 };
  272 #else
  273 stressor_info_t stress_poll_info = {
  274     .stressor = stress_not_implemented,
  275     .class = CLASS_SCHEDULER | CLASS_OS
  276 };
  277 #endif