"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-mcontend.c" (15 Mar 2019, 7821 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-mcontend.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  * This program is free software; you can redistribute it and/or
    3  * modify it under the terms of the GNU General Public License
    4  * as published by the Free Software Foundation; either version 2
    5  * of the License, or (at your option) any later version.
    6  *
    7  * This program is distributed in the hope that it will be useful,
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10  * GNU General Public License for more details.
   11  *
   12  * You should have received a copy of the GNU General Public License
   13  * along with this program; if not, write to the Free Software
   14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   15  *
   16  * This code is a complete clean re-write of the stress tool by
   17  * Colin Ian King <colin.king@canonical.com> and attempts to be
   18  * backwardly compatible with the stress tool by Amos Waterland
   19  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   20  * functionality.
   21  *
   22  */
   23 #include "stress-ng.h"
   24 
   25 #if defined(HAVE_LIB_PTHREAD)
   26 
   27 static sigset_t set;
   28 
   29 #define MAX_READ_THREADS    (4)
   30 #define MAX_MAPPINGS        (2)
   31 
   32 static inline void mem_barrier(void)
   33 {
   34     asm volatile("": : :"memory");
   35 }
   36 
   37 #if defined(STRESS_X86)
   38 static inline void cpu_relax(void)
   39 {
   40     asm volatile("pause\n": : :"memory");
   41 }
   42 #endif
   43 
   44 static inline HOT OPTIMIZE3 void read64(uint64_t *data)
   45 {
   46     register uint64_t v;
   47     volatile uint64_t *vdata = data;
   48 
   49     __builtin_prefetch(data);
   50     v = vdata[0];
   51     (void)v;
   52     v = vdata[1];
   53     (void)v;
   54     v = vdata[3];
   55     (void)v;
   56     v = vdata[4];
   57     (void)v;
   58     v = vdata[5];
   59     (void)v;
   60     v = vdata[6];
   61     (void)v;
   62     v = vdata[7];
   63     (void)v;
   64     v = vdata[8];
   65     (void)v;
   66 }
   67 
   68 /*
   69  *  stressmemory_contend()
   70  *  read a proc file
   71  */
   72 static inline HOT OPTIMIZE3 void stress_memory_contend(const pthread_args_t *pa)
   73 {
   74     uint64_t **mappings = pa->data;
   75     volatile uint64_t *vdata0 = mappings[0];
   76     volatile uint64_t *vdata1 = mappings[0];
   77     uint64_t *data0 = mappings[0];
   78     uint64_t *data1 = mappings[0];
   79     register int i;
   80 
   81     for (i = 0; i < 1024; i++) {
   82         vdata0[0] = i;
   83         vdata1[0] = i;
   84         vdata0[1] = i;
   85         vdata1[1] = i;
   86         vdata0[2] = i;
   87         vdata1[2] = i;
   88         vdata0[3] = i;
   89         vdata1[3] = i;
   90         vdata0[4] = i;
   91         vdata1[4] = i;
   92         vdata0[5] = i;
   93         vdata1[5] = i;
   94         vdata0[6] = i;
   95         vdata1[6] = i;
   96         vdata0[7] = i;
   97         vdata1[7] = i;
   98         read64(data0);
   99         read64(data1);
  100     }
  101 
  102     for (i = 0; i < 1024; i++) {
  103         vdata0[0] = i; mfence();
  104         vdata1[0] = i; mfence();
  105         vdata0[1] = i; mfence();
  106         vdata1[1] = i; mfence();
  107         vdata0[2] = i; mfence();
  108         vdata1[2] = i; mfence();
  109         vdata0[3] = i; mfence();
  110         vdata1[3] = i; mfence();
  111         vdata0[4] = i; mfence();
  112         vdata1[4] = i; mfence();
  113         vdata0[5] = i; mfence();
  114         vdata1[5] = i; mfence();
  115         vdata0[6] = i; mfence();
  116         vdata1[6] = i; mfence();
  117         vdata0[7] = i; mfence();
  118         vdata1[7] = i; mfence();
  119         read64(data0);
  120         read64(data1);
  121     }
  122 
  123 #if defined(STRESS_X86)
  124     for (i = 0; i < 1024; i++) {
  125         vdata0[0] = i;
  126         vdata1[0] = i;
  127         vdata0[1] = i;
  128         vdata1[1] = i;
  129         vdata0[2] = i;
  130         vdata1[2] = i;
  131         vdata0[3] = i;
  132         vdata1[3] = i;
  133         vdata0[4] = i;
  134         vdata1[4] = i;
  135         vdata0[5] = i;
  136         vdata1[5] = i;
  137         vdata0[6] = i;
  138         vdata1[6] = i;
  139         vdata0[7] = i;
  140         vdata1[7] = i;
  141         clflush(data0);
  142         clflush(data1);
  143         read64(data0);
  144         read64(data1);
  145     }
  146 
  147     for (i = 0; i < 1024; i++) {
  148         vdata0[0] = i; cpu_relax();
  149         vdata1[0] = i; cpu_relax();
  150         vdata0[1] = i; cpu_relax();
  151         vdata1[1] = i; cpu_relax();
  152         vdata0[2] = i; cpu_relax();
  153         vdata1[2] = i; cpu_relax();
  154         vdata0[3] = i; cpu_relax();
  155         vdata1[3] = i; cpu_relax();
  156         vdata0[4] = i; cpu_relax();
  157         vdata1[4] = i; cpu_relax();
  158         vdata0[5] = i; cpu_relax();
  159         vdata1[5] = i; cpu_relax();
  160         vdata0[6] = i; cpu_relax();
  161         vdata1[6] = i; cpu_relax();
  162         vdata0[7] = i; cpu_relax();
  163         vdata1[7] = i; cpu_relax();
  164         read64(data0);
  165         read64(data1);
  166     }
  167 #endif
  168     for (i = 0; i < 1024; i++) {
  169         vdata0[0] = i; mem_barrier();
  170         vdata1[0] = i; mem_barrier();
  171         vdata0[1] = i; mem_barrier();
  172         vdata1[1] = i; mem_barrier();
  173         vdata0[2] = i; mem_barrier();
  174         vdata1[2] = i; mem_barrier();
  175         vdata0[3] = i; mem_barrier();
  176         vdata1[3] = i; mem_barrier();
  177         vdata0[4] = i; mem_barrier();
  178         vdata1[4] = i; mem_barrier();
  179         vdata0[5] = i; mem_barrier();
  180         vdata1[5] = i; mem_barrier();
  181         vdata0[6] = i; mem_barrier();
  182         vdata1[6] = i; mem_barrier();
  183         vdata0[7] = i; mem_barrier();
  184         vdata1[7] = i; mem_barrier();
  185         read64(data0);
  186         read64(data1);
  187     }
  188     (void)shim_cacheflush((void *)data0, 64, DCACHE);
  189     (void)shim_cacheflush((void *)data1, 64, DCACHE);
  190 }
  191 
  192 /*
  193  *  stress_memory_contend_thread
  194  */
  195 static void *stress_memory_contend_thread(void *arg)
  196 {
  197     static void *nowt = NULL;
  198     uint8_t stack[SIGSTKSZ + STACK_ALIGNMENT];
  199     const pthread_args_t *pa = (const pthread_args_t *)arg;
  200 #if defined(HAVE_AFFINITY)
  201     const uint32_t cpus = stress_get_processors_configured();
  202 #endif
  203 
  204     /*
  205      *  Block all signals, let controlling thread
  206      *  handle these
  207      */
  208     (void)sigprocmask(SIG_BLOCK, &set, NULL);
  209 
  210     /*
  211      *  According to POSIX.1 a thread should have
  212      *  a distinct alternative signal stack.
  213      *  However, we block signals in this thread
  214      *  so this is probably just totally unncessary.
  215      */
  216     (void)memset(stack, 0, sizeof(stack));
  217     if (stress_sigaltstack(stack, SIGSTKSZ) < 0)
  218         return &nowt;
  219 
  220     while (g_keep_stressing_flag) {
  221 #if defined(HAVE_AFFINITY)
  222         cpu_set_t mask;
  223 #endif
  224         stress_memory_contend(pa);
  225 
  226 #if defined(HAVE_AFFINITY)
  227         const uint32_t cpu = mwc32() % cpus;
  228 
  229         CPU_ZERO(&mask);
  230         CPU_SET(cpu, &mask);
  231         (void)sched_setaffinity(0, sizeof(mask), &mask);
  232 #endif
  233     }
  234     return &nowt;
  235 }
  236 
  237 /*
  238  *  stress_mcontend
  239  *  memory contention stress
  240  */
  241 static int stress_mcontend(const args_t *args)
  242 {
  243     size_t i;
  244     pthread_t pthreads[MAX_READ_THREADS];
  245     int ret[MAX_READ_THREADS];
  246     void *data[MAX_MAPPINGS];
  247     char filename[PATH_MAX];
  248     pthread_args_t pa;
  249     int fd, rc;
  250 
  251     rc = stress_temp_dir_mk_args(args);
  252     if (rc < 0)
  253         return exit_status(-rc);
  254     (void)stress_temp_filename_args(args,
  255         filename, sizeof(filename), mwc32());
  256 
  257     fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
  258     if (fd < 0) {
  259         pr_inf("%s: open failed: errno=%d (%s)\n",
  260             args->name, errno, strerror(errno));
  261         return EXIT_NO_RESOURCE;
  262     }
  263     (void)shim_fallocate(fd, 0, 0, args->page_size);
  264     (void)unlink(filename);
  265     (void)stress_temp_dir_rm_args(args);
  266 
  267     pa.args = args;
  268     /*
  269      *  Get two different mappings of the same physical page
  270      *  just to make things more interesting
  271      */
  272     data[0] = mmap(NULL, args->page_size, PROT_READ | PROT_WRITE,
  273             MAP_PRIVATE, fd, 0);
  274     if (data[0] == MAP_FAILED) {
  275         pr_inf("%s: mmap failed: errno=%d (%s)\n",
  276             args->name, errno, strerror(errno));
  277         (void)close(fd);
  278         return EXIT_NO_RESOURCE;
  279     }
  280     data[1] = mmap(NULL, args->page_size , PROT_READ | PROT_WRITE,
  281             MAP_PRIVATE, fd, 0);
  282     if (data[1] == MAP_FAILED) {
  283         pr_inf("%s: mmap failed: errno=%d (%s)\n",
  284             args->name, errno, strerror(errno));
  285         (void)munmap(data[1], args->page_size);
  286         (void)close(fd);
  287         return EXIT_NO_RESOURCE;
  288     }
  289     (void)close(fd);
  290     (void)shim_mlock(data[0], args->page_size);
  291     (void)shim_mlock(data[1], args->page_size);
  292 
  293     pa.data = data;
  294     for (i = 0; i < MAX_READ_THREADS; i++) {
  295         ret[i] = pthread_create(&pthreads[i], NULL,
  296                 stress_memory_contend_thread, &pa);
  297     }
  298 
  299     do {
  300         stress_memory_contend(&pa);
  301 #if defined(HAVE_MSYNC)
  302         (void)msync(data[0], args->page_size, MS_ASYNC);
  303         (void)msync(data[1], args->page_size, MS_ASYNC);
  304 #endif
  305         inc_counter(args);
  306     } while (keep_stressing());
  307 
  308     for (i = 0; i < MAX_READ_THREADS; i++) {
  309         if (ret[i] == 0)
  310             (void)pthread_join(pthreads[i], NULL);
  311     }
  312     (void)munmap(data[0], args->page_size);
  313     (void)munmap(data[1], args->page_size);
  314 
  315     return EXIT_SUCCESS;
  316 }
  317 
  318 stressor_info_t stress_mcontend_info = {
  319     .stressor = stress_mcontend,
  320     .class = CLASS_MEMORY
  321 };
  322 #else
  323 stressor_info_t stress_mcontend_info = {
  324     .stressor = stress_not_implemented,
  325     .class = CLASS_MEMORY
  326 };
  327 #endif