"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.13.05/stress-context.c" (11 Oct 2021, 5208 Bytes) of package /linux/privat/stress-ng-0.13.05.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-context.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.13.04_vs_0.13.05.

    1 /*
    2  * Copyright (C) 2013-2021 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 static stress_help_t help[] = {
   28     { NULL, "context N",     "start N workers exercising user context" },
   29     { NULL, "context-ops N", "stop context workers after N bogo operations" },
   30     { NULL, NULL,        NULL }
   31 };
   32 
   33 #if defined(HAVE_SWAPCONTEXT) &&    \
   34     defined(HAVE_UCONTEXT_H)
   35 
   36 #define CONTEXT_STACK_SIZE  (16384)
   37 
   38 typedef struct {
   39     uint32_t check0;    /* memory clobbering check canary */
   40     ucontext_t uctx;    /* swapcontext context */
   41     uint32_t check1;    /* memory clobbering check canary */
   42 } chk_ucontext_t;
   43 
   44 typedef struct {
   45     uint32_t check0;    /* copy of original check1 canary */
   46     uint32_t check1;    /* copy of original check1 canary */
   47 } chk_canary_t;
   48 
   49 typedef struct {
   50     chk_ucontext_t  cu; /* check ucontext */
   51     uint8_t     stack[CONTEXT_STACK_SIZE + STACK_ALIGNMENT]; /* stack */
   52     chk_canary_t    canary; /* copy of canary */
   53 } context_info_t;
   54 
   55 static context_info_t context[3];
   56 static ucontext_t uctx_main;
   57 static uint64_t context_counter;
   58 static uint64_t stress_max_ops;
   59 
   60 static void thread1(void)
   61 {
   62     do {
   63         context_counter++;
   64         (void)swapcontext(&context[0].cu.uctx, &context[1].cu.uctx);
   65     } while (keep_stressing_flag() && (!stress_max_ops || (context_counter < stress_max_ops)));
   66     (void)swapcontext(&context[0].cu.uctx, &uctx_main);
   67 }
   68 
   69 static void thread2(void)
   70 {
   71     do {
   72         context_counter++;
   73         (void)swapcontext(&context[1].cu.uctx, &context[2].cu.uctx);
   74     } while (keep_stressing_flag() && (!stress_max_ops || (context_counter < stress_max_ops)));
   75     (void)swapcontext(&context[1].cu.uctx, &uctx_main);
   76 }
   77 
   78 static void thread3(void)
   79 {
   80     do {
   81         context_counter++;
   82         (void)swapcontext(&context[2].cu.uctx, &context[0].cu.uctx);
   83     } while (keep_stressing_flag() && (!stress_max_ops || (context_counter < stress_max_ops)));
   84     (void)swapcontext(&context[2].cu.uctx, &uctx_main);
   85 }
   86 
   87 static int stress_context_init(
   88     const stress_args_t *args,
   89     void (*func)(void),
   90     ucontext_t *uctx_link,
   91     context_info_t *context_info)
   92 {
   93     (void)memset(context_info, 0, sizeof(*context_info));
   94 
   95     if (getcontext(&context_info->cu.uctx) < 0) {
   96         pr_err("%s: getcontext failed: %d (%s)\n",
   97             args->name, errno, strerror(errno));
   98         return -1;
   99     }
  100 
  101     context_info->canary.check0 = stress_mwc32();
  102     context_info->canary.check1 = stress_mwc32();
  103 
  104     context_info->cu.check0 = context_info->canary.check0;
  105     context_info->cu.check1 = context_info->canary.check1;
  106     context_info->cu.uctx.uc_stack.ss_sp =
  107         (void *)stress_align_address(context_info->stack, STACK_ALIGNMENT);
  108     context_info->cu.uctx.uc_stack.ss_size = CONTEXT_STACK_SIZE;
  109     context_info->cu.uctx.uc_link = uctx_link;
  110     makecontext(&context_info->cu.uctx, func, 0);
  111 
  112     return 0;
  113 }
  114 
  115 /*
  116  *  stress_context()
  117  *  stress that exercises CPU context save/restore
  118  */
  119 static int stress_context(const stress_args_t *args)
  120 {
  121     size_t i;
  122 
  123     (void)memset(&uctx_main, 0, sizeof(uctx_main));
  124 
  125     context_counter = 0;
  126     stress_max_ops = args->max_ops * 1000;
  127 
  128     /* Create 3 micro threads */
  129     if (stress_context_init(args, thread1, &uctx_main, &context[0]) < 0)
  130         return EXIT_FAILURE;
  131     if (stress_context_init(args, thread2, &uctx_main, &context[1]) < 0)
  132         return EXIT_FAILURE;
  133     if (stress_context_init(args, thread3, &uctx_main, &context[2]) < 0)
  134         return EXIT_FAILURE;
  135 
  136     /* And start.. */
  137     if (swapcontext(&uctx_main, &context[0].cu.uctx) < 0) {
  138         pr_err("%s: swapcontext failed: %d (%s)\n",
  139             args->name, errno, strerror(errno));
  140         return EXIT_FAILURE;
  141     }
  142 
  143     set_counter(args, context_counter / 1000);
  144 
  145     stress_set_proc_state(args->name, STRESS_STATE_RUN);
  146 
  147     for (i = 0; i < SIZEOF_ARRAY(context); i++) {
  148         if (context[i].canary.check0 != context[i].cu.check0) {
  149             pr_fail("%s: swapcontext clobbered data before context region\n",
  150                 args->name);
  151         }
  152         if (context[i].canary.check1 != context[i].cu.check1) {
  153             pr_fail("%s: swapcontext clobbered data after context region\n",
  154                 args->name);
  155         }
  156     }
  157     stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
  158 
  159     return EXIT_SUCCESS;
  160 }
  161 
  162 stressor_info_t stress_context_info = {
  163     .stressor = stress_context,
  164     .class = CLASS_MEMORY | CLASS_CPU,
  165     .help = help
  166 };
  167 #else
  168 stressor_info_t stress_context_info = {
  169     .stressor = stress_not_implemented,
  170     .class = CLASS_MEMORY | CLASS_CPU,
  171     .help = help
  172 };
  173 #endif