"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-cache.c" (15 Mar 2019, 5128 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-cache.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 /* The compiler optimises out the unused cache flush and mfence calls */
   28 #define CACHE_WRITE(flag)                       \
   29     for (j = 0; j < mem_cache_size; j++) {              \
   30         if ((flag) & OPT_FLAGS_CACHE_PREFETCH) {        \
   31             __builtin_prefetch(&mem_cache[i + 1], 1, 1);    \
   32         }                           \
   33         mem_cache[i] += mem_cache[(mem_cache_size - 1) - i] + r;\
   34         if ((flag) & OPT_FLAGS_CACHE_FLUSH) {           \
   35             clflush(&mem_cache[i]);             \
   36         }                           \
   37         if ((flag) & OPT_FLAGS_CACHE_FENCE) {           \
   38             mfence();                   \
   39         }                           \
   40         i = (i + 32769) & (mem_cache_size - 1);         \
   41         if (!g_keep_stressing_flag)             \
   42             break;                      \
   43     }
   44 
   45 /*
   46  *  stress_cache()
   47  *  stress cache by psuedo-random memory read/writes and
   48  *  if possible change CPU affinity to try to cause
   49  *  poor cache behaviour
   50  */
   51 static int stress_cache(const args_t *args)
   52 {
   53 #if defined(HAVE_SCHED_GETAFFINITY) &&  \
   54     defined(HAVE_SCHED_GETCPU)
   55     cpu_set_t mask;
   56     uint32_t cpu = 0;
   57     const uint32_t cpus = stress_get_processors_configured();
   58     cpu_set_t proc_mask;
   59     bool pinned = false;
   60 #endif
   61     uint32_t total = 0;
   62     int ret = EXIT_SUCCESS;
   63     uint8_t *const mem_cache = g_shared->mem_cache;
   64     const uint64_t mem_cache_size = g_shared->mem_cache_size;
   65 
   66     if (args->instance == 0)
   67         pr_dbg("%s: using cache buffer size of %" PRIu64 "K\n",
   68             args->name, mem_cache_size / 1024);
   69 
   70 #if defined(HAVE_SCHED_GETAFFINITY) &&  \
   71     defined(HAVE_SCHED_GETCPU)
   72     if (sched_getaffinity(0, sizeof(proc_mask), &proc_mask) < 0)
   73         pinned = true;
   74     else
   75         if (!CPU_COUNT(&proc_mask))
   76             pinned = true;
   77 
   78     if (pinned) {
   79         pr_inf("%s: can't get sched affinity, pinning to "
   80             "CPU %d (instance %" PRIu32 ")\n",
   81             args->name, sched_getcpu(), pinned);
   82     }
   83 #endif
   84 
   85     do {
   86         uint64_t i = mwc64() % mem_cache_size;
   87         uint64_t r = mwc64();
   88         register uint64_t j;
   89 
   90         if ((r >> 13) & 1) {
   91             switch (g_opt_flags & OPT_FLAGS_CACHE_MASK) {
   92             case OPT_FLAGS_CACHE_FLUSH:
   93                 CACHE_WRITE(OPT_FLAGS_CACHE_FLUSH);
   94                 break;
   95             case OPT_FLAGS_CACHE_FENCE:
   96                 CACHE_WRITE(OPT_FLAGS_CACHE_FENCE);
   97                 break;
   98             case OPT_FLAGS_CACHE_FENCE | OPT_FLAGS_CACHE_FLUSH:
   99                 CACHE_WRITE(OPT_FLAGS_CACHE_FLUSH |
  100                         OPT_FLAGS_CACHE_FENCE);
  101                 break;
  102             case OPT_FLAGS_CACHE_PREFETCH:
  103                 CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH);
  104                 break;
  105             case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FLUSH:
  106                 CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH |
  107                         OPT_FLAGS_CACHE_FLUSH);
  108                 break;
  109             case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FENCE:
  110                 CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH |
  111                         OPT_FLAGS_CACHE_FENCE);
  112                 break;
  113             case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FLUSH |
  114                  OPT_FLAGS_CACHE_FENCE:
  115                 CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH |
  116                         OPT_FLAGS_CACHE_FLUSH |
  117                         OPT_FLAGS_CACHE_FENCE);
  118                 break;
  119             default:
  120                 CACHE_WRITE(0);
  121                 break;
  122             }
  123         } else {
  124             for (j = 0; j < mem_cache_size; j++) {
  125                 total += mem_cache[i] +
  126                     mem_cache[(mem_cache_size - 1) - i];
  127                 i = (i + 32769) % mem_cache_size;
  128                 if (!g_keep_stressing_flag)
  129                     break;
  130             }
  131         }
  132 #if defined(HAVE_SCHED_GETAFFINITY) &&  \
  133     defined(HAVE_SCHED_GETCPU)
  134         if ((g_opt_flags & OPT_FLAGS_CACHE_NOAFF) && !pinned) {
  135             int current;
  136 
  137             /* Pin to the current CPU */
  138             current = sched_getcpu();
  139             if (current < 0)
  140                 return EXIT_FAILURE;
  141 
  142             cpu = (int32_t)current;
  143         } else {
  144             do {
  145                 cpu = (g_opt_flags & OPT_FLAGS_AFFINITY_RAND) ?
  146                     (mwc32() >> 4) : cpu + 1;
  147                 cpu %= cpus;
  148             } while (!(CPU_ISSET(cpu, &proc_mask)));
  149         }
  150 
  151         if (!(g_opt_flags & OPT_FLAGS_CACHE_NOAFF) || !pinned) {
  152             CPU_ZERO(&mask);
  153             CPU_SET(cpu, &mask);
  154             (void)sched_setaffinity(0, sizeof(mask), &mask);
  155 
  156             if ((g_opt_flags & OPT_FLAGS_CACHE_NOAFF)) {
  157                 /* Don't continually set the affinity */
  158                 pinned = true;
  159             }
  160 
  161         }
  162 #endif
  163         (void)shim_cacheflush((char *)stress_cache, 8192, ICACHE);
  164         (void)shim_cacheflush((char *)mem_cache, (int)mem_cache_size, DCACHE);
  165         inc_counter(args);
  166     } while (keep_stressing());
  167 
  168     pr_dbg("%s: total [%" PRIu32 "]\n", args->name, total);
  169     return ret;
  170 }
  171 
  172 stressor_info_t stress_cache_info = {
  173     .stressor = stress_cache,
  174     .class = CLASS_CPU_CACHE
  175 };