"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-sleep.c" (15 Mar 2019, 5433 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-sleep.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 #if defined(HAVE_LIB_PTHREAD)
   28 
   29 typedef struct {
   30     const args_t *args;
   31     uint64_t counter;
   32     uint64_t sleep_max;
   33     pthread_t pthread;
   34 } ctxt_t;
   35 
   36 static volatile bool thread_terminate;
   37 static sigset_t set;
   38 #endif
   39 
   40 int stress_set_sleep_max(const char *opt)
   41 {
   42     uint64_t sleep_max;
   43 
   44     sleep_max = get_uint64(opt);
   45     check_range("sleep-max", sleep_max,
   46         MIN_SLEEP, MAX_SLEEP);
   47     return set_setting("sleep-max", TYPE_ID_UINT64, &sleep_max);
   48 }
   49 
   50 #if defined(HAVE_LIB_PTHREAD)
   51 
   52 static void MLOCKED_TEXT stress_sigalrm_handler(int signum)
   53 {
   54         (void)signum;
   55 
   56         thread_terminate = true;
   57 }
   58 
   59 /*
   60  *  stress_pthread_func()
   61  *  pthread that performs different ranges of sleeps
   62  */
   63 static void *stress_pthread_func(void *c)
   64 {
   65     uint8_t stack[SIGSTKSZ + STACK_ALIGNMENT];
   66     static void *nowt = NULL;
   67     ctxt_t *ctxt = (ctxt_t *)c;
   68     const args_t *args = ctxt->args;
   69     const uint64_t max_ops = 
   70         args->max_ops ? (args->max_ops / ctxt->sleep_max) + 1 : 0;
   71     /*
   72      *  According to POSIX.1 a thread should have
   73      *  a distinct alternative signal stack.
   74      *  However, we block signals in this thread
   75      *  so this is probably just totally unncessary.
   76      */
   77     (void)memset(stack, 0, sizeof(stack));
   78     if (stress_sigaltstack(stack, SIGSTKSZ) < 0)
   79         goto die;
   80 
   81     while (keep_stressing() && 
   82            !thread_terminate &&
   83                (!max_ops || ctxt->counter < max_ops)) {
   84         struct timespec tv;
   85 #if defined(HAVE_SYS_SELECT_H)
   86         struct timeval timeout;
   87 #endif
   88 
   89         tv.tv_sec = 0;
   90         tv.tv_nsec = 1;
   91         if (nanosleep(&tv, NULL) < 0)
   92             break;
   93         tv.tv_sec = 0;
   94         tv.tv_nsec = 10;
   95         if (nanosleep(&tv, NULL) < 0)
   96             break;
   97         tv.tv_sec = 0;
   98         tv.tv_nsec = 100;
   99         if (nanosleep(&tv, NULL) < 0)
  100             break;
  101         if (shim_usleep(1) < 0)
  102             break;
  103         if (shim_usleep(10) < 0)
  104             break;
  105         if (shim_usleep(100) < 0)
  106             break;
  107         if (shim_usleep(1000) < 0)
  108             break;
  109         if (shim_usleep(10000) < 0)
  110             break;
  111 
  112 #if defined(HAVE_SYS_SELECT_H)
  113         timeout.tv_sec = 0;
  114         timeout.tv_usec = 10;
  115         if (select(0, NULL, NULL, NULL, &timeout) < 0)
  116             break;
  117         timeout.tv_sec = 0;
  118         timeout.tv_usec = 100;
  119         if (select(0, NULL, NULL, NULL, &timeout) < 0)
  120             break;
  121         timeout.tv_sec = 0;
  122         timeout.tv_usec = 1000;
  123         if (select(0, NULL, NULL, NULL, &timeout) < 0)
  124             break;
  125         timeout.tv_sec = 0;
  126         timeout.tv_usec = 10000;
  127         if (select(0, NULL, NULL, NULL, &timeout) < 0)
  128             break;
  129 #endif
  130 
  131         ctxt->counter++;
  132     }
  133 die:
  134     return &nowt;
  135 }
  136 
  137 /*
  138  *  stress_sleep()
  139  *  stress by many sleeping threads
  140  */
  141 static int stress_sleep(const args_t *args)
  142 {
  143     uint64_t i, n, limited = 0;
  144     uint64_t sleep_max = DEFAULT_SLEEP;
  145     ctxt_t    ctxts[MAX_SLEEP];
  146     int ret = EXIT_SUCCESS;
  147 
  148     if (!get_setting("sleep-max", &sleep_max)) {
  149         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  150             sleep_max = MAX_SLEEP;
  151         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  152             sleep_max = MIN_SLEEP;
  153     }
  154 
  155     if (stress_sighandler(args->name, SIGALRM, stress_sigalrm_handler, NULL) < 0)
  156         return EXIT_FAILURE;
  157 
  158     (void)memset(ctxts, 0, sizeof(ctxts));
  159     (void)sigfillset(&set);
  160 
  161     for (n = 0; n < sleep_max;  n++) {
  162         ctxts[n].args = args;
  163         ctxts[n].sleep_max = sleep_max;
  164         ret = pthread_create(&ctxts[n].pthread, NULL,
  165             stress_pthread_func, &ctxts[n]);
  166         if (ret) {
  167             /* Out of resources, don't try any more */
  168             if (ret == EAGAIN) {
  169                 limited++;
  170                 break;
  171             }
  172             /* Something really unexpected */
  173             pr_fail_errno("pthread create", ret);
  174             ret = EXIT_NO_RESOURCE;
  175             goto tidy;
  176         }
  177         /* Timed out? abort! */
  178         if (!g_keep_stressing_flag)
  179             goto tidy;
  180     }
  181 
  182     do {
  183         set_counter(args, 0);
  184         (void)shim_usleep_interruptible(10000);
  185         for (i = 0; i < n; i++)
  186             add_counter(args, ctxts[i].counter);
  187     }  while (!thread_terminate && keep_stressing());
  188 
  189     ret = EXIT_SUCCESS;
  190 tidy:
  191     thread_terminate = true;
  192     for (i = 0; i < n; i++) {
  193         ret = pthread_join(ctxts[i].pthread, NULL);
  194         (void)ret;
  195         /*
  196         if (ret)
  197             pr_dbg("%s: pthread join, ret=%d\n", args->name, ret);
  198         */
  199     }
  200 
  201     if (limited) {
  202         pr_inf("%s: %.2f%% of iterations could not reach "
  203             "requested %" PRIu64 " threads (instance %"
  204             PRIu32 ")\n",
  205             args->name,
  206             100.0 * (double)limited / (double)sleep_max,
  207             sleep_max, args->instance);
  208     }
  209 
  210     return ret;
  211 }
  212 
  213 stressor_info_t stress_sleep_info = {
  214     .stressor = stress_sleep,
  215     .class = CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS
  216 };
  217 #else
  218 stressor_info_t stress_sleep_info = {
  219     .stressor = stress_not_implemented,
  220     .class = CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS
  221 };
  222 #endif