"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-rmap.c" (15 Mar 2019, 7060 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-rmap.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 #define RMAP_CHILD_MAX      (16)
   28 #define MAPPINGS_MAX        (64)
   29 #define MAPPING_PAGES       (16)
   30 
   31 /*
   32  *  [ MAPPING 0 ]
   33  *  [ page ][ MAPPING 1 ]
   34  *  [ page ][page ][ MAPPING 2]
   35  *  [ page ][page ][ page ][ MAPPING 3]
   36  *
   37  *  file size = ((MAPPINGS_MAX - 1) + MAPPING_PAGES) * page_size;
   38  */
   39 
   40 /*
   41  *  stress_rmap_handler()
   42  *      rmap signal handler
   43  */
   44 static void MLOCKED_TEXT stress_rmap_handler(int signum)
   45 {
   46     (void)signum;
   47 
   48     (void)kill(getppid(), SIGALRM);
   49     _exit(0);
   50 }
   51 
   52 static void stress_rmap_child(
   53     uint64_t *const counter,
   54     const uint64_t max_ops,
   55     const size_t page_size,
   56     uint8_t *mappings[MAPPINGS_MAX])
   57 {
   58     const size_t sz = MAPPING_PAGES * page_size;
   59 
   60     do {
   61         ssize_t i;
   62         const int sync_flag = mwc8() ? MS_ASYNC : MS_SYNC;
   63 
   64         switch (mwc32() & 3) {
   65         case 0: for (i = 0; g_keep_stressing_flag && (i < MAPPINGS_MAX); i++) {
   66                 if (max_ops && *counter >= max_ops)
   67                     break;
   68                 if (mappings[i] != MAP_FAILED) {
   69                     (void)memset(mappings[i], mwc8(), sz);
   70                     (void)shim_msync(mappings[i], sz, sync_flag);
   71                 }
   72             }
   73             break;
   74         case 1: for (i = MAPPINGS_MAX - 1; g_keep_stressing_flag && (i >= 0); i--) {
   75                 if (max_ops && *counter >= max_ops)
   76                     break;
   77                 if (mappings[i] != MAP_FAILED) {
   78                     (void)memset(mappings[i], mwc8(), sz);
   79                     (void)shim_msync(mappings[i], sz, sync_flag);
   80                 }
   81             }
   82             break;
   83         case 2: for (i = 0; g_keep_stressing_flag && (i < MAPPINGS_MAX); i++) {
   84                 size_t j = mwc32() % MAPPINGS_MAX;
   85                 if (max_ops && *counter >= max_ops)
   86                     break;
   87                 if (mappings[j] != MAP_FAILED) {
   88                     (void)memset(mappings[j], mwc8(), sz);
   89                     (void)shim_msync(mappings[j], sz, sync_flag);
   90                 }
   91             }
   92             break;
   93         case 3: for (i = 0; g_keep_stressing_flag && (i < MAPPINGS_MAX - 1); i++) {
   94                 if (max_ops && *counter >= max_ops)
   95                     break;
   96                 if (mappings[i] != MAP_FAILED) {
   97                     (void)memcpy(mappings[i], mappings[i + 1], sz);
   98                     (void)shim_msync(mappings[i], sz, sync_flag);
   99                 }
  100             }
  101             break;
  102         }
  103         (*counter)++;
  104     } while (g_keep_stressing_flag && (!max_ops || *counter < max_ops));
  105 
  106     _exit(0);
  107 }
  108 
  109 /*
  110  *  stress_rmap()
  111  *  stress mmap
  112  */
  113 static int stress_rmap(const args_t *args)
  114 {
  115     const size_t page_size = args->page_size;
  116     const size_t sz = ((MAPPINGS_MAX - 1) + MAPPING_PAGES) * page_size;
  117     const size_t counters_sz =
  118         (page_size + sizeof(uint64_t) * RMAP_CHILD_MAX) & ~(page_size - 1);
  119     int fd = -1;
  120     size_t i;
  121     ssize_t rc;
  122     pid_t pids[RMAP_CHILD_MAX];
  123     uint8_t *mappings[MAPPINGS_MAX];
  124     uint8_t *paddings[MAPPINGS_MAX];
  125     uint64_t *counters;
  126     char filename[PATH_MAX];
  127 
  128     counters = (uint64_t *)mmap(NULL, counters_sz, PROT_READ | PROT_WRITE,
  129         MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  130     if (counters == MAP_FAILED) {
  131         pr_err("%s: mmap failed: errno=%d (%s)\n",
  132             args->name, errno, strerror(errno));
  133         return EXIT_FAILURE;
  134     }
  135     (void)memset(counters, 0, counters_sz);
  136     (void)memset(pids, 0, sizeof(pids));
  137 
  138     for (i = 0; i < MAPPINGS_MAX; i++) {
  139         mappings[i] = MAP_FAILED;
  140         paddings[i] = MAP_FAILED;
  141     }
  142 
  143     /* Make sure this is killable by OOM killer */
  144     set_oom_adjustment(args->name, true);
  145 
  146     rc = stress_temp_dir_mk_args(args);
  147     if (rc < 0)
  148         return exit_status(-rc);
  149 
  150     (void)stress_temp_filename_args(args,
  151         filename, sizeof(filename), mwc32());
  152 
  153     if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
  154         rc = exit_status(errno);
  155         pr_fail_err("open");
  156         (void)unlink(filename);
  157         (void)stress_temp_dir_rm_args(args);
  158         (void)munmap((void *)counters, counters_sz);
  159 
  160         return rc;
  161     }
  162     (void)unlink(filename);
  163 
  164     if (shim_fallocate(fd, 0, 0, sz) < 0) {
  165         pr_fail_err("fallocate");
  166         (void)close(fd);
  167         (void)stress_temp_dir_rm_args(args);
  168         (void)munmap((void *)counters, counters_sz);
  169 
  170         return EXIT_FAILURE;
  171     }
  172 
  173     for (i = 0; i < MAPPINGS_MAX; i++) {
  174         off_t offset = i * page_size;
  175 
  176         if (!keep_stressing())
  177             goto cleanup;
  178 
  179         mappings[i] =
  180             (uint8_t *)mmap(0, MAPPING_PAGES * page_size, PROT_READ | PROT_WRITE,
  181                 MAP_SHARED, fd, offset);
  182         /* Squeeze at least a page in between each mapping */
  183         paddings[i] =
  184             (uint8_t *)mmap(0, page_size, PROT_READ | PROT_WRITE,
  185                 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  186     }
  187 
  188     /*
  189      *  Spawn children workers
  190      */
  191     for (i = 0; i < RMAP_CHILD_MAX; i++) {
  192         if (!keep_stressing())
  193             goto cleanup;
  194 
  195         pids[i] = fork();
  196         if (pids[i] < 0) {
  197             pr_err("%s: fork failed: errno=%d: (%s)\n",
  198                 args->name, errno, strerror(errno));
  199             goto cleanup;
  200         } else if (pids[i] == 0) {
  201             if (stress_sighandler(args->name, SIGALRM,
  202                 stress_rmap_handler, NULL) < 0)
  203                 _exit(EXIT_FAILURE);
  204 
  205             (void)setpgid(0, g_pgrp);
  206             stress_parent_died_alarm();
  207 
  208             /* Make sure this is killable by OOM killer */
  209             set_oom_adjustment(args->name, true);
  210             stress_rmap_child(&counters[i], (args->max_ops / RMAP_CHILD_MAX) + 1,
  211                 page_size, mappings);
  212         } else {
  213             (void)setpgid(pids[i], g_pgrp);
  214         }
  215     }
  216 
  217     /*
  218      *  Wait for SIGINT or SIGALRM
  219      */
  220     while (keep_stressing()) {
  221         uint64_t c = 0;
  222 
  223         /* Twiddle fingers */
  224         (void)shim_usleep(100000);
  225 
  226         for (i = 0; i < RMAP_CHILD_MAX; i++)
  227             c += counters[i];
  228 
  229         set_counter(args, c);
  230     }
  231 
  232 cleanup:
  233     /*
  234      *  Kill and wait for children
  235      */
  236     for (i = 0; i < RMAP_CHILD_MAX; i++) {
  237         if (pids[i] <= 0)
  238             continue;
  239         (void)kill(pids[i], SIGKILL);
  240     }
  241     for (i = 0; i < RMAP_CHILD_MAX; i++) {
  242         int status, ret;
  243 
  244         if (pids[i] <= 0)
  245             continue;
  246 
  247         ret = waitpid(pids[i], &status, 0);
  248         if (ret < 0) {
  249             if (errno != EINTR)
  250                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  251                     args->name, errno, strerror(errno));
  252             (void)kill(pids[i], SIGTERM);
  253             (void)kill(pids[i], SIGKILL);
  254             (void)waitpid(pids[i], &status, 0);
  255         }
  256     }
  257 
  258     (void)munmap((void *)counters, counters_sz);
  259     (void)close(fd);
  260     (void)stress_temp_dir_rm_args(args);
  261 
  262     for (i = 0; i < MAPPINGS_MAX; i++) {
  263         if (mappings[i] != MAP_FAILED)
  264             (void)munmap((void *)mappings[i], MAPPING_PAGES * page_size);
  265         if (paddings[i] != MAP_FAILED)
  266             (void)munmap((void *)paddings[i], page_size);
  267     }
  268 
  269     return EXIT_SUCCESS;
  270 }
  271 
  272 stressor_info_t stress_rmap_info = {
  273     .stressor = stress_rmap,
  274     .class = CLASS_OS | CLASS_MEMORY
  275 };