"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-mmapfixed.c" (15 Mar 2019, 5520 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-mmapfixed.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 #if UINTPTR_MAX == MAX_32
   28 #define MMAP_TOP    (0x80000000UL)
   29 #else
   30 #define MMAP_TOP    (0x8000000000000000ULL)
   31 #endif
   32 #define MMAP_BOTTOM (0x10000)
   33 
   34 /*
   35  *  stress_sigsegv_handler()
   36  *  older kernels can kill the child when fixed mappings
   37  *  can't be backed by physical pages. In this case,
   38  *  force child termination and reap and account this
   39  *  in the main stressor loop.
   40  */
   41 static void MLOCKED_TEXT stress_sigsegv_handler(int signum)
   42 {
   43     (void)signum;
   44 
   45     _exit(0);
   46 }
   47 
   48 static void stress_mmapfixed_child(const args_t *args)
   49 {
   50     const size_t page_size = args->page_size;
   51     uintptr_t addr = MMAP_TOP;
   52     int ret;
   53 
   54     ret = stress_sighandler(args->name, SIGSEGV,
   55                 stress_sigsegv_handler, NULL);
   56     (void)ret;
   57 
   58     do {
   59         uint8_t *buf;
   60         int flags = MAP_FIXED | MAP_ANONYMOUS;
   61         size_t  sz = page_size * (1 + (mwc8() % 7));
   62 
   63 #if defined(MAP_SHARED) && defined(MAP_PRIVATE)
   64         flags |= mwc1() ? MAP_SHARED : MAP_PRIVATE;
   65 #endif
   66 #if defined(MAP_LOCKED)
   67         flags |= mwc1() ? MAP_LOCKED : 0;
   68 #endif
   69 #if defined(MAP_NORESERVE)
   70         flags |= mwc1() ? MAP_NORESERVE : 0;
   71 #endif
   72 #if defined(MAP_POPULATE)
   73         flags |= mwc1() ? MAP_POPULATE : 0;
   74 #endif
   75 #if defined(MAP_FIXED_NOREPLACE)
   76         /* 4.17 Linux flag */
   77         flags &= ~MAP_FIXED;
   78         flags |= mwc1() ? MAP_FIXED : MAP_FIXED_NOREPLACE;
   79 #endif
   80 
   81         if (!g_keep_stressing_flag)
   82             break;
   83         buf = (uint8_t *)mmap((void *)addr, sz,
   84             PROT_READ, flags, -1, 0);
   85         if (buf == MAP_FAILED)
   86             goto next;
   87 
   88         (void)madvise_random(buf, sz);
   89 #if defined(HAVE_MREMAP) && NEED_GLIBC(2,4,0) && \
   90     defined(MREMAP_FIXED) && \
   91     defined(MREMAP_MAYMOVE)
   92         {
   93             uint8_t *newbuf;
   94             const uintptr_t newaddr = addr ^
   95                 ((page_size << 3) | (page_size << 4));
   96 
   97             newbuf = mremap(buf, sz, sz,
   98                     MREMAP_FIXED | MREMAP_MAYMOVE,
   99                     (void *)newaddr);
  100             if (newbuf && (newbuf != MAP_FAILED))
  101                 buf = newbuf;
  102 
  103             (void)madvise_random(buf, sz);
  104         }
  105 #endif
  106         (void)munmap((void *)buf, sz);
  107         inc_counter(args);
  108 next:
  109         addr >>= 1;
  110         if (addr < MMAP_BOTTOM)
  111             addr = MMAP_TOP;
  112     } while (keep_stressing());
  113 }
  114 
  115 /*
  116  *  stress_mmapfixed()
  117  *  stress mmap at fixed hinted addresses
  118  */
  119 static int stress_mmapfixed(const args_t *args)
  120 {
  121     pid_t pid;
  122     uint32_t ooms = 0, segvs = 0, buserrs = 0;
  123 
  124     /* Make sure this is killable by OOM killer */
  125     set_oom_adjustment(args->name, true);
  126 
  127 again:
  128     if (!g_keep_stressing_flag)
  129         goto cleanup;
  130     pid = fork();
  131     if (pid < 0) {
  132         if ((errno == EAGAIN) || (errno == ENOMEM))
  133             goto again;
  134         pr_err("%s: fork failed: errno=%d: (%s)\n",
  135             args->name, errno, strerror(errno));
  136     } else if (pid > 0) {
  137         int status, ret;
  138 
  139         (void)setpgid(pid, g_pgrp);
  140         /* Parent, wait for child */
  141         ret = waitpid(pid, &status, 0);
  142         if (ret < 0) {
  143             if (errno != EINTR)
  144                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  145                     args->name, errno, strerror(errno));
  146             (void)kill(pid, SIGTERM);
  147             (void)kill(pid, SIGKILL);
  148             (void)waitpid(pid, &status, 0);
  149         } else if (WIFSIGNALED(status)) {
  150             /* If we got killed by sigbus, re-start */
  151             if (WTERMSIG(status) == SIGBUS) {
  152                 /* Happens frequently, so be silent */
  153                 buserrs++;
  154                 goto again;
  155             }
  156 
  157             /*
  158              *  If child got killed by sigsegv then
  159              *  account this and silently restart.
  160              *  "Move along now, nothing to see.."
  161              */
  162             if (WTERMSIG(status) == SIGSEGV) {
  163                 segvs++;
  164                 goto again;
  165             }
  166 
  167             pr_dbg("%s: child died: %s (instance %d)\n",
  168                 args->name, stress_strsignal(WTERMSIG(status)),
  169                 args->instance);
  170             /* If we got killed by OOM killer, re-start */
  171             if (WTERMSIG(status) == SIGKILL) {
  172                 if (g_opt_flags & OPT_FLAGS_OOMABLE) {
  173                     log_system_mem_info();
  174                     pr_dbg("%s: assuming killed by OOM "
  175                         "killer, bailing out "
  176                         "(instance %d)\n",
  177                         args->name, args->instance);
  178                     _exit(0);
  179                 } else {
  180                     log_system_mem_info();
  181                     pr_dbg("%s: assuming killed by OOM "
  182                         "killer, restarting again "
  183                         "(instance %d)\n",
  184                         args->name, args->instance);
  185                     ooms++;
  186                     goto again;
  187                 }
  188             }
  189         }
  190     } else if (pid == 0) {
  191         (void)setpgid(0, g_pgrp);
  192         stress_parent_died_alarm();
  193 
  194         /* Make sure this is killable by OOM killer */
  195         set_oom_adjustment(args->name, true);
  196         stress_mmapfixed_child(args);
  197     }
  198 
  199 cleanup:
  200     if (ooms + segvs + buserrs > 0)
  201         pr_dbg("%s: OOM restarts: %" PRIu32
  202             ", SEGV restarts: %" PRIu32
  203             ", SIGBUS signals: %" PRIu32 "\n",
  204             args->name, ooms, segvs, buserrs);
  205 
  206     return EXIT_SUCCESS;
  207 }
  208 
  209 stressor_info_t stress_mmapfixed_info = {
  210     .stressor = stress_mmapfixed,
  211     .class = CLASS_VM | CLASS_OS
  212 };