"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-thrash.c" (15 Mar 2019, 4730 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 "core-thrash.c" see the Fossies "Dox" file reference documentation.

    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(__linux__) && defined(HAVE_PTRACE)
   28 
   29 #define KSM_RUN_MERGE       "1"
   30 
   31 static pid_t thrash_pid;
   32 
   33 /*
   34  *  pagein_proc()
   35  *  force pages into memory for a given process
   36  */
   37 static int pagein_proc(const pid_t pid)
   38 {
   39     char path[PATH_MAX];
   40     char buffer[4096];
   41     int fdmem, ret;
   42     FILE *fpmap;
   43     const size_t page_size = stress_get_pagesize();
   44     size_t pages = 0;
   45 
   46     ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
   47     if (ret < 0)
   48         return -errno;
   49 
   50     (void)snprintf(path, sizeof(path), "/proc/%d/mem", pid);
   51     fdmem = open(path, O_RDONLY);
   52     if (fdmem < 0)
   53         return -errno;
   54 
   55     (void)snprintf(path, sizeof(path), "/proc/%d/maps", pid);
   56     fpmap = fopen(path, "r");
   57     if (!fpmap) {
   58         (void)close(fdmem);
   59         return -errno;
   60     }
   61 
   62     /*
   63      * Look for field 0060b000-0060c000 r--p 0000b000 08:01 1901726
   64      */
   65     while (fgets(buffer, sizeof(buffer), fpmap)) {
   66         uintmax_t begin, end, len;
   67         uintptr_t off;
   68         char tmppath[1024];
   69         char prot[5];
   70 
   71         if (sscanf(buffer, "%" SCNx64 "-%" SCNx64
   72                    " %5s %*x %*x:%*x %*d %1023s", &begin, &end, prot, tmppath) != 4)
   73             continue;
   74 
   75         /* ignore non-readable or non-private mappings */
   76         if (prot[0] != 'r' && prot[3] != 'p')
   77             continue;
   78         len = end - begin;
   79 
   80         /* Ignore bad range */
   81         if ((begin >= end) || (len == 0) || (begin == 0))
   82             continue;
   83         /* Skip huge ranges more than 2GB */
   84         if (len > 0x80000000UL)
   85             continue;
   86 
   87         for (off = begin; off < end; off += page_size, pages++) {
   88             unsigned long data;
   89             off_t pos;
   90             size_t sz;
   91 
   92             (void)ptrace(PTRACE_PEEKDATA, pid, (void *)off, &data);
   93             pos = lseek(fdmem, off, SEEK_SET);
   94             if (pos != (off_t)off)
   95                 continue;
   96             sz = read(fdmem, &data, sizeof(data));
   97             (void)sz;
   98         }
   99     }
  100 
  101     (void)ptrace(PTRACE_DETACH, pid, NULL, NULL);
  102     (void)fclose(fpmap);
  103     (void)close(fdmem);
  104 
  105     return 0;
  106 }
  107 
  108 /*
  109  *  compact_memory()
  110  *  trigger memory compaction, Linux only
  111  */
  112 static inline void compact_memory(void)
  113 {
  114 #if defined(__linux__)
  115     int ret;
  116 
  117     ret = system_write("/proc/sys/vm/compact_memory", "1", 1);
  118     (void)ret;
  119 #endif
  120 }
  121 
  122 /*
  123  *  merge_memory()
  124  *  trigger ksm memory merging, Linux only
  125  */
  126 static inline void merge_memory(void)
  127 {
  128 #if defined(__linux__)
  129     int ret;
  130 
  131     ret = system_write("/proc/sys/mm/ksm/run", KSM_RUN_MERGE, 1);
  132     (void)ret;
  133 #endif
  134 }
  135 
  136 /*
  137  *  pagein_all_procs()
  138  *  force pages into memory for all processes
  139  */
  140 static int pagein_all_procs(void)
  141 {
  142     DIR *dp;
  143     struct dirent *d;
  144 
  145     dp = opendir("/proc");
  146     if (!dp)
  147         return -1;
  148 
  149     while ((d = readdir(dp)) != NULL) {
  150         pid_t pid;
  151 
  152         if (isdigit(d->d_name[0]) &&
  153             sscanf(d->d_name, "%d", &pid) == 1) {
  154             pagein_proc(pid);
  155         }
  156     }
  157     (void)closedir(dp);
  158 
  159     return 0;
  160 }
  161 
  162 /*
  163  *  thrash_start()
  164  *  start paging in thrash process
  165  */
  166 int thrash_start(void)
  167 {
  168     if (geteuid() != 0) {
  169         pr_inf("not running as root, ignoring --thrash option\n");
  170         return -1;
  171     }
  172     if (thrash_pid) {
  173         pr_err("thrash background process already started\n");
  174         return -1;
  175     }
  176     thrash_pid = fork();
  177     if (thrash_pid < 0) {
  178         pr_err("thrash background process failed to fork: %d (%s)\n",
  179             errno, strerror(errno));
  180         return -1;
  181     } else if (thrash_pid == 0) {
  182 #if defined(SCHED_RR)
  183         int ret;
  184 
  185         stress_set_proc_name("stress-ng-thrash");
  186 
  187         ret = stress_set_sched(getpid(), SCHED_RR, 10, true);
  188         (void)ret;
  189 #endif
  190         while (g_keep_stressing_flag) {
  191             pagein_all_procs();
  192             compact_memory();
  193             merge_memory();
  194             (void)sleep(1);
  195         }
  196         _exit(0);
  197     }
  198     return 0;
  199 }
  200 
  201 /*
  202  *  thrash_stop()
  203  *  stop paging in thrash process
  204  */
  205 void thrash_stop(void)
  206 {
  207     int status;
  208 
  209     if (!thrash_pid)
  210         return;
  211 
  212     (void)kill(thrash_pid, SIGKILL);
  213     (void)waitpid(thrash_pid, &status, 0);
  214 
  215     thrash_pid = 0;
  216 }
  217 
  218 #else
  219 int thrash_start(void)
  220 {
  221     return 0;
  222 }
  223 
  224 void thrash_stop(void)
  225 {
  226 }
  227 #endif