"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-bigheap.c" (15 Mar 2019, 5827 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-bigheap.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.09.55_vs_0.09.56.

    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  *  stress_set_bigheap_growth()
   29  *      Set bigheap growth from given opt arg string
   30  */
   31 int stress_set_bigheap_growth(const char *opt)
   32 {
   33     uint64_t bigheap_growth;
   34 
   35     bigheap_growth = get_uint64_byte(opt);
   36     check_range_bytes("bigheap-growth", bigheap_growth,
   37         MIN_BIGHEAP_GROWTH, MAX_BIGHEAP_GROWTH);
   38     return set_setting("bigheap-growth", TYPE_ID_UINT64, &bigheap_growth);
   39 }
   40 
   41 /*
   42  *  stress_bigheap()
   43  *  stress heap allocation
   44  */
   45 static int stress_bigheap(const args_t *args)
   46 {
   47     void *ptr = NULL, *last_ptr = NULL;
   48     const size_t page_size = args->page_size;
   49     const size_t stride = page_size;
   50     size_t size = 0;
   51     uint32_t ooms = 0, segvs = 0, nomems = 0;
   52     pid_t pid;
   53     uint8_t *last_ptr_end = NULL;
   54     uint64_t bigheap_growth = DEFAULT_BIGHEAP_GROWTH;
   55 
   56     if (!get_setting("bigheap-growth", &bigheap_growth)) {
   57         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
   58             bigheap_growth = MAX_BIGHEAP_GROWTH;
   59         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
   60             bigheap_growth = MIN_BIGHEAP_GROWTH;
   61     }
   62     if (bigheap_growth < page_size)
   63         bigheap_growth = page_size;
   64 
   65     /* Round growth size to nearest page size */
   66     bigheap_growth &= ~(page_size - 1);
   67 again:
   68     if (!keep_stressing())
   69         return EXIT_SUCCESS;
   70     pid = fork();
   71     if (pid < 0) {
   72         if (errno == EAGAIN)
   73             goto again;
   74         pr_err("%s: fork failed: errno=%d: (%s)\n",
   75             args->name, errno, strerror(errno));
   76     } else if (pid > 0) {
   77         int status, ret;
   78 
   79         (void)setpgid(pid, g_pgrp);
   80         /* Parent, wait for child */
   81         ret = waitpid(pid, &status, 0);
   82         if (ret < 0) {
   83             if (errno != EINTR)
   84                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
   85                     args->name, errno, strerror(errno));
   86             (void)kill(pid, SIGTERM);
   87             (void)kill(pid, SIGKILL);
   88             (void)waitpid(pid, &status, 0);
   89         } else if (WIFSIGNALED(status)) {
   90             pr_dbg("%s: child died: %s (instance %d)\n",
   91                 args->name, stress_strsignal(WTERMSIG(status)),
   92                 args->instance);
   93             /* If we got killed by OOM killer, re-start */
   94             if (WTERMSIG(status) == SIGKILL) {
   95                 if (g_opt_flags & OPT_FLAGS_OOMABLE) {
   96                     log_system_mem_info();
   97                     pr_dbg("%s: assuming killed by OOM "
   98                         "killer, bailing out "
   99                         "(instance %d)\n",
  100                         args->name, args->instance);
  101                     _exit(0);
  102                 } else {
  103                     log_system_mem_info();
  104                     pr_dbg("%s: assuming killed by OOM "
  105                         "killer, restarting again "
  106                         "(instance %d)\n",
  107                         args->name, args->instance);
  108                     ooms++;
  109                     goto again;
  110                 }
  111             }
  112             /* If we got killed by sigsegv, re-start */
  113             if (WTERMSIG(status) == SIGSEGV) {
  114                 pr_dbg("%s: killed by SIGSEGV, "
  115                     "restarting again "
  116                     "(instance %d)\n",
  117                     args->name, args->instance);
  118                 segvs++;
  119                 goto again;
  120             }
  121         }
  122     } else if (pid == 0) {
  123         (void)setpgid(0, g_pgrp);
  124         stress_parent_died_alarm();
  125 
  126         /* Make sure this is killable by OOM killer */
  127         set_oom_adjustment(args->name, true);
  128 
  129         do {
  130             void *old_ptr = ptr;
  131             size += (size_t)bigheap_growth;
  132 
  133             /*
  134              * With many instances running it is wise to
  135              * double check before the next realloc as
  136              * sometimes process start up is delayed for
  137              * some time and we should bail out before
  138              * exerting any more memory pressure
  139              */
  140             if (!keep_stressing())
  141                 goto abort;
  142 
  143             ptr = realloc(old_ptr, size);
  144             if (ptr == NULL) {
  145                 pr_dbg("%s: out of memory at %" PRIu64
  146                     " MB (instance %d)\n",
  147                     args->name, (uint64_t)(4096ULL * size) >> 20,
  148                     args->instance);
  149                 free(old_ptr);
  150                 size = 0;
  151                 nomems++;
  152             } else {
  153                 size_t i, n;
  154                 uint8_t *u8ptr, *tmp;
  155 
  156                 if (last_ptr == ptr) {
  157                     tmp = u8ptr = last_ptr_end;
  158                     n = (size_t)bigheap_growth;
  159                 } else {
  160                     tmp = u8ptr = ptr;
  161                     n = size;
  162                 }
  163                 if (!keep_stressing())
  164                     goto abort;
  165 
  166                 if (page_size > 0) {
  167                     size_t sz = page_size - 1;
  168                     uintptr_t pg_ptr = ((uintptr_t)ptr + sz) & ~sz;
  169                     size_t len = size - (pg_ptr - (uintptr_t)ptr);
  170                     (void)mincore_touch_pages((void *)pg_ptr, len);
  171                 }
  172 
  173                 for (i = 0; i < n; i+= stride, u8ptr += stride) {
  174                     if (!keep_stressing())
  175                         goto abort;
  176                     *u8ptr = (uint8_t)i;
  177                 }
  178 
  179                 if (g_opt_flags & OPT_FLAGS_VERIFY) {
  180                     for (i = 0; i < n; i+= stride, tmp += stride) {
  181                         if (!keep_stressing())
  182                             goto abort;
  183                         if (*tmp != (uint8_t)i)
  184                             pr_fail("%s: byte at location %p was 0x%" PRIx8
  185                                 " instead of 0x%" PRIx8 "\n",
  186                                 args->name, (void *)u8ptr, *tmp, (uint8_t)i);
  187                     }
  188                 }
  189                 last_ptr = ptr;
  190                 last_ptr_end = u8ptr;
  191             }
  192             inc_counter(args);
  193         } while (keep_stressing());
  194 abort:
  195         free(ptr);
  196     }
  197     if (ooms + segvs + nomems > 0)
  198         pr_dbg("%s: OOM restarts: %" PRIu32
  199             ", SEGV restarts: %" PRIu32
  200             ", out of memory restarts: %" PRIu32 ".\n",
  201             args->name, ooms, segvs, nomems);
  202 
  203     return EXIT_SUCCESS;
  204 }
  205 
  206 stressor_info_t stress_bigheap_info = {
  207     .stressor = stress_bigheap,
  208     .class = CLASS_OS | CLASS_VM
  209 };