"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-helper.c" (15 Mar 2019, 30989 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 "core-helper.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) 2014-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(PR_SET_DISABLE)
   28 #define SUID_DUMP_DISABLE   (0)       /* No setuid dumping */
   29 #endif
   30 #if !defined(SUID_DUMP_USER)
   31 #define SUID_DUMP_USER      (1)       /* Dump as user of process */
   32 #endif
   33 
   34 #if defined(HAVE_PRCTL_TIMER_SLACK)
   35 static unsigned long timer_slack = 0;
   36 #endif
   37 
   38 #if defined(NSIG)
   39 #define STRESS_NSIG NSIG
   40 #elif defined(_NSIG)
   41 #define STRESS_NSIG _NSIG
   42 #endif
   43 
   44 #if defined(__TINYC__)
   45 int __dso_handle;
   46 #endif
   47 
   48 static const char *stress_temp_path = ".";
   49 
   50 /*
   51  *  stress_get_pagesize()
   52  *  get pagesize
   53  */
   54 size_t stress_get_pagesize(void)
   55 {
   56     static size_t page_size = 0;
   57 
   58     /* Use cached size */
   59     if (page_size > 0)
   60         return page_size;
   61 
   62 #if defined(_SC_PAGESIZE)
   63     {
   64         /* Use modern sysconf */
   65         long sz = sysconf(_SC_PAGESIZE);
   66         if (sz > 0) {
   67             page_size = (size_t)sz;
   68             return page_size;
   69         }
   70     }
   71 #endif
   72 #if defined(HAVE_GETPAGESIZE)
   73     {
   74         /* Use deprecated getpagesize */
   75         long sz = getpagesize();
   76         if (sz > 0) {
   77             page_size = (size_t)sz;
   78             return page_size;
   79         }
   80     }
   81 #endif
   82     /* Guess */
   83     page_size = PAGE_4K;
   84     return page_size;
   85 }
   86 
   87 /*
   88  *  stress_get_processors_online()
   89  *  get number of processors that are online
   90  */
   91 int32_t stress_get_processors_online(void)
   92 {
   93     static int32_t processors_online = 0;
   94 
   95     if (processors_online > 0)
   96         return processors_online;
   97 
   98 #if defined(_SC_NPROCESSORS_ONLN)
   99     processors_online = (int32_t)sysconf(_SC_NPROCESSORS_ONLN);
  100     if (processors_online < 0)
  101         processors_online = 1;
  102 #else
  103     processors_online = 1;
  104 #endif
  105     return processors_online;
  106 }
  107 
  108 /*
  109  *  stress_get_processors_configured()
  110  *  get number of processors that are configured
  111  */
  112 int32_t stress_get_processors_configured(void)
  113 {
  114     static int32_t processors_configured = 0;
  115 
  116     if (processors_configured > 0)
  117         return processors_configured;
  118 
  119 #if defined(_SC_NPROCESSORS_CONF)
  120     processors_configured = (int32_t)sysconf(_SC_NPROCESSORS_CONF);
  121     if (processors_configured < 0)
  122         processors_configured = stress_get_processors_online();
  123 #else
  124     processors_configured = 1;
  125 #endif
  126     return processors_configured;
  127 }
  128 
  129 /*
  130  *  stress_get_ticks_per_second()
  131  *  get number of ticks perf second
  132  */
  133 int32_t stress_get_ticks_per_second(void)
  134 {
  135 #if defined(_SC_CLK_TCK)
  136     static uint32_t ticks_per_second = 0;
  137 
  138     if (ticks_per_second > 0)
  139         return ticks_per_second;
  140 
  141     ticks_per_second = sysconf(_SC_CLK_TCK);
  142     return ticks_per_second;
  143 #else
  144     return -1;
  145 #endif
  146 }
  147 
  148 /*
  149  *  stress_get_memlimits()
  150  *  get SHMALL and memory in system
  151  *  these are set to zero on failure
  152  */
  153 void stress_get_memlimits(
  154     size_t *shmall,
  155     size_t *freemem,
  156     size_t *totalmem,
  157     size_t *freeswap)
  158 {
  159 #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  160     struct sysinfo info;
  161     FILE *fp;
  162 #endif
  163     *shmall = 0;
  164     *freemem = 0;
  165     *totalmem = 0;
  166     *freeswap = 0;
  167 
  168 #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  169     if (sysinfo(&info) == 0) {
  170         *freemem = info.freeram * info.mem_unit;
  171         *totalmem = info.totalram * info.mem_unit;
  172         *freeswap = info.freeswap * info.mem_unit;
  173     }
  174 
  175     fp = fopen("/proc/sys/kernel/shmall", "r");
  176     if (!fp)
  177         return;
  178 
  179     if (fscanf(fp, "%zu", shmall) != 1) {
  180         (void)fclose(fp);
  181         return;
  182     }
  183     (void)fclose(fp);
  184 #endif
  185 }
  186 
  187 #if defined(_SC_AVPHYS_PAGES)
  188 #define STRESS_SC_PAGES _SC_AVPHYS_PAGES
  189 #elif defined(_SC_PHYS_PAGES)
  190 #define STRESS_SC_PAGES _SC_PHYS_PAGES
  191 #endif
  192 
  193 /*
  194  *  stress_get_phys_mem_size()
  195  *  get size of physical memory still available, 0 if failed
  196  */
  197 uint64_t stress_get_phys_mem_size(void)
  198 {
  199 #if defined(STRESS_SC_PAGES)
  200     uint64_t phys_pages = 0;
  201     const size_t page_size = stress_get_pagesize();
  202     const uint64_t max_pages = ~0ULL / page_size;
  203 
  204     phys_pages = sysconf(STRESS_SC_PAGES);
  205     /* Avoid overflow */
  206     if (phys_pages > max_pages)
  207         phys_pages = max_pages;
  208     return phys_pages * page_size;
  209 #else
  210     return 0ULL;
  211 #endif
  212 }
  213 
  214 /*
  215  *  stress_get_filesystem_size()
  216  *  get size of free space still available on the
  217  *  file system where stress temporary path is located,
  218  *  return 0 if failed
  219  */
  220 uint64_t stress_get_filesystem_size(void)
  221 {
  222 #if defined(HAVE_SYS_STATVFS_H)
  223     int rc;
  224     struct statvfs buf;
  225     fsblkcnt_t blocks, max_blocks;
  226 
  227     if (!stress_temp_path)
  228         return 0;
  229 
  230     rc = statvfs(stress_temp_path, &buf);
  231     if (rc < 0)
  232         return 0;
  233 
  234     max_blocks = (~(fsblkcnt_t)0) / buf.f_bsize;
  235     blocks = buf.f_bavail;
  236 
  237     if (blocks > max_blocks)
  238         blocks = max_blocks;
  239 
  240     return (uint64_t)buf.f_bsize * blocks;
  241 #else
  242     return 0ULL;
  243 #endif
  244 }
  245 
  246 /*
  247  *  stress_get_filesystem_available_inodes()
  248  *  get number of free available inodes on the current stress
  249  *  temporary path, return 0 if failed
  250  */
  251 uint64_t stress_get_filesystem_available_inodes(void)
  252 {
  253 #if defined(HAVE_SYS_STATVFS_H)
  254     int rc;
  255     struct statvfs buf;
  256 
  257     if (!stress_temp_path)
  258         return 0;
  259 
  260     rc = statvfs(stress_temp_path, &buf);
  261     if (rc < 0)
  262         return 0;
  263 
  264     return (uint64_t)buf.f_favail;
  265 #else
  266     return 0ULL;
  267 #endif
  268 }
  269 
  270 /*
  271  *  stress_set_nonblock()
  272  *  try to make fd non-blocking
  273  */
  274 int stress_set_nonblock(const int fd)
  275 {
  276     int flags;
  277 #if defined(O_NONBLOCK)
  278 
  279     if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
  280         flags = 0;
  281     return fcntl(fd, F_SETFL, O_NONBLOCK | flags);
  282 #else
  283     flags = 1;
  284     return ioctl(fd, FIOBIO, &flags);
  285 #endif
  286 }
  287 
  288 
  289 /*
  290  *  stress_get_load_avg()
  291  *  get load average
  292  */
  293 int stress_get_load_avg(
  294     double *min1,
  295     double *min5,
  296     double *min15)
  297 {
  298 #if NEED_GLIBC(2, 2, 0) && !defined(__UCLIBC__)
  299     int rc;
  300     double loadavg[3];
  301 
  302     rc = getloadavg(loadavg, 3);
  303     if (rc < 0)
  304         goto fail;
  305 
  306     *min1 = loadavg[0];
  307     *min5 = loadavg[1];
  308     *min15 = loadavg[2];
  309 
  310     return 0;
  311 fail:
  312 #elif defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  313     struct sysinfo info;
  314     const double scale = 1.0 / (double)(1 << SI_LOAD_SHIFT);
  315 
  316     if (sysinfo(&info) < 0)
  317         goto fail;
  318 
  319     *min1 = info.loads[0] * scale;
  320     *min5 = info.loads[1] * scale;
  321     *min15 = info.loads[2] * scale;
  322 
  323     return 0;
  324 fail:
  325 #endif
  326     *min1 = *min5 = *min15 = 0.0;
  327     return -1;
  328 }
  329 
  330 /*
  331  *  stress_parent_died_alarm()
  332  *  send child SIGALRM if the parent died
  333  */
  334 void stress_parent_died_alarm(void)
  335 {
  336 #if defined(HAVE_PRCTL) &&      \
  337     defined(HAVE_SYS_PRCTL_H) &&    \
  338     defined(PR_SET_PDEATHSIG)
  339     (void)prctl(PR_SET_PDEATHSIG, SIGALRM);
  340 #endif
  341 }
  342 
  343 /*
  344  *  stress_process_dumpable()
  345  *  set dumpable flag, e.g. produce a core dump or not,
  346  *  don't print an error if these fail, it's not that
  347  *  critical
  348  */
  349 int stress_process_dumpable(const bool dumpable)
  350 {
  351     int fd, rc = 0;
  352 
  353 #if defined(RLIMIT_CORE)
  354     {
  355         struct rlimit lim;
  356         int ret;
  357 
  358         ret = getrlimit(RLIMIT_CORE, &lim);
  359         if (ret == 0) {
  360             lim.rlim_cur = 0;
  361             (void)setrlimit(RLIMIT_CORE, &lim);
  362         }
  363         lim.rlim_cur = 0;
  364         lim.rlim_max = 0;
  365         (void)setrlimit(RLIMIT_CORE, &lim);
  366     }
  367 #endif
  368 
  369     /*
  370      *  changing PR_SET_DUMPABLE also affects the
  371      *  oom adjust capability, so for now, we disable
  372      *  this as I'd rather have a oom'able process when
  373      *  memory gets contrained. Don't enable this
  374      *  unless one checks that processes able oomable!
  375      */
  376 #if 0 && defined(HAVE_PRCTL) &&     \
  377     defined(HAVE_SYS_PRCTL_H) &&    \
  378     defined(PR_SET_DUMPABLE)
  379     (void)prctl(PR_SET_DUMPABLE,
  380         dumpable ? SUID_DUMP_USER : SUID_DUMP_DISABLE);
  381 #endif
  382     if ((fd = open("/proc/self/coredump_filter", O_WRONLY)) >= 0) {
  383         char const *str =
  384             dumpable ? "0x33" : "0x00";
  385 
  386         if (write(fd, str, strlen(str)) < 0)
  387             rc = -1;
  388         (void)close(fd);
  389     }
  390     return rc;
  391 }
  392 
  393 /*
  394  *  stress_set_timer_slackigned_longns()
  395  *  set timer slack in nanoseconds
  396  */
  397 int stress_set_timer_slack_ns(const char *opt)
  398 {
  399 #if defined(HAVE_PRCTL_TIMER_SLACK)
  400     timer_slack = get_uint32(opt);
  401 #else
  402     (void)opt;
  403 #endif
  404     return 0;
  405 }
  406 
  407 /*
  408  *  stress_set_timer_slack()
  409  *  set timer slack
  410  */
  411 void stress_set_timer_slack(void)
  412 {
  413 #if defined(HAVE_PRCTL) &&      \
  414     defined(HAVE_SYS_PRCTL_H) &&    \
  415     defined(HAVE_PRCTL_TIMER_SLACK)
  416     (void)prctl(PR_SET_TIMERSLACK, timer_slack);
  417 #endif
  418 }
  419 
  420 /*
  421  *  stress_set_proc_name()
  422  *  Set process name, we don't care if it fails
  423  */
  424 void stress_set_proc_name(const char *name)
  425 {
  426 #if defined(HAVE_PRCTL) &&      \
  427     defined(HAVE_SYS_PRCTL_H) &&    \
  428     defined(PR_SET_NAME)
  429     if (!(g_opt_flags & OPT_FLAGS_KEEP_NAME))
  430         (void)prctl(PR_SET_NAME, name);
  431 #else
  432     (void)name; /* No-op */
  433 #endif
  434 }
  435 
  436 /*
  437  *  stress_munge_underscore()
  438  *  turn '_' to '-' in strings
  439  */
  440 char *stress_munge_underscore(const char *str)
  441 {
  442     static char munged[128];
  443     char *dst;
  444     const char *src;
  445     size_t str_len = strlen(str);
  446     ssize_t len = STRESS_MINIMUM(str_len, sizeof(munged) - 1);
  447 
  448     for (src = str, dst = munged; *src && (dst - munged) < len; src++)
  449         *dst++ = (*src == '_' ? '-' : *src);
  450 
  451     *dst = '\0';
  452 
  453     return munged;
  454 }
  455 
  456 /*
  457  *  __stress_get_stack_direction()
  458  *  helper to determine direction of stack
  459  */
  460 static ssize_t __stress_get_stack_direction(const uint8_t *val1)
  461 {
  462     const uint8_t val2;
  463     const ssize_t diff = &val2 - (const uint8_t *)val1;
  464 
  465     return (diff > 0) - (diff < 0);
  466 }
  467 
  468 /*
  469  *  stress_get_stack_direction()
  470  *      determine which way the stack goes, up / down
  471  *  just pass in any var on the stack before calling
  472  *  return:
  473  *       1 - stack goes down (conventional)
  474  *       0 - error
  475  *      -1 - stack goes up (unconventional)
  476  */
  477 ssize_t stress_get_stack_direction(void)
  478 {
  479     uint8_t val1 = 0;
  480     uint8_t waste[64];
  481 
  482     waste[(sizeof waste) - 1] = 0;
  483     return __stress_get_stack_direction(&val1);
  484 }
  485 
  486 /*
  487  *  stress_uint64_zero()
  488  *  return uint64 zero in way that force less smart
  489  *  static analysers to realise we are doing this
  490  *  to force a division by zero. I'd like to have
  491  *  a better solution than this ghastly way.
  492  */
  493 uint64_t stress_uint64_zero(void)
  494 {
  495     return g_shared->zero;
  496 }
  497 
  498 /*
  499  *  stress_set_temp_path()
  500  *  set temporary file path, default
  501  *  is . - current dir
  502  */
  503 int stress_set_temp_path(const char *path)
  504 {
  505     stress_temp_path = path;
  506 
  507     if (access(path, R_OK | W_OK) < 0) {
  508         (void)fprintf(stderr, "temp-path '%s' must be readable "
  509             "and writeable\n", path);
  510         return -1;
  511     }
  512 
  513     return 0;
  514 }
  515 
  516 /*
  517  *  stress_temp_filename()
  518  *      construct a temp filename
  519  */
  520 int stress_temp_filename(
  521     char *path,
  522     const size_t len,
  523     const char *name,
  524     const pid_t pid,
  525     const uint32_t instance,
  526     const uint64_t magic)
  527 {
  528     return snprintf(path, len, "%s/tmp-%s-%d-%"
  529         PRIu32 "/%s-%d-%"
  530         PRIu32 "-%" PRIu64,
  531         stress_temp_path,
  532         name, (int)pid, instance,
  533         name, (int)pid, instance, magic);
  534 }
  535 
  536 /*
  537  *  stress_temp_filename_args()
  538  *      construct a temp filename using info from args
  539  */
  540 int stress_temp_filename_args(
  541     const args_t *args,
  542     char *path,
  543     const size_t len,
  544     const uint64_t magic)
  545 {
  546     return stress_temp_filename(path, len, args->name,
  547         args->pid, args->instance, magic);
  548 }
  549 
  550 /*
  551  *  stress_temp_dir()
  552  *  create a temporary directory name
  553  */
  554 int stress_temp_dir(
  555     char *path,
  556     const size_t len,
  557     const char *name,
  558     const pid_t pid,
  559     const uint32_t instance)
  560 {
  561     return snprintf(path, len, "%s/tmp-%s-%d-%" PRIu32,
  562         stress_temp_path, name, (int)pid, instance);
  563 }
  564 
  565 /*
  566  *  stress_temp_dir_args()
  567  *  create a temporary directory name using info from args
  568  */
  569 int stress_temp_dir_args(
  570     const args_t *args,
  571     char *path,
  572     const size_t len)
  573 {
  574     return stress_temp_dir(path, len,
  575         args->name, args->pid, args->instance);
  576 }
  577 
  578 /*
  579  *   stress_temp_dir_mk()
  580  *  create a temporary directory
  581  */
  582 int stress_temp_dir_mk(
  583     const char *name,
  584     const pid_t pid,
  585     const uint32_t instance)
  586 {
  587     int ret;
  588     char tmp[PATH_MAX];
  589 
  590     stress_temp_dir(tmp, sizeof(tmp), name, pid, instance);
  591     ret = mkdir(tmp, S_IRWXU);
  592     if (ret < 0) {
  593         ret = -errno;
  594         pr_fail("%s: mkdir '%s' failed, errno=%d (%s)\n",
  595             name, tmp, errno, strerror(errno));
  596     }
  597 
  598     return ret;
  599 }
  600 
  601 /*
  602  *   stress_temp_dir_mk_args()
  603  *  create a temporary director using info from args
  604  */
  605 int stress_temp_dir_mk_args(const args_t *args)
  606 {
  607     return stress_temp_dir_mk(args->name, args->pid, args->instance);
  608 }
  609 
  610 /*
  611  *  stress_temp_dir_rm()
  612  *  remove a temporary directory
  613  */
  614 int stress_temp_dir_rm(
  615     const char *name,
  616     const pid_t pid,
  617     const uint32_t instance)
  618 {
  619     int ret;
  620     char tmp[PATH_MAX + 1];
  621 
  622     stress_temp_dir(tmp, sizeof(tmp), name, pid, instance);
  623     ret = rmdir(tmp);
  624     if (ret < 0) {
  625         ret = -errno;
  626         pr_fail("%s: rmdir '%s' failed, errno=%d (%s)\n",
  627             name, tmp, errno, strerror(errno));
  628     }
  629 
  630     return ret;
  631 }
  632 
  633 /*
  634  *  stress_temp_dir_rm_args()
  635  *  remove a temporary directory using info from args
  636  */
  637 int stress_temp_dir_rm_args(const args_t *args)
  638 {
  639     return stress_temp_dir_rm(args->name, args->pid, args->instance);
  640 }
  641 
  642 /*
  643  *  stress_cwd_readwriteable()
  644  *  check if cwd is read/writeable
  645  */
  646 void stress_cwd_readwriteable(void)
  647 {
  648     char path[PATH_MAX];
  649 
  650     if (getcwd(path, sizeof(path)) == NULL) {
  651         pr_dbg("cwd: Cannot determine current working directory\n");
  652         return;
  653     }
  654     if (access(path, R_OK | W_OK)) {
  655         pr_inf("Working directory %s is not read/writeable, "
  656             "some I/O tests may fail\n", path);
  657         return;
  658     }
  659 }
  660 
  661 /*
  662  *  stress_strsignal()
  663  *  signum to human readable string
  664  */
  665 const char *stress_strsignal(const int signum)
  666 {
  667     static char buffer[128];
  668 #if defined(STRESS_NSIG)
  669     const char *str = NULL;
  670 
  671     if ((signum >= 0) && (signum < STRESS_NSIG))
  672         str = strsignal(signum);
  673     if (str)
  674         (void)snprintf(buffer, sizeof(buffer), "signal %d (%s)",
  675             signum, str);
  676     else
  677         (void)snprintf(buffer, sizeof(buffer), "signal %d", signum);
  678 #else
  679     (void)snprintf(buffer, sizeof(buffer), "signal %d", signum);
  680 #endif
  681     return buffer;
  682 }
  683 
  684 
  685 /*
  686  *  stress_strnrnd()
  687  *  fill string with random chars
  688  */
  689 void stress_strnrnd(char *str, const size_t len)
  690 {
  691     char *end = str + len;
  692 
  693     while (str < end - 1)
  694         *str++ = (mwc8() % 26) + 'a';
  695 
  696     *str = '\0';
  697 }
  698 
  699 /*
  700  *  pr_yaml_runinfo()
  701  *  log info about the system we are running stress-ng on
  702  */
  703 void pr_yaml_runinfo(FILE *yaml)
  704 {
  705 #if defined(HAVE_UNAME) && defined(HAVE_SYS_UTSNAME_H)
  706     struct utsname uts;
  707 #endif
  708 #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  709     struct sysinfo info;
  710 #endif
  711     time_t t;
  712     struct tm *tm = NULL;
  713     char hostname[128];
  714     char *user = shim_getlogin();
  715 
  716     pr_yaml(yaml, "system-info:\n");
  717     if (time(&t) != ((time_t)-1))
  718         tm = localtime(&t);
  719 
  720     pr_yaml(yaml, "      stress-ng-version: " VERSION "\n");
  721     pr_yaml(yaml, "      run-by: %s\n", user ? user : "unknown");
  722     if (tm) {
  723         pr_yaml(yaml, "      date-yyyy-mm-dd: %4.4d:%2.2d:%2.2d\n",
  724             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
  725         pr_yaml(yaml, "      time-hh-mm-ss: %2.2d:%2.2d:%2.2d\n",
  726             tm->tm_hour, tm->tm_min, tm->tm_sec);
  727         pr_yaml(yaml, "      epoch-secs: %ld\n", (long)t);
  728     }
  729     if (!gethostname(hostname, sizeof(hostname)))
  730         pr_yaml(yaml, "      hostname: %s\n", hostname);
  731 #if defined(HAVE_UNAME) && defined(HAVE_SYS_UTSNAME_H)
  732     if (uname(&uts) == 0) {
  733         pr_yaml(yaml, "      sysname: %s\n", uts.sysname);
  734         pr_yaml(yaml, "      nodename: %s\n", uts.nodename);
  735         pr_yaml(yaml, "      release: %s\n", uts.release);
  736         pr_yaml(yaml, "      version: %s\n", uts.version);
  737         pr_yaml(yaml, "      machine: %s\n", uts.machine);
  738     }
  739 #endif
  740 #if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
  741     if (sysinfo(&info) == 0) {
  742         pr_yaml(yaml, "      uptime: %ld\n", info.uptime);
  743         pr_yaml(yaml, "      totalram: %lu\n", info.totalram);
  744         pr_yaml(yaml, "      freeram: %lu\n", info.freeram);
  745         pr_yaml(yaml, "      sharedram: %lu\n", info.sharedram);
  746         pr_yaml(yaml, "      bufferram: %lu\n", info.bufferram);
  747         pr_yaml(yaml, "      totalswap: %lu\n", info.totalswap);
  748         pr_yaml(yaml, "      freeswap: %lu\n", info.freeswap);
  749     }
  750 #endif
  751     pr_yaml(yaml, "      pagesize: %zd\n", stress_get_pagesize());
  752     pr_yaml(yaml, "      cpus: %" PRId32 "\n", stress_get_processors_configured());
  753     pr_yaml(yaml, "      cpus-online: %" PRId32 "\n", stress_get_processors_online());
  754     pr_yaml(yaml, "      ticks-per-second: %" PRId32 "\n", stress_get_ticks_per_second());
  755     pr_yaml(yaml, "\n");
  756 }
  757 
  758 
  759 /*
  760  *  stress_cache_alloc()
  761  *  allocate shared cache buffer
  762  */
  763 int stress_cache_alloc(const char *name)
  764 {
  765 #if defined(__linux__)
  766     cpus_t *cpu_caches;
  767     cpu_cache_t *cache = NULL;
  768     uint16_t max_cache_level = 0;
  769 #endif
  770 
  771 #if !defined(__linux__)
  772     g_shared->mem_cache_size = MEM_CACHE_SIZE;
  773 #else
  774     cpu_caches = get_all_cpu_cache_details();
  775     if (!cpu_caches) {
  776         if (warn_once(WARN_ONCE_CACHE_DEFAULT))
  777             pr_inf("%s: using defaults, can't determine cache details from sysfs\n", name);
  778         g_shared->mem_cache_size = MEM_CACHE_SIZE;
  779         goto init_done;
  780     }
  781 
  782     max_cache_level = get_max_cache_level(cpu_caches);
  783 
  784     if (g_shared->mem_cache_level > max_cache_level) {
  785         if (warn_once(WARN_ONCE_CACHE_REDUCED))
  786             pr_dbg("%s: reducing cache level from L%d (too high) "
  787                 "to L%d\n", name,
  788                 g_shared->mem_cache_level, max_cache_level);
  789         g_shared->mem_cache_level = max_cache_level;
  790     }
  791 
  792     cache = get_cpu_cache(cpu_caches, g_shared->mem_cache_level);
  793     if (!cache) {
  794         if (warn_once(WARN_ONCE_CACHE_NONE))
  795             pr_inf("%s: using built-in defaults as no suitable "
  796                 "cache found\n", name);
  797         g_shared->mem_cache_size = MEM_CACHE_SIZE;
  798         goto init_done;
  799     }
  800 
  801     if (g_shared->mem_cache_ways > 0) {
  802         uint64_t way_size;
  803 
  804         if (g_shared->mem_cache_ways > cache->ways) {
  805             if (warn_once(WARN_ONCE_CACHE_WAY))
  806                 pr_inf("%s: cache way value too high - "
  807                     "defaulting to %d (the maximum)\n",
  808                     name, cache->ways);
  809             g_shared->mem_cache_ways = cache->ways;
  810         }
  811 
  812         way_size = cache->size / cache->ways;
  813 
  814         /* only fill the specified number of cache ways */
  815         g_shared->mem_cache_size = way_size * g_shared->mem_cache_ways;
  816     } else {
  817         /* fill the entire cache */
  818         g_shared->mem_cache_size = cache->size;
  819     }
  820 
  821     if (!g_shared->mem_cache_size) {
  822         if (warn_once(WARN_ONCE_CACHE_DEFAULT))
  823             pr_inf("%s: using built-in defaults as "
  824                 "unable to determine cache size\n", name);
  825         g_shared->mem_cache_size = MEM_CACHE_SIZE;
  826     }
  827 init_done:
  828     free_cpu_caches(cpu_caches);
  829 #endif
  830     g_shared->mem_cache = calloc(g_shared->mem_cache_size, 1);
  831     if (!g_shared->mem_cache) {
  832         pr_err("%s: failed to allocate shared cache buffer\n",
  833             name);
  834         return -1;
  835     }
  836     if (warn_once(WARN_ONCE_CACHE_SIZE))
  837         pr_dbg("%s: default cache size: %" PRIu64 "K\n",
  838             name, g_shared->mem_cache_size / 1024);
  839 
  840     return 0;
  841 }
  842 
  843 /*
  844  *  stress_cache_free()
  845  *  free shared cache buffer
  846  */
  847 void stress_cache_free(void)
  848 {
  849     free(g_shared->mem_cache);
  850 }
  851 
  852 /*
  853  *  system_write()
  854  *  write a buffer to a /sys or /proc entry
  855  */
  856 int system_write(
  857     const char *path,
  858     const char *buf,
  859     const size_t buf_len)
  860 {
  861     int fd;
  862     ssize_t ret;
  863 
  864     fd = open(path, O_WRONLY);
  865     if (fd < 0)
  866         return -errno;
  867     ret = write(fd, buf, buf_len);
  868     if (ret < (ssize_t)buf_len)
  869         ret = -errno;
  870     (void)close(fd);
  871 
  872     return ret;
  873 }
  874 
  875 /*
  876  *  system_read()
  877  *  read a buffer from a /sys or /proc entry
  878  */
  879 int system_read(
  880     const char *path,
  881     char *buf,
  882     const size_t buf_len)
  883 {
  884     int fd;
  885     ssize_t ret;
  886 
  887     (void)memset(buf, 0, buf_len);
  888 
  889     fd = open(path, O_RDONLY);
  890     if (fd < 0)
  891         return -errno;
  892     ret = read(fd, buf, buf_len);
  893     if (ret < 0)
  894         ret = -errno;
  895     (void)close(fd);
  896 
  897     return ret;
  898 }
  899 
  900 
  901 /*
  902  *  stress_is_prime64()
  903  *      return true if 64 bit value n is prime
  904  *      http://en.wikipedia.org/wiki/Primality_test
  905  */
  906 static inline bool stress_is_prime64(const uint64_t n)
  907 {
  908     register uint64_t i, max;
  909 
  910     if (n <= 3)
  911         return n >= 2;
  912     if ((n % 2 == 0) || (n % 3 == 0))
  913         return false;
  914     max = sqrt(n) + 1;
  915     for (i = 5; i < max; i+= 6)
  916         if ((n % i == 0) || (n % (i + 2) == 0))
  917             return false;
  918     return true;
  919 }
  920 
  921 /*
  922  *  stress_get_prime64()
  923  *  find a prime that is not a multiple of n,
  924  *  used for file name striding
  925  */
  926 uint64_t stress_get_prime64(const uint64_t n)
  927 {
  928     static uint p = 1009;
  929 
  930     if (n != p)
  931         return p;
  932 
  933     /* Search for next prime.. */
  934     for (;;) {
  935         p += 2;
  936 
  937         if ((n % p) && stress_is_prime64(p))
  938             return p;
  939     }
  940 }
  941 
  942 /*
  943  *  stress_get_file_limit()
  944  *  get max number of files that the current
  945  *  process can open;
  946  */
  947 size_t stress_get_file_limit(void)
  948 {
  949     struct rlimit rlim;
  950     size_t i, opened = 0, max = 65536;  /* initial guess */
  951 
  952     if (!getrlimit(RLIMIT_NOFILE, &rlim))
  953         max = (size_t)rlim.rlim_cur;
  954 
  955     /* Determine max number of free file descriptors we have */
  956     for (i = 0; i < max; i++) {
  957         if (fcntl((int)i, F_GETFL) > -1)
  958             opened++;
  959     }
  960     return max - opened;
  961 }
  962 
  963 /*
  964  *  stress_sigaltstack()
  965  *  attempt to set up an alternative signal stack
  966  *    stack - must be at least 4K
  967  *    size  - size of stack (- STACK_ALIGNMENT)
  968  */
  969 int stress_sigaltstack(const void *stack, const size_t size)
  970 {
  971 #if defined(HAVE_SIGALTSTACK)
  972     stack_t ss;
  973 
  974     if (size < (size_t)MINSIGSTKSZ) {
  975         pr_err("sigaltstack stack size %zu must be more than %zuK\n",
  976             size, (size_t)MINSIGSTKSZ / 1024);
  977         return -1;
  978     }
  979     ss.ss_sp = stress_align_address(stack, STACK_ALIGNMENT);
  980     ss.ss_size = size;
  981     ss.ss_flags = 0;
  982     if (sigaltstack(&ss, NULL) < 0) {
  983         pr_fail("sigaltstack failed: errno=%d (%s)\n",
  984             errno, strerror(errno));
  985         return -1;
  986     }
  987 #else
  988     (void)stack;
  989     (void)size;
  990 #endif
  991     return 0;
  992 }
  993 
  994 /*
  995  *  stress_sighandler()
  996  *  set signal handler in generic way
  997  */
  998 int stress_sighandler(
  999     const char *name,
 1000     const int signum,
 1001     void (*handler)(int),
 1002     struct sigaction *orig_action)
 1003 {
 1004     struct sigaction new_action;
 1005 #if defined(HAVE_SIGALTSTACK)
 1006     static bool set_altstack = false;
 1007 
 1008     /*
 1009      *  Signal handlers should really be using an alternative
 1010      *  signal stack to be totally safe.  For any new instance we
 1011      *  should set this alternative signal stack before setting
 1012      *  up any signal handler. We only need to do this once
 1013      *  per process instance, so just do it on the first
 1014      *  call to stress_sighandler.
 1015      */
 1016     if (!set_altstack) {
 1017         static uint8_t MLOCKED_DATA stack[SIGSTKSZ + STACK_ALIGNMENT];
 1018 
 1019         if (stress_sigaltstack(stack, SIGSTKSZ) < 0)
 1020             return -1;
 1021         set_altstack = true;
 1022     }
 1023 #endif
 1024 
 1025     (void)memset(&new_action, 0, sizeof new_action);
 1026     new_action.sa_handler = handler;
 1027     (void)sigemptyset(&new_action.sa_mask);
 1028     new_action.sa_flags = SA_ONSTACK;
 1029 
 1030     if (sigaction(signum, &new_action, orig_action) < 0) {
 1031         pr_fail("%s: sigaction %s: errno=%d (%s)\n",
 1032             name, stress_strsignal(signum), errno, strerror(errno));
 1033         return -1;
 1034     }
 1035     return 0;
 1036 }
 1037 
 1038 /*
 1039  *  stress_handle_stop_stressing()
 1040  *  set flag to indicate to stressor to stop stressing
 1041  */
 1042 void stress_handle_stop_stressing(int signum)
 1043 {
 1044     (void)signum;
 1045 
 1046     g_keep_stressing_flag = false;
 1047 }
 1048 
 1049 /*
 1050  *  stress_sig_stop_stressing()
 1051  *  install a handler that sets the global flag
 1052  *  to indicate to a stressor to stop stressing
 1053  */
 1054 int stress_sig_stop_stressing(const char *name, const int sig)
 1055 {
 1056     return stress_sighandler(name, sig, stress_handle_stop_stressing, NULL);
 1057 }
 1058 
 1059 /*
 1060  *  stress_sigrestore()
 1061  *  restore a handler
 1062  */
 1063 int stress_sigrestore(
 1064     const char *name,
 1065     const int signum,
 1066     struct sigaction *orig_action)
 1067 {
 1068     if (sigaction(signum, orig_action, NULL) < 0) {
 1069         pr_fail("%s: sigaction %s restore: errno=%d (%s)\n",
 1070             name, stress_strsignal(signum), errno, strerror(errno));
 1071         return -1;
 1072     }
 1073     return 0;
 1074 }
 1075 
 1076 /*
 1077  *  stress_get_cpu()
 1078  *  get cpu number that process is currently on
 1079  */
 1080 unsigned int stress_get_cpu(void)
 1081 {
 1082 #if defined(HAVE_SCHED_GETCPU) && !defined(__PPC64__)
 1083     int cpu;
 1084 
 1085     cpu = sched_getcpu();
 1086     return (unsigned int)((cpu < 0) ? 0 : cpu);
 1087 #else
 1088     return 0;
 1089 #endif
 1090 }
 1091 
 1092 #define XSTRINGIFY(s) STRINGIFY(s)
 1093 #define STRINGIFY(s) #s
 1094 
 1095 /*
 1096  *  stress_get_compiler()
 1097  *  return compiler info
 1098  */
 1099 const char *stress_get_compiler(void)
 1100 {
 1101 #if defined(__clang_major__) && defined(__clang_minor__)
 1102     static const char cc[] = "clang " XSTRINGIFY(__clang_major__) "." XSTRINGIFY(__clang_minor__) "";
 1103 #elif defined(__GNUC__) && defined(__GNUC_MINOR__)
 1104     static const char cc[] = "gcc " XSTRINGIFY(__GNUC__) "." XSTRINGIFY(__GNUC_MINOR__) "";
 1105 #else
 1106     static const char cc[] = "cc unknown";
 1107 #endif
 1108     return cc;
 1109 }
 1110 
 1111 /*
 1112  *  stress_get_uname_info()
 1113  *  return uname information
 1114  */
 1115 const char *stress_get_uname_info(void)
 1116 {
 1117 #if defined(HAVE_UNAME) && defined(HAVE_SYS_UTSNAME_H)
 1118     struct utsname buf;
 1119 
 1120     if (!uname(&buf)) {
 1121         static char str[sizeof(buf.machine) +
 1122                             sizeof(buf.sysname) +
 1123                 sizeof(buf.release) + 3];
 1124 
 1125         (void)snprintf(str, sizeof(str), "%s %s %s", buf.machine, buf.sysname, buf.release);
 1126         return str;
 1127     }
 1128 #endif
 1129     return "unknown";
 1130 }
 1131 
 1132 /*
 1133  *  stress_not_implemented()
 1134  *  report that a stressor is not implemented
 1135  *  on a particular arch or kernel
 1136  */
 1137 int stress_not_implemented(const args_t *args)
 1138 {
 1139 #if defined(HAVE_UNAME) && defined(HAVE_SYS_UTSNAME_H)
 1140     struct utsname buf;
 1141 
 1142     if (!uname(&buf)) {
 1143         pr_inf("%s: this stressor is not implemented on this system: %s %s\n",
 1144             args->name, stress_get_uname_info(), stress_get_compiler());
 1145         return EXIT_NOT_IMPLEMENTED;
 1146     }
 1147 #endif
 1148     pr_inf("%s: this stressor is not implemented on this system: %s\n",
 1149         args->name, stress_get_compiler());
 1150     return EXIT_NOT_IMPLEMENTED;
 1151 }
 1152 
 1153 #if defined(F_SETPIPE_SZ)
 1154 /*
 1155  *  stress_check_max_pipe_size()
 1156  *  check if the given pipe size is allowed
 1157  */
 1158 static inline size_t stress_check_max_pipe_size(
 1159     const size_t sz,
 1160     const size_t page_size)
 1161 {
 1162     int fds[2];
 1163 
 1164     if (sz < page_size)
 1165         return -1;
 1166 
 1167     if (pipe(fds) < 0)
 1168         return -1;
 1169 
 1170     if (fcntl(fds[0], F_SETPIPE_SZ, sz) < 0)
 1171         return -1;
 1172 
 1173     (void)close(fds[0]);
 1174     (void)close(fds[1]);
 1175     return 0;
 1176 }
 1177 #endif
 1178 
 1179 /*
 1180  *  stress_probe_max_pipe_size()
 1181  *  determine the maximim allowed pipe size
 1182  */
 1183 size_t stress_probe_max_pipe_size(void)
 1184 {
 1185     static size_t max_pipe_size;
 1186 
 1187 #if defined(F_SETPIPE_SZ)
 1188     size_t i, ret, prev_sz, sz, min, max;
 1189     char buf[64];
 1190     size_t page_size;
 1191 #endif
 1192     /* Already determined? returned cached size */
 1193     if (max_pipe_size)
 1194         return max_pipe_size;
 1195 
 1196 #if defined(F_SETPIPE_SZ)
 1197     page_size = stress_get_pagesize();
 1198 
 1199     /*
 1200      *  Try and find maximum pipe size directly
 1201      */
 1202     ret = system_read("/proc/sys/fs/pipe-max-size", buf, sizeof(buf));
 1203     if (ret > 0) {
 1204         if (sscanf(buf, "%zd", &sz) == 1)
 1205             if (!stress_check_max_pipe_size(sz, page_size))
 1206                 goto ret;
 1207     }
 1208 
 1209     /*
 1210      *  Need to find size by binary chop probing
 1211      */
 1212     min = page_size;
 1213     max = INT_MAX;
 1214     prev_sz = 0;
 1215     for (i = 0; i < 64; i++) {
 1216         sz = min + (max - min) / 2;
 1217         if (prev_sz == sz)
 1218             return sz;
 1219         prev_sz = sz;
 1220         if (stress_check_max_pipe_size(sz, page_size) == 0) {
 1221             min = sz;
 1222         } else {
 1223             max = sz;
 1224         }
 1225     }
 1226 ret:
 1227     max_pipe_size = sz;
 1228 #else
 1229     max_pipe_size = stress_get_pagesize();
 1230 
 1231 #endif
 1232     return max_pipe_size;
 1233 }
 1234 
 1235 /*
 1236  *  stress_align_address
 1237  *  align address to alignment, alignment MUST be a power of 2
 1238  */
 1239 void *stress_align_address(const void *addr, const size_t alignment)
 1240 {
 1241     const uintptr_t uintptr =
 1242         ((uintptr_t)addr + alignment) & ~(alignment - 1);
 1243 
 1244     return (void *)uintptr;
 1245 }
 1246 
 1247 /*
 1248  *  keep_stressing()
 1249  *  returns true if we can keep on running a stressor
 1250  */
 1251 bool HOT OPTIMIZE3 __keep_stressing(const args_t *args)
 1252 {
 1253     return (LIKELY(g_keep_stressing_flag) &&
 1254             LIKELY(!args->max_ops || (get_counter(args) < args->max_ops)));
 1255 }
 1256 
 1257 /*
 1258  *  stress_uint64_to_str()
 1259  *  turn 64 bit size to human readable string
 1260  */
 1261 char *stress_uint64_to_str(char *str, size_t len, const uint64_t val)
 1262 {
 1263     typedef struct {
 1264         uint64_t size;
 1265         char *suffix;
 1266     } size_info_t;
 1267 
 1268     static const size_info_t size_info[] = {
 1269         { EB, "E" },
 1270         { PB, "P" },
 1271         { TB, "T" },
 1272         { GB, "G" },
 1273         { MB, "M" },
 1274         { KB, "K" },
 1275     };
 1276     size_t i;
 1277     char *suffix = "";
 1278     uint64_t scale = 1;
 1279 
 1280     for (i = 0; i < SIZEOF_ARRAY(size_info); i++) {
 1281         uint64_t scaled = val / size_info[i].size;
 1282 
 1283         if ((scaled >= 1) && (scaled < 1024)) {
 1284             suffix = size_info[i].suffix;
 1285             scale = size_info[i].size;
 1286             break;
 1287         }
 1288     }
 1289 
 1290     (void)snprintf(str, len, "%.1f%s", (double)val / scale, suffix);
 1291 
 1292     return str;
 1293 }
 1294 
 1295 #if defined(HAVE_SYS_CAPABILITY_H)
 1296 int stress_drop_capabilities(const char *name)
 1297 {
 1298     int ret;
 1299     uint32_t i;
 1300     struct __user_cap_header_struct uch;
 1301     struct __user_cap_data_struct ucd[_LINUX_CAPABILITY_U32S_3];
 1302 
 1303     (void)memset(&uch, 0, sizeof uch);
 1304     (void)memset(ucd, 0, sizeof ucd);
 1305 
 1306     uch.version = _LINUX_CAPABILITY_VERSION_3;
 1307     uch.pid = getpid();
 1308 
 1309     ret = capget(&uch, ucd);
 1310     if (ret < 0) {
 1311         pr_fail("%s: capget on pid %d failed: "
 1312             "errno=%d (%s)\n",
 1313             name, uch.pid, errno, strerror(errno));
 1314         return -1;
 1315     }
 1316 
 1317     /*
 1318      *  We could just memset ucd to zero, but
 1319      *  lets explicity set all the capability
 1320      *  bits to zero to show the intent
 1321      */
 1322     for (i = 0; i <= CAP_LAST_CAP; i++) {
 1323         uint32_t idx = CAP_TO_INDEX(i);
 1324         uint32_t mask = CAP_TO_MASK(i);
 1325 
 1326         ucd[idx].inheritable &= ~mask;
 1327         ucd[idx].permitted &= ~mask;
 1328         ucd[idx].effective &= ~mask;
 1329     }
 1330 
 1331     ret = capset(&uch, ucd);
 1332     if (ret < 0) {
 1333         pr_fail("%s: capset on pid %d failed: "
 1334             "errno=%d (%s)\n",
 1335             name, uch.pid, errno, strerror(errno));
 1336         return -1;
 1337     }
 1338 #if defined(HAVE_PRCTL) &&      \
 1339     defined(HAVE_SYS_PRCTL_H) &&    \
 1340     defined(PR_SET_NO_NEW_PRIVS)
 1341     ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
 1342     if (ret < 0) {
 1343         pr_inf("%s: prctl PR_SET_NO_NEW_PRIVS on pid %d failed: "
 1344             "errno=%d (%s)\n",
 1345             name, uch.pid, errno, strerror(errno));
 1346         return -1;
 1347     }
 1348 #endif
 1349     return 0;
 1350 }
 1351 #else
 1352 int stress_drop_capabilities(const char *name)
 1353 {
 1354     (void)name;
 1355 
 1356     return 0;
 1357 }
 1358 #endif
 1359 
 1360 /*
 1361  *  stress_is_dot_filename()
 1362  *  is filename "." or ".."
 1363  */
 1364 bool stress_is_dot_filename(const char *name)
 1365 {
 1366     if (!strcmp(name, "."))
 1367         return true;
 1368     if (!strcmp(name, ".."))
 1369         return true;
 1370     return false;
 1371 }
 1372 
 1373 /*
 1374  *  stress_const_optdup(const char *opt)
 1375  *  duplicate a modifyable copy of a const option string opt
 1376  */
 1377 char *stress_const_optdup(const char *opt)
 1378 {
 1379     char *str;
 1380 
 1381     str = strdup(opt);
 1382     if (!str)
 1383         fprintf(stderr, "out of memory duplicating option '%s'\n", opt);
 1384 
 1385     return str;
 1386 }
 1387 
 1388 /*
 1389  *  stress_text_addr()
 1390  *  return length and start/end addresses of text segment
 1391  */
 1392 size_t stress_text_addr(char **start, char **end)
 1393 {
 1394 #if defined(__APPLE__)
 1395         extern void *get_etext(void);
 1396         ptrdiff_t text_start = (ptrdiff_t)get_etext();
 1397 #elif defined(__OpenBSD__)
 1398         extern char _start[];
 1399         ptrdiff_t text_start = (ptrdiff_t)&_start[0];
 1400 #elif defined(__TINYC__)
 1401         extern char _etext;
 1402         ptrdiff_t text_start = (ptrdiff_t)&_etext;
 1403 #else
 1404         extern char etext;
 1405         ptrdiff_t text_start = (ptrdiff_t)&etext;
 1406 #endif
 1407 
 1408 #if defined(__APPLE__)
 1409         extern void *get_edata(void);
 1410         ptrdiff_t text_end = (ptrdiff_t)get_edata();
 1411 #elif defined(__TINYC__)
 1412         extern char _edata;
 1413         ptrdiff_t text_end = (ptrdiff_t)&_edata;
 1414 #else
 1415         extern char edata;
 1416         ptrdiff_t text_end = (ptrdiff_t)&edata;
 1417 #endif
 1418         const size_t text_len = text_end - text_start;
 1419 
 1420     if ((start == NULL) || (end == NULL) || (text_start >= text_end))
 1421         return 0;
 1422 
 1423     *start = (char *)text_start;
 1424     *end = (char *)text_end;
 1425 
 1426     return text_len;
 1427 }