"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-memcpy.c" (15 Mar 2019, 6997 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-memcpy.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.54_vs_0.09.55.

    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 #define ALIGN_SIZE  (64)
   28 
   29 typedef struct {
   30     uint8_t buffer[STR_SHARED_SIZE + ALIGN_SIZE];
   31 } buffer_t;
   32 
   33 typedef void (*stress_memcpy_func)(buffer_t *b, uint8_t *b_str, uint8_t *str_shared, uint8_t *aligned_buf);
   34 
   35 typedef struct {
   36         const char *name;
   37         const stress_memcpy_func func;
   38 } stress_memcpy_method_info_t;
   39 
   40 static NOINLINE void *__memcpy(void *dest, const void *src, size_t n)
   41 {
   42     return memcpy(dest, src, n);
   43 }
   44 
   45 static NOINLINE void *__memmove(void *dest, const void *src, size_t n)
   46 {
   47     return memmove(dest, src, n);
   48 }
   49 
   50 static inline void *__naive_memcpy(void *dest, const void *src, size_t n)
   51 {
   52     register size_t i;
   53     register char *cdest = (char *)dest;
   54     register const char *csrc = (const char *)src;
   55 
   56     for (i = 0; i < n; i++)
   57         *(cdest++) = *(csrc++);
   58     return dest;
   59 }
   60 
   61 static inline void *__naive_memmove(void *dest, const void *src, size_t n)
   62 {
   63     register size_t i;
   64     register char *cdest = (char *)dest;
   65     register const char *csrc = (const char *)src;
   66 
   67     if (dest < src) {
   68         for (i = 0; i < n; i++)
   69             *(cdest++) = *(csrc++);
   70     } else {
   71         csrc += n;
   72         cdest += n;
   73 
   74         for (i = 0; i < n; i++)
   75             *(--cdest) = *(--csrc);
   76     }
   77     return dest;
   78 }
   79 
   80 static NOINLINE void stress_memcpy_libc(
   81     buffer_t *b,
   82     uint8_t *b_str,
   83     uint8_t *str_shared,
   84     uint8_t *aligned_buf)
   85 {
   86     (void)__memcpy(aligned_buf, str_shared, STR_SHARED_SIZE);
   87     (void)__memcpy(str_shared, aligned_buf, STR_SHARED_SIZE / 2);
   88     (void)__memmove(aligned_buf, aligned_buf + 64, STR_SHARED_SIZE - 64);
   89     (void)__memcpy(b_str, b, STR_SHARED_SIZE);
   90     (void)__memmove(aligned_buf + 64, aligned_buf, STR_SHARED_SIZE - 64);
   91     (void)__memcpy(b, b_str, STR_SHARED_SIZE);
   92     (void)__memmove(aligned_buf + 1, aligned_buf, STR_SHARED_SIZE - 1);
   93     (void)__memmove(aligned_buf, aligned_buf + 1, STR_SHARED_SIZE - 1);
   94 }
   95 
   96 static NOINLINE void stress_memcpy_builtin(
   97     buffer_t *b,
   98     uint8_t *b_str,
   99     uint8_t *str_shared,
  100     uint8_t *aligned_buf)
  101 {
  102 #if defined(HAVE_BUILTIN_MEMCPY) && \
  103     defined(HAVE_BUILTIN_MEMMOVE)
  104     (void)__builtin_memcpy(aligned_buf, str_shared, STR_SHARED_SIZE);
  105     (void)__builtin_memcpy(str_shared, aligned_buf, STR_SHARED_SIZE / 2);
  106     (void)__builtin_memmove(aligned_buf, aligned_buf + 64, STR_SHARED_SIZE - 64);
  107     (void)__builtin_memcpy(b_str, b, STR_SHARED_SIZE);
  108     (void)__builtin_memmove(aligned_buf + 64, aligned_buf, STR_SHARED_SIZE - 64);
  109     (void)__builtin_memcpy(b, b_str, STR_SHARED_SIZE);
  110     (void)__builtin_memmove(aligned_buf + 1, aligned_buf, STR_SHARED_SIZE - 1);
  111     (void)__builtin_memmove(aligned_buf, aligned_buf + 1, STR_SHARED_SIZE - 1);
  112 #else
  113     /*
  114      *  Compiler may fall back to turning these into inline'd
  115      *  optimized versions even if there are no explicit built-in
  116      *  versions, so use these.
  117      */
  118     (void)memcpy(aligned_buf, str_shared, STR_SHARED_SIZE);
  119     (void)memcpy(str_shared, aligned_buf, STR_SHARED_SIZE / 2);
  120     (void)memmove(aligned_buf, aligned_buf + 64, STR_SHARED_SIZE - 64);
  121     (void)memcpy(b_str, b, STR_SHARED_SIZE);
  122     (void)memmove(aligned_buf + 64, aligned_buf, STR_SHARED_SIZE - 64);
  123     (void)memcpy(b, b_str, STR_SHARED_SIZE);
  124     (void)memmove(aligned_buf + 1, aligned_buf, STR_SHARED_SIZE - 1);
  125     (void)memmove(aligned_buf, aligned_buf + 1, STR_SHARED_SIZE - 1);
  126 #endif
  127 }
  128 
  129 static NOINLINE void stress_memcpy_naive(
  130     buffer_t *b,
  131     uint8_t *b_str,
  132     uint8_t *str_shared,
  133     uint8_t *aligned_buf)
  134 {
  135     (void)__naive_memcpy(aligned_buf, str_shared, STR_SHARED_SIZE);
  136     (void)__naive_memcpy(str_shared, aligned_buf, STR_SHARED_SIZE / 2);
  137     (void)__naive_memmove(aligned_buf, aligned_buf + 64, STR_SHARED_SIZE - 64);
  138     (void)__naive_memcpy(b_str, b, STR_SHARED_SIZE);
  139     (void)__naive_memmove(aligned_buf + 64, aligned_buf, STR_SHARED_SIZE - 64);
  140     (void)__naive_memcpy(b, b_str, STR_SHARED_SIZE);
  141     (void)__naive_memmove(aligned_buf + 1, aligned_buf, STR_SHARED_SIZE - 1);
  142     (void)__naive_memmove(aligned_buf, aligned_buf + 1, STR_SHARED_SIZE - 1);
  143 }
  144 
  145 static NOINLINE void stress_memcpy_all(
  146     buffer_t *b,
  147     uint8_t *b_str,
  148     uint8_t *str_shared,
  149     uint8_t *aligned_buf)
  150 {
  151     static int whence;
  152 
  153     switch (whence) {
  154     case 0:
  155         whence++;
  156         stress_memcpy_libc(b, b_str, str_shared, aligned_buf);
  157         return;
  158     case 1:
  159         whence++;
  160         stress_memcpy_builtin(b, b_str, str_shared, aligned_buf);
  161         return;
  162     default:
  163         whence = 0;
  164         stress_memcpy_naive(b, b_str, str_shared, aligned_buf);
  165         return;
  166     }
  167 }
  168 
  169 static const stress_memcpy_method_info_t stress_memcpy_methods[] = {
  170     { "all",    stress_memcpy_all },
  171         { "libc",   stress_memcpy_libc },
  172         { "builtin",    stress_memcpy_builtin },
  173         { "naive",      stress_memcpy_naive },
  174         { NULL,         NULL }
  175 };
  176 
  177 /*
  178  *  stress_set_memcpy_method()
  179  *      set default memcpy stress method
  180  */
  181 int stress_set_memcpy_method(const char *name)
  182 {
  183     stress_memcpy_method_info_t const *info;
  184 
  185     for (info = stress_memcpy_methods; info->func; info++) {
  186         if (!strcmp(info->name, name)) {
  187             set_setting("memcpy-method", TYPE_ID_UINTPTR_T, &info);
  188             return 0;
  189         }
  190     }
  191 
  192     (void)fprintf(stderr, "memcpy-method must be one of:");
  193     for (info = stress_memcpy_methods; info->func; info++) {
  194         (void)fprintf(stderr, " %s", info->name);
  195     }
  196     (void)fprintf(stderr, "\n");
  197 
  198     return -1;
  199 }
  200 
  201 static void stress_memcpy_set_default(void)
  202 {
  203         stress_set_memcpy_method("libc");
  204 }
  205 
  206 /*
  207  *  stress_memcpy()
  208  *  stress memory copies
  209  */
  210 static int stress_memcpy(const args_t *args)
  211 {
  212     static buffer_t b;
  213     uint8_t *b_str = g_shared->str_shared;
  214     uint8_t *str_shared = g_shared->str_shared;
  215     uint8_t *aligned_buf = stress_align_address(b.buffer, ALIGN_SIZE);
  216     const stress_memcpy_method_info_t *memcpy_method = &stress_memcpy_methods[1];
  217 
  218     (void)get_setting("memcpy-method", &memcpy_method);
  219 
  220     stress_strnrnd((char *)aligned_buf, ALIGN_SIZE);
  221 
  222     do {
  223         memcpy_method->func(&b, b_str, str_shared, aligned_buf);
  224         inc_counter(args);
  225     } while (keep_stressing());
  226 
  227     return EXIT_SUCCESS;
  228 }
  229 
  230 stressor_info_t stress_memcpy_info = {
  231     .stressor = stress_memcpy,
  232     .set_default = stress_memcpy_set_default,
  233     .class = CLASS_CPU_CACHE | CLASS_MEMORY
  234 };