stress-ng-0.03.15/0000775000175000017500000000000012466243163012260 5ustar kingkingstress-ng-0.03.15/helper.c0000664000175000017500000001132712466243156013711 0ustar kingking/* * Copyright (C) 2014-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #define MUNGE_MIN(a,b) (((a) < (b)) ? (a) : (b)) /* * stress_get_pagesize() * get pagesize */ size_t stress_get_pagesize(void) { #ifdef _SC_PAGESIZE long sz; #endif static size_t page_size = 0; if (page_size > 0) return page_size; #ifdef _SC_PAGESIZE sz = sysconf(_SC_PAGESIZE); page_size = (sz <= 0) ? PAGE_4K : (size_t)sz; #else page_size = PAGE_4K; #endif return page_size; } /* * stress_get_processors_online() * get number of processors that are online */ long stress_get_processors_online(void) { static long processors_online = 0; if (processors_online > 0) return processors_online; #ifdef _SC_NPROCESSORS_ONLN processors_online = sysconf(_SC_NPROCESSORS_ONLN); return processors_online; #else return -1; #endif } /* * stress_get_ticks_per_second() * get number of processors that are online */ long stress_get_ticks_per_second(void) { static long ticks_per_second = 0; if (ticks_per_second > 0) return ticks_per_second; #ifdef _SC_CLK_TCK ticks_per_second = sysconf(_SC_CLK_TCK); return ticks_per_second; #else return -1; #endif } /* * munge_underscore() * turn '_' to '-' in strings */ char *munge_underscore(char *str) { static char munged[128]; char *src, *dst; size_t str_len = strlen(str); ssize_t len = MUNGE_MIN(str_len, sizeof(munged) - 1); for (src = str, dst = munged; *src && (dst - munged) < len; src++) *dst++ = (*src == '_' ? '-' : *src); *dst = '\0'; return munged; } /* * force stress-float to think the doubles are actually * being used - this avoids the float loop from being * over optimised out per iteration. */ void double_put(const double a) { (void)a; } /* * force stress-int to think the uint64_t args are actually * being used - this avoids the integer loop from being * over optimised out per iteration. */ void uint64_put(const uint64_t a) { (void)a; } /* * uint64_zero() * return uint64 zero in way that force less smart * static analysers to realise we are doing this * to force a division by zero. I'd like to have * a better solution than this ghastly way. */ uint64_t uint64_zero(void) { return 0ULL; } /* * stress_temp_filename() * construct a temp filename */ int stress_temp_filename( char *path, const size_t len, const char *name, const pid_t pid, const uint32_t instance, const uint64_t magic) { return snprintf(path, len, ".%s-%i-%" PRIu32 "/%s-%i-%" PRIu32 "-%" PRIu64, name, pid, instance, name, pid, instance, magic); } /* * stress_temp_dir() * create a temporary directory name */ int stress_temp_dir( char *path, const size_t len, const char *name, const pid_t pid, const uint32_t instance) { return snprintf(path, len, ".%s-%i-%" PRIu32, name, pid, instance); } /* * stress_temp_dir_mk() * create a temportary directory */ int stress_temp_dir_mk( const char *name, const pid_t pid, const uint32_t instance) { int ret; char tmp[PATH_MAX]; stress_temp_dir(tmp, sizeof(tmp), name, pid, instance); ret = mkdir(tmp, S_IRWXU); if (ret < 0) pr_failed_err(name, "mkdir"); return ret; } /* * stress_temp_dir_rm() * remove a temporary directory */ int stress_temp_dir_rm( const char *name, const pid_t pid, const uint32_t instance) { int ret; char tmp[PATH_MAX + 1]; stress_temp_dir(tmp, sizeof(tmp), name, pid, instance); ret = rmdir(tmp); if (ret < 0) pr_failed_err(name, "rmdir"); return ret; } stress-ng-0.03.15/stress-wait.c0000664000175000017500000001027312466243156014716 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #if !defined(__gnu_hurd__) && !defined(__NetBSD__) #define ABORT_TIMEOUT (2.0) /* * spawn() * spawn a process */ static int spawn( void (*func)(const pid_t pid, uint64_t *counter, const uint64_t max_ops), pid_t pid_arg, uint64_t *counter, uint64_t max_ops) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { func(pid_arg, counter, max_ops); exit(EXIT_SUCCESS); } return pid; } /* * runner() * this process pauses, but is continually being * stopped and continued by the killer process */ static void runner(const pid_t pid, uint64_t *counter, const uint64_t max_ops) { (void)pid; pr_dbg(stderr, "wait: runner started [%d]\n", getpid()); do { (void)pause(); } while (opt_do_run && (!max_ops || *counter < max_ops)); kill(getppid(), SIGALRM); exit(EXIT_SUCCESS); } /* * killer() * this continually stops and continues the runner process */ static void killer(const pid_t pid, uint64_t *counter, const uint64_t max_ops) { double start = time_now(); uint64_t last_counter = *counter; pr_dbg(stderr, "wait: killer started [%d]\n", getpid()); do { (void)kill(pid, SIGSTOP); (void)kill(pid, SIGCONT); /* * The waits may be blocked and * so the counter is not being updated. * If it is blocked for too long bail out * so we don't get stuck in the parent * waiter indefintely. */ if (last_counter == *counter) { if (time_now() - start > ABORT_TIMEOUT) { pr_dbg(stderr, "waits were blocked, aborting\n"); break; } } else { start = time_now(); last_counter = *counter; } } while (opt_do_run && (!max_ops || *counter < max_ops)); /* forcefully kill runner, wait is in parent */ (void)kill(pid, SIGKILL); /* tell parent to wake up! */ (void)kill(getppid(), SIGALRM); exit(EXIT_SUCCESS); } /* * stress_wait * stress wait*() family of calls */ int stress_wait( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int status, ret = EXIT_SUCCESS; pid_t pid_r, pid_k; (void)instance; pr_dbg(stderr, "%s: waiter started [%d]\n", name, getpid()); pid_r = spawn(runner, 0, counter, max_ops); if (pid_r < 0) { pr_failed_dbg(name, "fork"); exit(EXIT_FAILURE); } pid_k = spawn(killer, pid_r, counter, max_ops); if (pid_k < 0) { pr_failed_dbg(name, "fork"); ret = EXIT_FAILURE; goto tidy; } do { waitpid(pid_r, &status, WCONTINUED); if (!opt_do_run) break; if (WIFCONTINUED(status)) (*counter)++; #if _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \ _POSIX_C_SOURCE >= 200809L { siginfo_t info; waitid(P_PID, pid_r, &info, WCONTINUED); if (!opt_do_run) break; if (WIFCONTINUED(status)) (*counter)++; } #endif } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)kill(pid_k, SIGKILL); (void)waitpid(pid_k, &status, 0); tidy: (void)kill(pid_r, SIGKILL); (void)waitpid(pid_r, &status, 0); return ret; } #endif stress-ng-0.03.15/stress-link.c0000664000175000017500000000677112466243156014717 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_link_unlink() * remove all links */ static void stress_link_unlink( const uint64_t n, const char *name, const pid_t pid, const uint32_t instance) { uint64_t i; for (i = 0; i < n; i++) { char path[PATH_MAX]; (void)stress_temp_filename(path, sizeof(path), name, pid, instance, i); (void)unlink(path); } sync(); } /* * stress_link_generic * stress links, generic case */ static int stress_link_generic( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, int (*linkfunc)(const char *oldpath, const char *newpath), const char *funcname) { const pid_t pid = getpid(); int fd; char oldpath[PATH_MAX]; if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(oldpath, sizeof(oldpath), name, pid, instance, ~0); if ((fd = open(oldpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)close(fd); do { uint64_t i, n = DEFAULT_LINKS; for (i = 0; i < n; i++) { char newpath[PATH_MAX]; (void)stress_temp_filename(newpath, sizeof(newpath), name, pid, instance, i); if (linkfunc(oldpath, newpath) < 0) { pr_failed_err(name, funcname); n = i; break; } if (!opt_do_run || (max_ops && *counter >= max_ops)) goto abort; (*counter)++; } stress_link_unlink(n, name, pid, instance); } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: /* force unlink of all files */ pr_tidy(stderr, "%s: removing %" PRIu32" entries\n", name, DEFAULT_LINKS); stress_link_unlink(DEFAULT_LINKS, name, pid, instance); (void)unlink(oldpath); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } /* * stress_link * stress hard links */ int stress_link( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { return stress_link_generic(counter, instance, max_ops, name, link, "link"); } /* * stress_symlink * stress symbolic links */ int stress_symlink( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { return stress_link_generic(counter, instance, max_ops, name, symlink, "symlink"); } stress-ng-0.03.15/stress-malloc.c0000664000175000017500000001122412466243156015216 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static size_t opt_malloc_bytes = DEFAULT_MALLOC_BYTES; static size_t opt_malloc_max = DEFAULT_MALLOC_MAX; void stress_set_malloc_bytes(const char *optarg) { opt_malloc_bytes = (size_t)get_uint64_byte(optarg); check_range("malloc-bytes", opt_malloc_bytes, MIN_MALLOC_BYTES, MAX_MALLOC_BYTES); } void stress_set_malloc_max(const char *optarg) { opt_malloc_max = (size_t)get_uint64_byte(optarg); check_range("malloc-max", opt_malloc_max, MIN_MALLOC_MAX, MAX_MALLOC_MAX); } /* * stress_alloc_size() * get a new allocation size, ensuring * it is never zero bytes. */ static inline size_t stress_alloc_size(void) { size_t len = mwc() % opt_malloc_bytes; return len ? len : 1; } /* * stress_malloc() * stress malloc by performing a mix of * allocation and frees */ int stress_malloc( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; uint32_t restarts = 0, nomems = 0; again: pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; /* Parent, wait for child */ ret = waitpid(pid, &status, 0); if (ret < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n", name, errno, strerror(errno)); (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %d (instance %d)\n", name, WTERMSIG(status), instance); /* If we got killed by OOM killer, re-start */ if (WTERMSIG(status) == SIGKILL) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; goto again; } } } else if (pid == 0) { void *addr[opt_malloc_max]; size_t j; memset(addr, 0, sizeof(addr)); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { unsigned int rnd = mwc(); unsigned int i = rnd % opt_malloc_max; unsigned int action = (rnd >> 12) & 1; unsigned int do_calloc = (rnd >> 14) & 0x1f; /* * With many instances running it is wise to * double check before the next allocation as * sometimes process start up is delayed for * some time and we should bail out before * exerting any more memory pressure */ if (!opt_do_run) goto abort; if (addr[i]) { /* 50% free, 50% realloc */ if (action) { free(addr[i]); addr[i] = NULL; (*counter)++; } else { void *tmp; size_t len = stress_alloc_size(); tmp = realloc(addr[i], len); if (tmp) { addr[i] = tmp; (void)mincore_touch_pages(addr[i], len); (*counter)++; } } } else { /* 50% free, 50% alloc */ if (action) { size_t len = stress_alloc_size(); if (do_calloc == 0) { size_t n = ((rnd >> 15) % 17) + 1; addr[i] = calloc(len / n, len * n); } else { addr[i] = malloc(len); } if (addr[i]) { (*counter)++; (void)mincore_touch_pages(addr[i], len); } } } } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: for (j = 0; j < opt_malloc_max; j++) { free(addr[j]); } } if (restarts + nomems > 0) pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 ", out of memory restarts: %" PRIu32 ".\n", name, restarts, nomems); return EXIT_SUCCESS; } stress-ng-0.03.15/mascot/0000775000175000017500000000000012466243156013550 5ustar kingkingstress-ng-0.03.15/mascot/stress-ng.svg0000664000175000017500000066572612466243156016244 0ustar kingking image/svg+xml stress-ng-0.03.15/stress-fstat.c0000664000175000017500000000673312466243156015101 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static const char *opt_fstat_dir = "/dev"; void stress_set_fstat_dir(const char *optarg) { opt_fstat_dir = optarg; } /* * stress_fstat() * stress system with fstat */ int stress_fstat( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { typedef struct dir_info { char *path; bool ignore; bool noaccess; struct dir_info *next; } dir_info_t; DIR *dp; dir_info_t *dir_info = NULL, *di; struct dirent *d; int ret = EXIT_FAILURE; bool stat_some; (void)instance; if ((dp = opendir(opt_fstat_dir)) == NULL) { pr_err(stderr, "%s: opendir on %s failed: errno=%d: (%s)\n", name, opt_fstat_dir, errno, strerror(errno)); return EXIT_FAILURE; } /* Cache all the directory entries */ while ((d = readdir(dp)) != NULL) { char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", opt_fstat_dir, d->d_name); if ((di = calloc(1, sizeof(*di))) == NULL) { pr_err(stderr, "%s: out of memory\n", name); (void)closedir(dp); goto free_cache; } if ((di->path = strdup(path)) == NULL) { pr_err(stderr, "%s: out of memory\n", name); free(di); (void)closedir(dp); goto free_cache; } di->ignore = false; di->noaccess = false; di->next = dir_info; dir_info = di; } (void)closedir(dp); do { stat_some = false; for (di = dir_info; di; di = di->next) { int fd; struct stat buf; if (di->ignore) continue; if ((stat(di->path, &buf) < 0) && (errno != ENOMEM)) { di->ignore = true; continue; } if ((lstat(di->path, &buf) < 0) && (errno != ENOMEM)) { di->ignore = true; continue; } if (di->noaccess) continue; fd = open(di->path, O_RDONLY); if (fd < 0) { di->noaccess = true; continue; } if ((fstat(fd, &buf) < 0) && (errno != ENOMEM)) di->ignore = true; (void)close(fd); stat_some = true; (*counter)++; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } } while (stat_some && opt_do_run && (!max_ops || *counter < max_ops)); ret = EXIT_SUCCESS; free_cache: /* Free cache */ for (di = dir_info; di; ) { dir_info_t *next = di->next; free(di->path); free(di); di = next; } return ret; } stress-ng-0.03.15/io-priority.c0000664000175000017500000000715012466243156014717 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #if defined (__linux__) #include /* * See ioprio_set(2) and linux/ioprio.h, glibc has no definitions * for these at present. Also refer to Documentation/block/ioprio.txt * in the Linux kernel source. */ #define IOPRIO_CLASS_RT (1) #define IOPRIO_CLASS_BE (2) #define IOPRIO_CLASS_IDLE (3) #define IOPRIO_WHO_PROCESS (1) #define IOPRIO_WHO_PGRP (2) #define IOPRIO_WHO_USER (3) #define IOPRIO_PRIO_VALUE(class, data) (((class) << 13) | data) #endif #include "stress-ng.h" /* * get_opt_ionice_class() * string io scheduler to IOPRIO_CLASS */ int get_opt_ionice_class(const char *const str) { #if defined (IOPRIO_CLASS_IDLE) if (!strcmp("idle", str)) return IOPRIO_CLASS_IDLE; #endif #if defined (IOPRIO_CLASS_BE) if (!strcmp("besteffort", str) || !strcmp("be", str)) return IOPRIO_CLASS_BE; #endif #if defined (IOPRIO_CLASS_RT) if (!strcmp("realtime", str) || !strcmp("rt", str)) return IOPRIO_CLASS_RT; #endif if (strcmp("which", str)) fprintf(stderr, "Invalid ionice-class option: %s\n", str); fprintf(stderr, "Available options are:"); #if defined (IOPRIO_CLASS_IDLE) fprintf(stderr, " idle"); #endif #if defined (IOPRIO_CLASS_BE) fprintf(stderr, " besteffort be"); #endif #if defined (IOPRIO_CLASS_RT) fprintf(stderr, " realtime rt"); #endif fprintf(stderr, "\n"); exit(EXIT_FAILURE); } #if defined (__linux__) /* * ioprio_set() * ioprio_set system call */ static int ioprio_set(const int which, const int who, const int ioprio) { return syscall(SYS_ioprio_set, which, who, ioprio); } /* * set_iopriority() * check ioprio settings and set */ void set_iopriority(const int class, const int level) { int data = level, rc; switch (class) { case UNDEFINED: /* No preference, don't set */ return; case IOPRIO_CLASS_RT: case IOPRIO_CLASS_BE: if (level < 0 || level > 7) { fprintf(stderr, "Priority levels range from 0 (max) to 7 (min)\n"); exit(EXIT_FAILURE); } break; case IOPRIO_CLASS_IDLE: if ((level != UNDEFINED) && (level != 0)) fprintf(stderr, "Cannot set priority level with idle, defaulting to 0\n"); data = 0; break; default: fprintf(stderr, "Unknown priority class: %d\n", class); exit(EXIT_FAILURE); } rc = ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(class, data)); if (rc < 0) { fprintf(stderr, "Cannot set I/O priority: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } #else void set_iopriority(const int class, const int level) { (void)class; (void)level; } #endif stress-ng-0.03.15/stress-sem-sysv.c0000664000175000017500000001100212466243156015527 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if !defined(__gnu_hurd__) #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_semaphore_sysv_procs = DEFAULT_SEMAPHORE_PROCS; void stress_set_semaphore_sysv_procs(const char *optarg) { opt_semaphore_sysv_procs = get_uint64_byte(optarg); check_range("sem-procs", opt_semaphore_sysv_procs, MIN_SEMAPHORE_PROCS, MAX_SEMAPHORE_PROCS); } /* * stress_semaphore_sysv_init() * initialise a System V semaphore */ void stress_semaphore_sysv_init(void) { int count = 0; while (count < 100) { shared->sem_sysv_key_id = (key_t)(mwc() & 0xffff); shared->sem_sysv_id = semget(shared->sem_sysv_key_id, 1, IPC_CREAT | S_IRUSR | S_IWUSR); if (shared->sem_sysv_id >= 0) break; count++; } if (shared->sem_sysv_id >= 0) { unsigned short semval = 1; if (semctl(shared->sem_sysv_id, 0, SETVAL, semval) == 0) { shared->sem_sysv_init = true; return; } /* Clean up */ (void)semctl(shared->sem_sysv_id, 0, IPC_RMID); } if (opt_sequential) { pr_inf(stderr, "Semaphore init failed: errno=%d: (%s), " "skipping semaphore stressor\n", errno, strerror(errno)); } else { pr_err(stderr, "Semaphore init failed: errno=%d: (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } /* * stress_semaphore_sysv_destory() * destroy a System V semaphore */ void stress_semaphore_sysv_destroy(void) { if (shared->sem_sysv_init) (void)semctl(shared->sem_sysv_id, 0, IPC_RMID); } /* * semaphore_sysv_thrash() * exercise the semaphore */ static void semaphore_sysv_thrash( const char *name, const uint64_t max_ops, uint64_t *counter) { do { int i; for (i = 0; i < 1000; i++) { struct sembuf semwait, semsignal; semwait.sem_num = 0; semwait.sem_op = -1; semwait.sem_flg = SEM_UNDO; semsignal.sem_num = 0; semsignal.sem_op = 1; semsignal.sem_flg = SEM_UNDO; if (semop(shared->sem_sysv_id, &semwait, 1) < 0) { if (errno != EINTR) pr_failed_dbg(name, "semop wait"); break; } (*counter)++; if (semop(shared->sem_sysv_id, &semsignal, 1) < 0) { if (errno != EINTR) pr_failed_dbg(name, "semop signal"); break; } if (!opt_do_run) break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * semaphore_sysv_spawn() * spawn a process */ static int semaphore_sysv_spawn( const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { semaphore_sysv_thrash(name, max_ops, counter); exit(EXIT_SUCCESS); } return pid; } /* * stress_sem_sysv() * stress system by sem ops */ int stress_sem_sysv( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_SEMAPHORE_PROCS]; uint64_t i; (void)instance; if (!shared->sem_sysv_init) { pr_err(stderr, "%s: aborting, semaphore not initialised\n", name); return EXIT_FAILURE; } memset(pids, 0, sizeof(pids)); for (i = 0; i < opt_semaphore_sysv_procs; i++) { pids[i] = semaphore_sysv_spawn(name, max_ops, counter); if (pids[i] < 0) goto reap; } semaphore_sysv_thrash(name, max_ops, counter); reap: for (i = 0; i < opt_semaphore_sysv_procs; i++) { if (pids[i] > 0) { int status; (void)kill(pids[i], SIGKILL); waitpid(pids[i], &status, 0); } } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-sigq.c0000664000175000017500000000532512466243156014717 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" #if _POSIX_C_SOURCE >= 199309L && !defined(__gnu_hurd__) static void stress_sigqhandler(int dummy) { (void)dummy; } /* * stress_sigq * stress by heavy sigqueue message sending */ int stress_sigq( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; struct sigaction new_action; new_action.sa_handler = stress_sigqhandler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGUSR1, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); for (;;) { siginfo_t info; sigwaitinfo(&mask, &info); if (info.si_value.sival_int) break; } pr_dbg(stderr, "%s: child got termination notice\n", name); pr_dbg(stderr, "%s: exited on pid [%d] (instance %" PRIu32 ")\n", name, getpid(), instance); _exit(0); } else { /* Parent */ union sigval s; int status; do { memset(&s, 0, sizeof(s)); s.sival_int = 0; sigqueue(pid, SIGUSR1, s); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_dbg(stderr, "%s: parent sent termination notice\n", name); memset(&s, 0, sizeof(s)); s.sival_int = 1; sigqueue(pid, SIGUSR1, s); usleep(250); /* And ensure child is really dead */ (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-bsearch.c0000664000175000017500000000613012466243156015356 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include "stress-ng.h" uint64_t opt_bsearch_size = DEFAULT_BSEARCH_SIZE; /* * stress_set_bsearch_size() * set bsearch size from given option string */ void stress_set_bsearch_size(const char *optarg) { opt_bsearch_size = get_uint64_byte(optarg); check_range("bsearch-size", opt_bsearch_size, MIN_BSEARCH_SIZE, MAX_BSEARCH_SIZE); } /* * cmp() * compare int32 values for bsearch */ static int cmp(const void *p1, const void *p2) { int32_t *i1 = (int32_t *)p1; int32_t *i2 = (int32_t *)p2; if (*i1 > *i2) return 1; else if (*i1 < *i2) return -1; else return 0; } /* * Monotonically increasing values */ #define SETDATA(d, i, v, prev) \ d[i] = 1 + prev + (v & 0x7); \ v >>= 2; \ prev = d[i]; \ i++; \ /* * stress_bsearch() * stress bsearch */ int stress_bsearch( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data, *ptr, prev = 0; const size_t n = (size_t)opt_bsearch_size; const size_t n8 = (n + 7) & ~7; size_t i; (void)instance; /* allocate in multiples of 8 */ if ((data = malloc(sizeof(int32_t) * n8)) == NULL) { pr_failed_dbg(name, "malloc"); return EXIT_FAILURE; } /* Populate with ascending data */ prev = 0; for (i = 0; i < n;) { uint64_t v = mwc(); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); SETDATA(data, i, v, prev); } do { for (ptr = data, i = 0; i < n; i++, ptr++) { int32_t *result; result = bsearch(ptr, data, n, sizeof(*ptr), cmp); if (opt_flags & OPT_FLAGS_VERIFY) { if (result == NULL) pr_fail(stderr, "element %zu could not be found\n", i); else if (*result != *ptr) pr_fail(stderr, "element %zu found %" PRIu32 ", expecting %" PRIu32 "\n", i, *result, *ptr); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(data); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-bigheap.c0000664000175000017500000001122212466243156015344 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_bigheap_growth = DEFAULT_BIGHEAP_GROWTH; /* * stress_set_bigheap_growth() * Set bigheap growth from given opt arg string */ void stress_set_bigheap_growth(const char *optarg) { opt_bigheap_growth = get_uint64_byte(optarg); check_range("bigheap-growth", opt_bigheap_growth, MIN_BIGHEAP_GROWTH, MAX_BIGHEAP_GROWTH); } /* * stress_bigheap() * stress heap allocation */ int stress_bigheap( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { void *ptr = NULL, *last_ptr = NULL; uint8_t *last_ptr_end = NULL; size_t size = 0; size_t stride = 4096; pid_t pid; uint32_t restarts = 0, nomems = 0; const size_t page_size = stress_get_pagesize(); again: pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; /* Parent, wait for child */ ret = waitpid(pid, &status, 0); if (ret < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n", name, errno, strerror(errno)); (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %d (instance %d)\n", name, WTERMSIG(status), instance); /* If we got killed by OOM killer, re-start */ if (WTERMSIG(status) == SIGKILL) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; goto again; } } } else if (pid == 0) { /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { void *old_ptr = ptr; size += (size_t)opt_bigheap_growth; /* * With many instances running it is wise to * double check before the next realloc as * sometimes process start up is delayed for * some time and we should bail out before * exerting any more memory pressure */ if (!opt_do_run) goto abort; ptr = realloc(old_ptr, size); if (ptr == NULL) { pr_dbg(stderr, "%s: out of memory at %" PRIu64 " MB (instance %d)\n", name, (uint64_t)(4096ULL * size) >> 20, instance); free(old_ptr); size = 0; nomems++; } else { size_t i, n; uint8_t *u8ptr, *tmp; if (last_ptr == ptr) { tmp = u8ptr = last_ptr_end; n = (size_t)opt_bigheap_growth; } else { tmp = u8ptr = ptr; n = size; } if (page_size > 0) { size_t sz = page_size - 1; uintptr_t pg_ptr = ((uintptr_t)ptr + sz) & ~sz; size_t len = size - (pg_ptr - (uintptr_t)ptr); (void)mincore_touch_pages((void *)pg_ptr, len); } for (i = 0; i < n; i+= stride, u8ptr += stride) { if (!opt_do_run) goto abort; *u8ptr = (uint8_t)i; } if (opt_flags & OPT_FLAGS_VERIFY) { for (i = 0; i < n; i+= stride, tmp += stride) { if (!opt_do_run) goto abort; if (*tmp != (uint8_t)i) pr_fail(stderr, "byte at location %p was 0x%" PRIx8 " instead of 0x%" PRIx8 "\n", u8ptr, *tmp, (uint8_t)i); } } last_ptr = ptr; last_ptr_end = u8ptr; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: free(ptr); } if (restarts + nomems > 0) pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 ", out of memory restarts: %" PRIu32 ".\n", name, restarts, nomems); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-inotify.c0000664000175000017500000003676012466243156015444 0ustar kingking/* * Copyright (C) 2012-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * * stress-inotify.c is derived from the eCryptfs inotify tests * that I authored in 2012. */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #define DIR_FLAGS (S_IRWXU | S_IRWXG) #define FILE_FLAGS (S_IRUSR | S_IWUSR) #define TIME_OUT (10) /* Secs for inotify to report back */ #define BUF_SIZE (4096) typedef int (*inotify_helper)(const char *path, const void *private); typedef void (*inotify_func)(const char *path); typedef struct { const inotify_func func; const char* description; } inotify_stress_t; /* * inotify_exercise() * run a given test helper function 'func' and see if this triggers the * required inotify event flags 'flags'. */ static void inotify_exercise( const char *filename, /* Filename in test */ const char *watchname, /* File or directory to watch using inotify */ const char *matchname, /* Filename we expect inotify event to report */ const inotify_helper func, /* Helper func */ const int flags, /* IN_* flags to watch for */ void *private) /* Helper func private data */ { int fd, wd, check_flags = flags; char buffer[1024]; static uint32_t n = 0; retry: n++; if ((fd = inotify_init()) < 0) { /* This is just so wrong... */ if (n < 1000 && errno == EMFILE) { /* * inotify cleanup may be still running from a previous * iteration, in which case we've run out of resources * temporarily, so sleep a short while and retry. */ usleep(10000); goto retry; } /* Nope, give up */ pr_fail(stderr, "inotify_init failed: errno=%d (%s) after %" PRIu32 " calls\n", errno, strerror(errno), n); return; } if ((wd = inotify_add_watch(fd, watchname, flags)) < 0) { (void)close(fd); pr_fail(stderr, "inotify_add_watch failed: errno=%d (%s)", errno, strerror(errno)); return; } if (func(filename, private) < 0) goto cleanup; while (check_flags) { ssize_t len, i = 0; struct timeval tv; fd_set rfds; int err; /* We give inotify TIME_OUT seconds to report back */ tv.tv_sec = TIME_OUT; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(fd, &rfds); /* Wait for an inotify event ... */ err = select(fd + 1, &rfds, NULL, NULL, &tv); if (err == -1) { if (errno != EINTR) pr_err(stderr, "select error: errno=%d (%s)\n", errno, strerror(errno)); break; } else if (err == 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "timed waiting for event flags 0x%x\n", flags); break; } len = read(fd, buffer, sizeof(buffer)); if ((len < 0) || (len > (ssize_t)sizeof(buffer))) { pr_fail(stderr, "error reading inotify: errno=%d (%s)\n", errno, strerror(errno)); break; } /* Scan through inotify events */ do { struct inotify_event *event = (struct inotify_event *)&buffer[i]; int f = event->mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB); if (event->len && strcmp(event->name, matchname) == 0 && flags & event->mask) check_flags &= ~(flags & event->mask); else if (flags & f) check_flags &= ~(flags & event->mask); i += sizeof(struct inotify_event) + event->len; } while (i < len); } cleanup: (void)inotify_rm_watch(fd, wd); if (close(fd) < 0) { pr_err(stderr, "close error: errno=%d (%s)\n", errno, strerror(errno)); } } /* * rm_file() * remove a file */ static int rm_file(const char *path) { if ((unlink(path) < 0) && errno != ENOENT) { pr_err(stderr, "cannot remove file %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } return 0; } /* * rm_dir() * clean files in directory and directory */ static int rm_dir(const char *path) { DIR *dp; int ret; dp = opendir(path); if (dp != NULL) { struct dirent *d; while ((d = readdir(dp)) != NULL) { char filename[PATH_MAX]; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; snprintf(filename, sizeof(filename), "%s/%s", path, d->d_name); (void)rm_file(filename); } (void)closedir(dp); } ret = rmdir(path); if (ret < 0 && errno != ENOENT) pr_err(stderr, "cannot remove directory %s: errno=%d (%s)\n", path, errno, strerror(errno)); return ret; } /* * mk_dir() * make a directory */ static int mk_dir(const char *path) { if (mkdir(path, DIR_FLAGS) < 0) { pr_err(stderr, "cannot mkdir %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } return 0; } /* * mk_filename() * simple helper to create a filename */ static void mk_filename( char *filename, const size_t len, const char *path, const char *name) { snprintf(filename, len, "%s/%s", path, name); } /* * mk_file() * create file of length len bytes */ static int mk_file(const char *filename, const size_t len) { int fd; size_t sz = len; char buffer[BUF_SIZE]; (void)rm_file(filename); if ((fd = open(filename, O_CREAT | O_RDWR, FILE_FLAGS)) < 0) { pr_err(stderr, "cannot create file %s: errno=%d (%s)\n", filename, errno, strerror(errno)); return -1; } memset(buffer, 'x', BUF_SIZE); while (sz > 0) { size_t n = (sz > BUF_SIZE) ? BUF_SIZE : sz; int ret; if ((ret = write(fd, buffer, n)) < 0) { pr_err(stderr, "error writing to file %s: errno=%d (%s)\n", filename, errno, strerror(errno)); (void)close(fd); return -1; } sz -= ret; } if (close(fd) < 0) { pr_err(stderr, "cannot close file %s: errno=%d (%s)\n", filename, errno, strerror(errno)); return -1; } return 0; } static int inotify_attrib_helper(const char *path, const void *dummy) { (void)dummy; if (chmod(path, S_IRUSR | S_IWUSR) < 0) { pr_err(stderr, "cannot chmod file %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } return 0; } void inotify_attrib_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; inotify_exercise(filepath, path, "inotify_file", inotify_attrib_helper, IN_ATTRIB, NULL); (void)rm_file(filepath); } static int inotify_access_helper(const char *path, const void *dummy) { int fd; char buffer[1]; int rc = 0; (void)dummy; if ((fd = open(path, O_RDONLY)) < 0) { pr_err(stderr, "cannot open file %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } /* Just want to force an access */ if (read(fd, buffer, 1) < 0) { pr_err(stderr, "cannot read file %s: errno=%d (%s)\n", path, errno, strerror(errno)); rc = -1; } (void)close(fd); return rc; } static void inotify_access_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; inotify_exercise(filepath, path, "inotify_file", inotify_access_helper, IN_ACCESS, NULL); (void)rm_file(filepath); } static int inotify_modify_helper(const char *path, const void *dummy) { int fd, rc = 0; char buffer[1] = { 0 }; (void)dummy; if (mk_file(path, 4096) < 0) return -1; if ((fd = open(path, O_RDWR)) < 0) { pr_err(stderr, "cannot open file %s: errno=%d (%s)\n", path, errno, strerror(errno)); rc = -1; goto remove; } if (write(fd, buffer, 1) < 0) { pr_err(stderr, "cannot write to file %s: errno=%d (%s)\n", path, errno, strerror(errno)); rc = -1; } (void)close(fd); remove: (void)rm_file(path); return rc; } static void inotify_modify_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); inotify_exercise(filepath, path, "inotify_file", inotify_modify_helper, IN_MODIFY, NULL); } static int inotify_creat_helper(const char *path, const void *dummy) { (void)dummy; int fd; if ((fd = creat(path, FILE_FLAGS)) < 0) { pr_err(stderr, "cannot create file %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } (void)close(fd); return 0; } static void inotify_creat_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); inotify_exercise(filepath, path, "inotify_file", inotify_creat_helper, IN_CREATE, NULL); (void)rm_file(filepath); } static int inotify_open_helper(const char *path, const void *dummy) { int fd; (void)dummy; if ((fd = open(path, O_RDONLY)) < 0) { pr_err(stderr, "cannot open file %s: errno=%d (%s)\n", path, errno, strerror(errno)); return -1; } (void)close(fd); return 0; } static void inotify_open_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; inotify_exercise(filepath, path, "inotify_file", inotify_open_helper, IN_OPEN, NULL); (void)rm_file(filepath); } static int inotify_delete_helper(const char *path, const void *dummy) { (void)dummy; return rm_file(path); } static void inotify_delete_file(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; inotify_exercise(filepath, path, "inotify_file", inotify_delete_helper, IN_DELETE, NULL); /* We remove (again) it just in case the test failed */ (void)rm_file(filepath); } static int inotify_delete_self_helper(const char *path, const void *dummy) { (void)dummy; return rm_dir(path); } static void inotify_delete_self(const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_dir"); if (mk_dir(filepath) < 0) return; inotify_exercise(filepath, filepath, "inotify_dir", inotify_delete_self_helper, IN_DELETE_SELF, NULL); /* We remove (again) in case the test failed */ (void)rm_dir(filepath); } static int inotify_move_self_helper(const char *oldpath, const void *private) { char *newpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "cannot rename %s to %s: errno=%d (%s)\n", oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_move_self(const char *path) { char filepath[PATH_MAX], newpath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_dir"); if (mk_dir(filepath) < 0) return; mk_filename(newpath, PATH_MAX, path, "renamed_dir"); inotify_exercise(filepath, filepath, "inotify_dir", inotify_move_self_helper, IN_MOVE_SELF, newpath); (void)rm_dir(newpath); (void)rm_dir(filepath); /* In case rename failed */ } static int inotify_moved_to_helper(const char *newpath, const void *private) { char *oldpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "cannot rename %s to %s: errno=%d (%s)\n", oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_moved_to(const char *path) { char olddir[PATH_MAX], oldfile[PATH_MAX], newfile[PATH_MAX]; mk_filename(olddir, PATH_MAX, path, "new_dir"); (void)rm_dir(olddir); if (mk_dir(olddir) < 0) return; mk_filename(oldfile, PATH_MAX, olddir, "inotify_file"); if (mk_file(oldfile, 4096) < 0) return; mk_filename(newfile, PATH_MAX, path, "inotify_file"); inotify_exercise(newfile, path, "inotify_dir", inotify_moved_to_helper, IN_MOVED_TO, oldfile); (void)rm_file(newfile); (void)rm_dir(olddir); } static int inotify_moved_from_helper(const char *oldpath, const void *private) { char *newpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "cannot rename %s to %s: errno=%d (%s)\n", oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_moved_from(const char *path) { char oldfile[PATH_MAX], newdir[PATH_MAX], newfile[PATH_MAX]; mk_filename(oldfile, PATH_MAX, path, "inotify_file"); if (mk_file(oldfile, 4096) < 0) return; mk_filename(newdir, PATH_MAX, path, "new_dir"); (void)rm_dir(newdir); if (mk_dir(newdir) < 0) return; mk_filename(newfile, PATH_MAX, newdir, "inotify_file"); inotify_exercise(oldfile, path, "inotify_dir", inotify_moved_from_helper, IN_MOVED_FROM, newfile); (void)rm_file(newfile); (void)rm_file(oldfile); /* In case rename failed */ (void)rm_dir(newdir); } static int inotify_close_write_helper(const char *path, const void *fdptr) { (void)path; (void)close(*(int *)fdptr); return 0; } static void inotify_close_write_file(const char *path) { char filepath[PATH_MAX]; int fd; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; if ((fd = open(filepath, O_RDWR)) < 0) { pr_err(stderr, "cannot re-open %s: errno=%d (%s)\n", filepath, errno, strerror(errno)); return; } inotify_exercise(filepath, path, "inotify_file", inotify_close_write_helper, IN_CLOSE_WRITE, (void*)&fd); (void)rm_file(filepath); (void)close(fd); } static int inotify_close_nowrite_helper(const char *path, const void *fdptr) { (void)path; (void)close(*(int *)fdptr); return 0; } static void inotify_close_nowrite_file(const char *path) { char filepath[PATH_MAX]; int fd; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(filepath, 4096) < 0) return; if ((fd = open(filepath, O_RDONLY)) < 0) { pr_err(stderr, "cannot re-open %s: errno=%d (%s)\n", filepath, errno, strerror(errno)); (void)rm_file(filepath); return; } inotify_exercise(filepath, path, "inotify_file", inotify_close_nowrite_helper, IN_CLOSE_NOWRITE, (void*)&fd); (void)rm_file(filepath); (void)close(fd); } static const inotify_stress_t inotify_stressors[] = { { inotify_access_file, "IN_ACCESS" }, { inotify_modify_file, "IN_MODIFY" }, { inotify_attrib_file, "IN_ATTRIB" }, { inotify_close_write_file, "IN_CLOSE_WRITE" }, { inotify_close_nowrite_file, "IN_CLOSE_NOWRITE" }, { inotify_open_file, "IN_OPEN" }, { inotify_moved_from, "IN_MOVED_FROM" }, { inotify_moved_to, "IN_MOVED_TO" }, { inotify_creat_file, "IN_CREATE" }, { inotify_delete_file, "IN_DELETE" }, { inotify_delete_self, "IN_DELETE_SELF" }, { inotify_move_self, "IN_MOVE_SELF" }, { NULL, NULL } }; /* * stress_inotify() * stress inotify */ int stress_inotify( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char dirname[PATH_MAX]; int i; const pid_t pid = getpid(); (void)counter; (void)max_ops; stress_temp_dir(dirname, sizeof(dirname), name, pid, instance); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; do { for (i = 0; opt_do_run && inotify_stressors[i].func; i++) inotify_stressors[i].func(dirname); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-shm-sysv.c0000664000175000017500000001234112466243156015541 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #define KEY_GET_RETRIES (40) static size_t opt_shm_sysv_bytes = DEFAULT_SHM_SYSV_BYTES; static size_t opt_shm_sysv_segments = DEFAULT_SHM_SYSV_SEGMENTS; void stress_set_shm_sysv_bytes(const char *optarg) { opt_shm_sysv_bytes = (size_t)get_uint64_byte(optarg); check_range("shm-sysv-bytes", opt_shm_sysv_bytes, MIN_SHM_SYSV_BYTES, MAX_SHM_SYSV_BYTES); } void stress_set_shm_sysv_segments(const char *optarg) { opt_shm_sysv_segments = (size_t)get_uint64_byte(optarg); check_range("shm-sysv-segments", opt_shm_sysv_segments, MIN_SHM_SYSV_SEGMENTS, MAX_SHM_SYSV_SEGMENTS); } /* * stress_shm_sysv_check() * simple check if shared memory is sane */ static int stress_shm_sysv_check(uint8_t *buf, const size_t sz) { uint8_t *ptr, *end = buf + sz; uint8_t val; memset(buf, 0xa5, sz); for (val = 0, ptr = buf; ptr < end; ptr += 4096, val++) { *ptr = val; } for (val = 0, ptr = buf; ptr < end; ptr += 4096, val++) { if (*ptr != val) return -1; } return 0; } /* * stress_shm_sysv() * stress SYSTEM V shared memory */ int stress_shm_sysv( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t page_size = stress_get_pagesize(); size_t sz = opt_shm_sysv_bytes & ~(page_size - 1); const size_t orig_sz = sz; void *addrs[opt_shm_sysv_segments]; key_t keys[opt_shm_sysv_segments]; int shm_ids[opt_shm_sysv_segments]; int rc = EXIT_SUCCESS; bool ok = true; (void)instance; memset(addrs, 0, sizeof(addrs)); memset(keys, 0, sizeof(keys)); memset(shm_ids, 0, sizeof(shm_ids)); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { ssize_t i; for (i = 0; i < (ssize_t)opt_shm_sysv_segments; i++) { int shm_id, count = 0; void *addr; key_t key; if (!opt_do_run) goto reap; for (count = 0; count < KEY_GET_RETRIES; count++) { /* Get a unique key */ bool unique = true; do { ssize_t j; if (!opt_do_run) goto reap; /* Get a unique random key */ key = (key_t)(mwc() & 0xffff); for (j = 0; j < i - 1; j++) { if (key == keys[j]) { unique = false; break; } } } while (!unique); shm_id = shmget(key, sz, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); if (shm_id >= 0) break; if (errno == EINTR) goto reap; if ((errno == EINVAL) || (errno == ENOMEM)) { /* On some systems we may need to reduce the size */ if (sz > page_size) sz = sz / 2; } } if (shm_id < 0) { ok = false; pr_fail(stderr, "%s: shmget failed: errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto reap; } addr = shmat(shm_id, NULL, 0); if (addr == (char *) -1) { ok = false; pr_fail(stderr, "%s: shmat failed: errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto reap; } addrs[i] = addr; shm_ids[i] = shm_id; keys[i] = key; if (!opt_do_run) goto reap; (void)mincore_touch_pages(addr, sz); if (!opt_do_run) goto reap; (void)madvise_random(addr, sz); if (!opt_do_run) goto reap; if (stress_shm_sysv_check(addr, sz) < 0) { ok = false; pr_fail(stderr, "%s: memory check failed\n", name); rc = EXIT_FAILURE; goto reap; } (*counter)++; } reap: for (i = 0; i < (ssize_t)opt_shm_sysv_segments; i++) { if (addrs[i]) { if (shmdt(addrs[i]) < 0) { pr_fail(stderr, "%s: shmdt failed: errno=%d (%s)\n", name, errno, strerror(errno)); } } if (shm_ids[i] >= 0) { if (shmctl(shm_ids[i], IPC_RMID, NULL) < 0) { if (errno != EIDRM) pr_fail(stderr, "%s: shmctl failed: errno=%d (%s)\n", name, errno, strerror(errno)); } } addrs[i] = NULL; shm_ids[i] = 0; keys[i] = 0; } } while (ok && opt_do_run && (!max_ops || *counter < max_ops)); if (orig_sz != sz) pr_dbg(stderr, "%s: reduced shared memory size from %zu to %zu bytes\n", name, orig_sz, sz); return rc; } stress-ng-0.03.15/stress-lsearch.c0000664000175000017500000000552112466243156015373 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" static uint64_t opt_lsearch_size = DEFAULT_LSEARCH_SIZE; /* * stress_set_lsearch_size() * set lsearch size from given option string */ void stress_set_lsearch_size(const char *optarg) { opt_lsearch_size = get_uint64_byte(optarg); check_range("lsearch-size", opt_lsearch_size, MIN_TSEARCH_SIZE, MAX_TSEARCH_SIZE); } /* * cmp() * lsearch uint32 comparison for sorting */ static int cmp(const void *p1, const void *p2) { return (*(uint32_t *)p1 - *(uint32_t *)p2); } /* * stress_lsearch() * stress lsearch */ int stress_lsearch( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data, *root; const size_t max = (size_t)opt_lsearch_size; size_t i; (void)instance; if ((data = calloc(max, sizeof(int32_t))) == NULL) { pr_failed_dbg(name, "malloc"); return EXIT_FAILURE; } if ((root = calloc(max, sizeof(int32_t))) == NULL) { free(data); pr_failed_dbg(name, "malloc"); return EXIT_FAILURE; } do { size_t n = 0; /* Step #1, populate tree */ for (i = 0; i < max; i++) { data[i] = ((mwc() & 0xfff) << 20) ^ i; (void)lsearch(&data[i], root, &n, sizeof(int32_t), cmp); } /* Step #2, find */ for (i = 0; opt_do_run && i < n; i++) { int32_t *result; result = lfind(&data[i], root, &n, sizeof(int32_t), cmp); if (opt_flags & OPT_FLAGS_VERIFY) { if (result == NULL) pr_fail(stderr, "element %zu could not be found\n", i); else if (*result != data[i]) pr_fail(stderr, "element %zu found %" PRIu32 ", expecting %" PRIu32 "\n", i, *result, data[i]); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(root); free(data); return EXIT_SUCCESS; } stress-ng-0.03.15/parse-opts.c0000664000175000017500000000775512466243156014541 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * check_value() * sanity check number of workers */ void check_value( const char *const msg, const int val) { if ((val < 0) || (val > STRESS_PROCS_MAX)) { fprintf(stderr, "Number of %s workers must be between " "0 and %d\n", msg, STRESS_PROCS_MAX); exit(EXIT_FAILURE); } } /* * check_range() * Sanity check val against a lo - hi range */ void check_range( const char *const opt, const uint64_t val, const uint64_t lo, const uint64_t hi) { if ((val < lo) || (val > hi)) { fprintf(stderr, "Value %" PRId64 " is out of range for %s," " allowed: %" PRId64 " .. %" PRId64 "\n", val, opt, lo, hi); exit(EXIT_FAILURE); } } /* * ensure_positive() * ensure string contains just a +ve value */ static void ensure_positive(const char *const str) { char *ptr = (char *)str; bool negative = false; for (ptr = (char *)str; *ptr; ptr++) { if (*ptr == '-') { negative = true; continue; } if (isdigit((int)*ptr)) { if (!negative) return; fprintf(stderr, "Invalid negative number %s\n", str); exit(EXIT_FAILURE); } } } /* * get_int() * string to int */ int get_int(const char *const str) { int val; if (sscanf(str, "%12d", &val) != 1) { fprintf(stderr, "Invalid number %s\n", str); exit(EXIT_FAILURE); } return val; } /* * get_uint64() * string to uint64_t */ uint64_t get_uint64(const char *const str) { uint64_t val; ensure_positive(str); if (sscanf(str, "%" SCNu64, &val) != 1) { fprintf(stderr, "Invalid number %s\n", str); exit(EXIT_FAILURE); } return val; } /* * get_uint64_scale() * get a value and scale it by the given scale factor */ uint64_t get_uint64_scale( const char *const str, const scale_t scales[], const char *const msg) { uint64_t val; size_t len = strlen(str); int ch; int i; val = get_uint64(str); if (!len) { fprintf(stderr, "Value %s is an invalid size\n", str); exit(EXIT_FAILURE); } len--; ch = str[len]; if (isdigit(ch)) return val; ch = tolower(ch); for (i = 0; scales[i].ch; i++) { if (ch == scales[i].ch) return val * scales[i].scale; } printf("Illegal %s specifier %c\n", msg, str[len]); exit(EXIT_FAILURE); } /* * get_uint64_byte() * size in bytes, K bytes, M bytes or G bytes */ uint64_t get_uint64_byte(const char *const str) { static const scale_t scales[] = { { 'b', 1 }, { 'k', 1 << 10 }, { 'm', 1 << 20 }, { 'g', 1 << 30 }, { 0, 0 }, }; return get_uint64_scale(str, scales, "length"); } /* * get_uint64_time() * time in seconds, minutes, hours, days or years */ uint64_t get_uint64_time(const char *const str) { static const scale_t scales[] = { { 's', 1 }, { 'm', 60 }, { 'h', 3600 }, { 'd', 24 * 3600 }, { 'y', 365 * 24 * 3600 }, }; return get_uint64_scale(str, scales, "time"); } stress-ng-0.03.15/stress-hdd.c0000664000175000017500000002331512466243156014512 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" #define BUF_ALIGNMENT (4096) /* Write and read stress modes */ #define HDD_OPT_WR_SEQ (0x00000001) #define HDD_OPT_WR_RND (0x00000002) #define HDD_OPT_RD_SEQ (0x00000010) #define HDD_OPT_RD_RND (0x00000020) #define HDD_OPT_WR_MASK (0x00000003) #define HDD_OPT_RD_MASK (0x00000030) /* POSIX fadvise modes */ #define HDD_OPT_FADV_NORMAL (0x00000100) #define HDD_OPT_FADV_SEQ (0x00000200) #define HDD_OPT_FADV_RND (0x00000400) #define HDD_OPT_FADV_NOREUSE (0x00000800) #define HDD_OPT_FADV_WILLNEED (0x00001000) #define HDD_OPT_FADV_DONTNEED (0x00002000) #define HDD_OPT_FADV_MASK (0x00003f00) /* Open O_* modes */ #define HDD_OPT_O_SYNC (0x00010000) #define HDD_OPT_O_DSYNC (0x00020000) #define HDD_OPT_O_DIRECT (0x00040000) #define HDD_OPT_O_NOATIME (0x00080000) #define HDD_OPT_O_MASK (0x000f0000) static uint64_t opt_hdd_bytes = DEFAULT_HDD_BYTES; static uint64_t opt_hdd_write_size = DEFAULT_HDD_WRITE_SIZE; static int opt_hdd_flags = 0; static int opt_hdd_oflags = 0; typedef struct { const char *opt; /* User option */ int flag; /* HDD_OPT_ flag */ int exclude; /* Excluded HDD_OPT_ flags */ int advice; /* posix_fadvise value */ int oflag; /* open O_* flags */ } hdd_opts_t; static const hdd_opts_t hdd_opts[] = { #if defined(O_SYNC) { "sync", HDD_OPT_O_SYNC, 0, 0, O_SYNC }, #endif #if defined(O_DSYNC) { "dsync", HDD_OPT_O_DSYNC, 0, 0, O_DSYNC }, #endif #if defined(O_DIRECT) { "direct", HDD_OPT_O_DIRECT, 0, 0, O_DIRECT }, #endif #if defined(O_NOATIME) { "noatime", HDD_OPT_O_NOATIME, 0, 0, O_NOATIME }, #endif #if defined(POSIX_FADV_NORMAL) && !defined(__gnu_hurd__) { "wr-seq", HDD_OPT_WR_SEQ, HDD_OPT_WR_RND, 0, 0 }, { "wr-rnd", HDD_OPT_WR_RND, HDD_OPT_WR_SEQ, 0, 0 }, { "rd-seq", HDD_OPT_RD_SEQ, HDD_OPT_RD_RND, 0, 0 }, { "rd-rnd", HDD_OPT_RD_RND, HDD_OPT_RD_SEQ, 0, 0 }, { "fadv-normal",HDD_OPT_FADV_NORMAL, (HDD_OPT_FADV_SEQ | HDD_OPT_FADV_RND | HDD_OPT_FADV_NOREUSE | HDD_OPT_FADV_WILLNEED | HDD_OPT_FADV_DONTNEED), POSIX_FADV_NORMAL, 0 }, #endif #if defined(POSIX_FADV_SEQ) && !defined(__gnu_hurd__) { "fadv-seq", HDD_OPT_FADV_SEQ, (HDD_OPT_FADV_NORMAL | HDD_OPT_FADV_RND), POSIX_FADV_SEQUENTIAL, 0 }, #endif #if defined(POSIX_FADV_RND) && !defined(__gnu_hurd__) { "fadv-rnd", HDD_OPT_FADV_RND, (HDD_OPT_FADV_NORMAL | HDD_OPT_FADV_SEQ), POSIX_FADV_RANDOM, 0 }, #endif #if defined(POSIX_FADV_NOREUSE) && !defined(__gnu_hurd__) { "fadv-noreuse", HDD_OPT_FADV_NOREUSE, HDD_OPT_FADV_NORMAL, POSIX_FADV_NOREUSE, 0 }, #endif #if defined(POSIX_FADV_WILLNEED) && !defined(__gnu_hurd__) { "fadv-willneed", HDD_OPT_FADV_WILLNEED, (HDD_OPT_FADV_NORMAL | HDD_OPT_FADV_DONTNEED), POSIX_FADV_WILLNEED, 0 }, #endif #if defined(POSIX_FADV_DONTNEED) && !defined(__gnu_hurd__) { "fadv-dontneed", HDD_OPT_FADV_DONTNEED, (HDD_OPT_FADV_NORMAL | HDD_OPT_FADV_WILLNEED), POSIX_FADV_DONTNEED, 0 }, #endif { NULL, 0, 0, 0, 0 } }; void stress_set_hdd_bytes(const char *optarg) { opt_hdd_bytes = get_uint64_byte(optarg); check_range("hdd-bytes", opt_hdd_bytes, MIN_HDD_BYTES, MAX_HDD_BYTES); } void stress_set_hdd_write_size(const char *optarg) { opt_hdd_write_size = get_uint64_byte(optarg); check_range("hdd-write-size", opt_hdd_write_size, MIN_HDD_WRITE_SIZE, MAX_HDD_WRITE_SIZE); } /* * stress_hdd_opts * parse --hdd-opts option(s) list */ int stress_hdd_opts(char *opts) { char *str, *token, *saveptr = NULL; for (str = opts; (token = strtok_r(str, ",", &saveptr)) != NULL; str = NULL) { int i; bool opt_ok = false; for (i = 0; hdd_opts[i].opt; i++) { if (!strcmp(token, hdd_opts[i].opt)) { int exclude = opt_hdd_flags & hdd_opts[i].exclude; if (exclude) { int j; for (j = 0; hdd_opts[j].opt; j++) { if ((exclude & hdd_opts[j].flag) == exclude) { fprintf(stderr, "hdd-opt option '%s' is not " "compatible with option '%s'\n", token, hdd_opts[j].opt); break; } } return -1; } opt_hdd_flags |= hdd_opts[i].flag; opt_hdd_oflags |= hdd_opts[i].oflag; opt_ok = true; } } if (!opt_ok) { fprintf(stderr, "hdd-opt option '%s' not known, options are:", token); for (i = 0; hdd_opts[i].opt; i++) fprintf(stderr, "%s %s", i == 0 ? "" : ",", hdd_opts[i].opt); fprintf(stderr, "\n"); return -1; } } return 0; } /* * stress_hdd_advise() * set posix_fadvise options */ static int stress_hdd_advise(const char *name, const int fd, const int flags) { #if (defined(POSIX_FADV_SEQ) || defined(POSIX_FADV_RND) || \ defined(POSIX_FADV_NOREUSE) || defined(POSIX_FADV_WILLNEED) || \ defined(POSIX_FADV_DONTNEED)) && !defined(__gnu_hurd__) int i; if (!(flags & HDD_OPT_FADV_MASK)) return 0; for (i = 0; hdd_opts[i].opt; i++) { if (hdd_opts[i].flag & flags) { if (posix_fadvise(fd, 0, 0, hdd_opts[i].advice) < 0) { pr_failed_err(name, "posix_fadvise"); return -1; } } } #else (void)name; (void)fd; (void)flags; #endif return 0; } /* * stress_hdd * stress I/O via writes */ int stress_hdd( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *buf = NULL; uint64_t i; const pid_t pid = getpid(); int ret, rc = EXIT_FAILURE; char filename[PATH_MAX]; int flags = O_CREAT | O_RDWR | O_TRUNC | opt_hdd_oflags; int fadvise_flags = opt_hdd_flags & HDD_OPT_FADV_MASK; if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; /* Must have some write option */ if ((opt_hdd_flags & HDD_OPT_WR_MASK) == 0) opt_hdd_flags |= HDD_OPT_WR_SEQ; ret = posix_memalign((void **)&buf, BUF_ALIGNMENT, (size_t)opt_hdd_write_size); if (ret || !buf) { pr_err(stderr, "%s: cannot allocate buffer\n", name); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } for (i = 0; i < opt_hdd_write_size; i++) buf[i] = (uint8_t)mwc(); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); do { int fd; (void)umask(0077); if ((fd = open(filename, flags, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); goto finish; } (void)unlink(filename); if (stress_hdd_advise(name, fd, fadvise_flags) < 0) goto finish; /* Sequential Write */ if (opt_hdd_flags & HDD_OPT_WR_SEQ) { for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { if (write(fd, buf, (size_t)opt_hdd_write_size) < 0) { pr_failed_err(name, "write"); (void)close(fd); goto finish; } (*counter)++; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } } /* Random Write */ if (opt_hdd_flags & HDD_OPT_WR_RND) { for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { off_t offset = (mwc() % opt_hdd_bytes) & ~511; if (lseek(fd, offset, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); (void)close(fd); goto finish; } if (write(fd, buf, (size_t)opt_hdd_write_size) < 0) { pr_failed_err(name, "write"); (void)close(fd); goto finish; } (*counter)++; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } } /* Sequential Read */ if (opt_hdd_flags & HDD_OPT_RD_SEQ) { uint64_t misreads = 0; if (lseek(fd, 0, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); (void)close(fd); goto finish; } for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { ssize_t ret; ret = read(fd, buf, (size_t)opt_hdd_write_size); if (ret < 0) { pr_failed_err(name, "read"); (void)close(fd); goto finish; } if (ret != (ssize_t)opt_hdd_write_size) misreads++; (*counter)++; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } pr_dbg(stderr, "%s: %" PRIu64 " incomplete reads\n", name, misreads); } /* Random Read */ if (opt_hdd_flags & HDD_OPT_RD_RND) { uint64_t misreads = 0; for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { ssize_t ret; off_t offset = (mwc() % opt_hdd_bytes) & ~511; if (lseek(fd, offset, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); (void)close(fd); goto finish; } ret = read(fd, buf, (size_t)opt_hdd_write_size); if (ret < 0) { pr_failed_err(name, "read"); (void)close(fd); goto finish; } if (ret != (ssize_t)opt_hdd_write_size) misreads++; (*counter)++; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } pr_dbg(stderr, "%s: %" PRIu64 " incomplete reads\n", name, misreads); } (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; finish: free(buf); (void)stress_temp_dir_rm(name, pid, instance); return rc; } stress-ng-0.03.15/stress-msg.c0000664000175000017500000000632512466243156014543 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #if !defined(__gnu_hurd__) #define MAX_SIZE (8) #define MSG_STOP "STOPMSG" typedef struct { long mtype; char msg[MAX_SIZE]; } msg_t; /* * stress_msg * stress by message queues */ int stress_msg( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int msgq_id; (void)instance; msgq_id = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL); if (msgq_id < 0) { pr_failed_dbg(name, "msgget"); return EXIT_FAILURE; } pr_dbg(stderr, "System V message queue created, id: %d\n", msgq_id); pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { for (;;) { msg_t msg; uint64_t i; for (i = 0; ; i++) { uint64_t v; if (msgrcv(msgq_id, &msg, sizeof(msg.msg), 0, 0) < 0) { pr_failed_dbg(name, "msgrcv"); break; } if (!strcmp(msg.msg, MSG_STOP)) break; if (opt_flags & OPT_FLAGS_VERIFY) { memcpy(&v, msg.msg, sizeof(v)); if (v != i) pr_fail(stderr, "msgrcv: expected msg containing 0x%" PRIx64 " but received 0x%" PRIx64 " instead\n", i, v); } } exit(EXIT_SUCCESS); } } else { msg_t msg; uint64_t i = 0; int status; /* Parent */ do { memcpy(msg.msg, &i, sizeof(i)); msg.mtype = 1; if (msgsnd(msgq_id, &msg, sizeof(i), 0) < 0) { if (errno != EINTR) pr_failed_dbg(name, "msgsnd"); break; } i++; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); strncpy(msg.msg, MSG_STOP, sizeof(msg.msg)); if (msgsnd(msgq_id, &msg, sizeof(msg.msg), 0) < 0) pr_failed_dbg(name, "termination msgsnd"); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); if (msgctl(msgq_id, IPC_RMID, NULL) < 0) pr_failed_dbg(name, "msgctl"); else pr_dbg(stderr, "System V message queue deleted, id: %d\n", msgq_id); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-get.c0000664000175000017500000001256312466243156014535 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #if defined(__linux__) #include #endif #include "stress-ng.h" #define check_do_run() \ if (!opt_do_run) \ break; \ #define GIDS_MAX (1024) static const int rusages[] = { #ifdef RUSAGE_SELF RUSAGE_SELF, #endif #ifdef RUSAGE_CHILDREN RUSAGE_CHILDREN, #endif #ifdef RUSAGE_THREAD RUSAGE_THREAD #endif }; static const int rlimits[] = { #ifdef RLIMIT_AS RLIMIT_AS, #endif #ifdef RLIMIT_CORE RLIMIT_CORE, #endif #ifdef RLIMIT_CPU RLIMIT_CPU, #endif #ifdef RLIMIT_DATA RLIMIT_DATA, #endif #ifdef RLIMIT_FSIZE RLIMIT_FSIZE, #endif #ifdef RLIMIT_MEMLOCK RLIMIT_MEMLOCK, #endif #ifdef RLIMIT_MSGQUEUE RLIMIT_MSGQUEUE, #endif #ifdef RLIMIT_NICE RLIMIT_NICE, #endif #ifdef RLIMIT_NOFILE RLIMIT_NOFILE, #endif #ifdef RLIMIT_RSS RLIMIT_RSS, #endif #ifdef RLIMIT_RTPRIO RLIMIT_RTPRIO, #endif #ifdef RLIMIT_RTTIME RLIMIT_RTTIME, #endif #ifdef RLIMIT_SIGPENDING RLIMIT_SIGPENDING, #endif #ifdef RLIMIT_STACK RLIMIT_STACK #endif }; static int priorities[] = { #ifdef PRIO_PROCESS PRIO_PROCESS, #endif #ifdef PRIO_PGRP PRIO_PGRP, #endif #ifdef PRIO_USER PRIO_USER #endif }; #if defined(__linux__) static inline int gettid(void) { return syscall(SYS_gettid); } #endif /* * stress on get*() calls * stress system by rapid get*() system calls */ int stress_get( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; do { char path[PATH_MAX]; char *ptr; gid_t gids[GIDS_MAX]; #if defined(__linux__) gid_t rgid, egid, sgid; uid_t ruid, euid, suid; #endif const pid_t mypid = getpid(); int ret; size_t i; struct timeval tv; check_do_run(); (void)getppid(); check_do_run(); ptr = getcwd(path, sizeof path); if ((opt_flags & OPT_FLAGS_VERIFY) && (!ptr)) pr_fail(stderr, "%s: getcwd failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); (void)getgid(); check_do_run(); (void)getegid(); check_do_run(); (void)getuid(); check_do_run(); (void)geteuid(); check_do_run(); ret = getgroups(GIDS_MAX, gids); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getgroups failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); (void)getpgrp(); check_do_run(); (void)getpgid(mypid); check_do_run(); for (i = 0; i < SIZEOF_ARRAY(priorities); i++) { errno = 0; ret = getpriority(priorities[i], 0); if ((opt_flags & OPT_FLAGS_VERIFY) && errno && (ret < 0)) pr_fail(stderr, "%s: getpriority failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); } #if defined(__linux__) ret = getresgid(&rgid, &egid, &sgid); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getresgid failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); ret = getresuid(&ruid, &euid, &suid); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getresuid failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); #endif for (i = 0; i < SIZEOF_ARRAY(rlimits); i++) { struct rlimit rlim; ret = getrlimit(rlimits[i], &rlim); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getrlimit(%zu, ..) failed, errno=%d (%s)\n", name, i, errno, strerror(errno)); check_do_run(); } for (i = 0; i < SIZEOF_ARRAY(rusages); i++) { struct rusage usage; ret = getrusage(rusages[i], &usage); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getrusage(%zu, ..) failed, errno=%d (%s)\n", name, i, errno, strerror(errno)); check_do_run(); } #if _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED ret = getsid(mypid); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: getsid failed, errno=%d (%s)\n", name, errno, strerror(errno)); check_do_run(); #endif #if defined(__linux__) (void)gettid(); check_do_run(); #endif ret = gettimeofday(&tv, NULL); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0)) pr_fail(stderr, "%s: gettimeval failed, errno=%d (%s)\n", name, errno, strerror(errno)); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-futex.c0000664000175000017500000000674212466243156015113 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined (__linux__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * futex wake() * wake n waiters on futex */ static inline int futex_wake(const void *futex, const int n) { return syscall(SYS_futex, futex, FUTEX_WAKE, n, NULL, NULL, 0); } /* * futex_wait() * wait on futex with a timeout */ static inline int futex_wait(const void *futex, const int val, const struct timespec *timeout) { return syscall(SYS_futex, futex, FUTEX_WAIT, val, timeout, NULL, 0); } /* * stress_fuxex() * stress system by futex calls. The intention is not to * efficiently use futex, but to stress the futex system call * by rapidly calling it on wait and wakes */ int stress_futex( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint64_t *timeout = &shared->futex_timeout[instance]; uint32_t *futex = &shared->futex[instance]; pid_t pid; pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } if (pid > 0) { int status; do { int ret; /* Break early in case wake gets stuck (which it shouldn't) */ if (!opt_do_run) break; ret = futex_wake(futex, 1); if (opt_flags & OPT_FLAGS_VERIFY) { if (ret < 0) pr_fail(stderr, "futex wake failed: errno=%d (%s)\n", errno, strerror(errno)); } } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Kill waiter process */ kill(pid, SIGKILL); waitpid(pid, &status, 0); pr_dbg(stderr, "futex timeouts: %" PRIu64 "\n", *timeout); } else { do { /* Small timeout to force rapid timer wakeups */ const struct timespec t = { .tv_sec = 0, .tv_nsec = 5000 }; int ret; /* Break early before potential long wait */ if (!opt_do_run) break; ret = futex_wait(futex, 0, &t); /* timeout, re-do, stress on stupid fast polling */ if ((ret < 0) && (errno == ETIMEDOUT)) { (*timeout)++; continue; } if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "futex wait failed: errno=%d (%s)\n", errno, strerror(errno)); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-lockf.c0000664000175000017500000000650612466243156015054 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) /* * stress_lockf * stress file locking via lockf() */ int stress_lockf( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd, ret = EXIT_FAILURE; pid_t ppid = getppid(); char filename[PATH_MAX]; char dirname[PATH_MAX]; char buffer[4096]; off_t offset; const int lock_cmd = (opt_flags & OPT_FLAGS_LOCKF_NONBLK) ? F_TLOCK : F_LOCK; memset(buffer, 0, sizeof(buffer)); /* * There will be a race to create the directory * so EEXIST is expected on all but one instance */ (void)stress_temp_dir(dirname, sizeof(dirname), name, ppid, instance); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_failed_err(name, "mkdir"); return EXIT_FAILURE; } } /* * Lock file is based on parent pid and instance 0 * as we need to share this among all the other * stress flock processes */ (void)stress_temp_filename(filename, sizeof(filename), name, ppid, 0, 0); retry: if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { if ((errno == ENOENT) && opt_do_run) { /* Race, sometimes we need to retry */ goto retry; } /* Not sure why this fails.. report and abort */ pr_failed_err(name, "open"); (void)rmdir(dirname); return EXIT_FAILURE; } if (lseek(fd, 0, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); goto tidy; } if (write(fd, buffer, sizeof(buffer)) != sizeof(buffer)) { pr_failed_err(name, "write"); goto tidy; } do { offset = mwc() & 0x1000 ? 0 : sizeof(buffer) / 2; if (lseek(fd, offset, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); goto tidy; } while (lockf(fd, lock_cmd, sizeof(buffer) / 2) < 0) { if (!opt_do_run) break; } if (lockf(fd, F_ULOCK, sizeof(buffer) / 2) < 0) { pr_failed_err(name, "lockf unlock"); goto tidy; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); ret = EXIT_SUCCESS; tidy: (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return ret; } #endif stress-ng-0.03.15/stress-rename.c0000664000175000017500000000456612466243156015231 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_rename() * stress system by renames */ int stress_rename( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char name1[PATH_MAX], name2[PATH_MAX]; char *oldname = name1, *newname = name2, *tmpname; FILE *fp; uint64_t i = 0; const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; restart: (void)stress_temp_filename(oldname, PATH_MAX, name, pid, instance, i++); if ((fp = fopen(oldname, "w+")) == NULL) { pr_err(stderr, "%s: fopen failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)fclose(fp); do { (void)stress_temp_filename(newname, PATH_MAX, name, pid, instance, i++); if (rename(oldname, newname) < 0) { (void)unlink(oldname); (void)unlink(newname); goto restart; } tmpname = oldname; oldname = newname; newname = tmpname; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)unlink(oldname); (void)unlink(newname); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-fifo.c0000664000175000017500000001017612466243156014677 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_fifo_readers = DEFAULT_FIFO_READERS; void stress_set_fifo_readers(const char *optarg) { opt_fifo_readers = get_uint64(optarg); check_range("fifo-readers", opt_fifo_readers, MIN_FIFO_READERS, MAX_FIFO_READERS); } /* * fifo_spawn() * spawn a process */ static int fifo_spawn( void (*func)(const char *name, const char *fifoname), const char *name, const char *fifoname) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { func(name, fifoname); exit(EXIT_SUCCESS); } return pid; } /* * * */ void stress_fifo_reader(const char *name, const char *fifoname) { int fd; uint64_t val, lastval = 0; uint64_t wrap_mask = 0xffff000000000000ULL; fd = open(fifoname, O_RDONLY); if (fd < 0) { pr_err(stderr, "%s: fifo read open failed: errno=%d (%s)\n", name, errno, strerror(errno)); return; } for (;;) { ssize_t sz; sz = read(fd, &val, sizeof(val)); if (sz < 0) { if (errno != EINTR) { pr_err(stderr, "%s: fifo read failed: errno=%d (%s)\n", name, errno, strerror(errno)); } break; } if (sz == 0) break; if (sz != sizeof(val)) { pr_err(stderr, "%s: fifo read did not get uint64\n", name); break; } if ((val < lastval) && ((~val & wrap_mask) && (lastval & wrap_mask))) { pr_err(stderr, "%s: fifo read did not get expected value\n", name); break; } } (void)close(fd); } /* * stress_fifo * stress by heavy fifo I/O */ int stress_fifo( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_FIFO_READERS]; int fd; char fifoname[PATH_MAX]; uint64_t i, val = 0ULL; int ret = EXIT_FAILURE; const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(fifoname, sizeof(fifoname), name, pid, instance, mwc()); (void)umask(0077); if (mkfifo(fifoname, S_IRUSR | S_IWUSR) < 0) { pr_err(stderr, "%s: mkfifo failed: errno=%d (%s)\n", name, errno, strerror(errno)); goto tidy; } memset(pids, 0, sizeof(pids)); for (i = 0; i < opt_fifo_readers; i++) { pids[i] = fifo_spawn(stress_fifo_reader, name, fifoname); if (pids[i] < 0) goto reap; } fd = open(fifoname, O_WRONLY); if (fd < 0) { pr_err(stderr, "%s: fifo write open failed: errno=%d (%s)\n", name, errno, strerror(errno)); goto reap; } do { if (write(fd, &val, sizeof(val)) < 0) { if (errno != EINTR) pr_failed_dbg(name, "write"); break; } val++; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); ret = EXIT_SUCCESS; reap: for (i = 0; i < opt_fifo_readers; i++) { if (pids[i] > 0) { int status; (void)kill(pids[i], SIGKILL); waitpid(pids[i], &status, 0); } } tidy: (void)unlink(fifoname); (void)stress_temp_dir_rm(name, pid, instance); return ret; } stress-ng-0.03.15/stress-memcpy.c0000664000175000017500000000340612466243156015244 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include "stress-ng.h" static uint8_t buffer[MEM_CACHE_SIZE] ALIGN64; /* * stress_memcpy() * stress memory copies */ int stress_memcpy( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; uint8_t *mem_cache = shared->mem_cache; do { memcpy(buffer, mem_cache, MEM_CACHE_SIZE); memcpy(mem_cache, buffer, MEM_CACHE_SIZE); memmove(buffer, buffer + 64, MEM_CACHE_SIZE - 64); memmove(buffer + 64, buffer, MEM_CACHE_SIZE - 64); memmove(buffer + 1, buffer, MEM_CACHE_SIZE - 1); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/coredump.c0000664000175000017500000000326412466243156014251 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include "stress-ng.h" #if defined (__linux__) /* * set_coredump() * limit what is coredumped because * potentially we could have huge dumps * with the vm and mmap tests */ void set_coredump(const char *name) { char path[PATH_MAX]; int fd; snprintf(path, sizeof(path), "/proc/%d/coredump_filter", getpid()); if ((fd = open(path, O_WRONLY)) >= 0) { const char *str = "0x00"; ssize_t n = write(fd, str, strlen(str)); (void)close(fd); if (n < 0) pr_failed_dbg(name, "can't set coredump_filter"); else return; } } #else void set_coredump(const char *name) { (void)name; } #endif stress-ng-0.03.15/stress-mremap.c0000664000175000017500000001145112466243156015232 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static size_t opt_mremap_bytes = DEFAULT_MMAP_BYTES; void stress_set_mremap_bytes(const char *optarg) { opt_mremap_bytes = (size_t)get_uint64_byte(optarg); check_range("mmap-bytes", opt_mremap_bytes, MIN_MMAP_BYTES, MAX_MMAP_BYTES); } /* * try_remap() * try and remap old size to new size */ static int try_remap( const char *name, uint8_t **buf, const size_t old_sz, const size_t new_sz) { uint8_t *newbuf; int retry; #if defined(MREMAP_MAYMOVE) int flags = MREMAP_MAYMOVE; #else int flags = 0; #endif for (retry = 0; retry < 100; retry++) { if (!opt_do_run) return 0; newbuf = mremap(*buf, old_sz, new_sz, flags); if (newbuf != MAP_FAILED) { *buf = newbuf; return 0; } switch (errno) { case ENOMEM: case EAGAIN: continue; case EFAULT: case EINVAL: default: break; } } pr_fail(stderr, "%s: mremap failed, errno = %d (%s)\n", name, errno, strerror(errno)); return -1; } /* * stress_mremap_check() * check if mmap'd data is sane */ static int stress_mremap_check(uint8_t *buf, const size_t sz) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += 4096) { if (!opt_do_run) break; for (j = 0; j < 4096; j++) if (*ptr++ != val++) return -1; val++; } return 0; } static void stress_mremap_set(uint8_t *buf, const size_t sz) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += 4096) { if (!opt_do_run) break; for (j = 0; j < 4096; j++) *ptr++ = val++; val++; } } /* * stress_mremap() * stress mmap */ int stress_mremap( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *buf = NULL; const size_t page_size = stress_get_pagesize(); const size_t sz = opt_mremap_bytes & ~(page_size - 1); size_t new_sz = sz, old_sz; int flags = MAP_PRIVATE | MAP_ANONYMOUS; #ifdef MAP_POPULATE flags |= MAP_POPULATE; #endif (void)instance; /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { if (!opt_do_run) break; buf = mmap(NULL, new_sz, PROT_READ | PROT_WRITE, flags, -1, 0); if (buf == MAP_FAILED) { /* Force MAP_POPULATE off, just in case */ #ifdef MAP_POPULATE flags &= ~MAP_POPULATE; #endif continue; /* Try again */ } (void)madvise_random(buf, new_sz); (void)mincore_touch_pages(buf, opt_mremap_bytes); /* Ensure we can write to the mapped pages */ if (opt_flags & OPT_FLAGS_VERIFY) { stress_mremap_set(buf, new_sz); if (stress_mremap_check(buf, sz) < 0) { pr_fail(stderr, "mmap'd region of %zu bytes does " "not contain expected data\n", sz); munmap(buf, new_sz); return EXIT_FAILURE; } } old_sz = new_sz; new_sz >>= 1; while (new_sz > page_size) { if (try_remap(name, &buf, old_sz, new_sz) < 0) { munmap(buf, old_sz); return EXIT_FAILURE; } (void)madvise_random(buf, new_sz); if (opt_flags & OPT_FLAGS_VERIFY) { if (stress_mremap_check(buf, new_sz) < 0) { pr_fail(stderr, "mremap'd region of %zu bytes does " "not contain expected data\n", sz); munmap(buf, new_sz); return EXIT_FAILURE; } } old_sz = new_sz; new_sz >>= 1; } new_sz <<= 1; while (new_sz < opt_mremap_bytes) { if (try_remap(name, &buf, old_sz, new_sz) < 0) { munmap(buf, old_sz); return EXIT_FAILURE; } (void)madvise_random(buf, new_sz); old_sz = new_sz; new_sz <<= 1; } (void)munmap(buf, old_sz); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-sigsegv.c0000664000175000017500000000455712466243156015431 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" static sigjmp_buf jmp_env; /* * stress_segvhandler() * SEGV handler */ static void stress_segvhandler(int dummy) { (void)dummy; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } /* * stress_sigsegv * stress by generating segmentation faults */ int stress_sigsegv( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *ptr = NULL; (void)instance; for (;;) { struct sigaction new_action; int ret; memset(&new_action, 0, sizeof new_action); new_action.sa_handler = stress_segvhandler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGSEGV, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } if (sigaction(SIGILL, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); /* * We return here if we segfault, so * first check if we need to terminate */ if (!opt_do_run || (max_ops && *counter >= max_ops)) break; if (ret) (*counter)++; /* SIGSEGV/SIGILL occurred */ else *ptr = 0; /* Trip a SIGSEGV/SIGILL */ } return EXIT_SUCCESS; } stress-ng-0.03.15/stress-zero.c0000664000175000017500000000342512466243156014732 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_zero * stress reading of /dev/zero */ int stress_zero( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd; (void)instance; if ((fd = open("/dev/zero", O_RDONLY)) < 0) { pr_failed_err(name, "open"); return EXIT_FAILURE; } do { char buffer[4096]; if (read(fd, buffer, sizeof(buffer)) < 0) { pr_failed_err(name, "read"); (void)close(fd); return EXIT_FAILURE; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); return EXIT_SUCCESS; } stress-ng-0.03.15/out-of-memory.c0000664000175000017500000000455712466243156015160 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" #if defined (__linux__) /* * set_oom_adjustment() * attempt to stop oom killer * if we have root privileges then try and make process * unkillable by oom killer */ void set_oom_adjustment(const char *name, bool killable) { char path[PATH_MAX]; int fd; bool high_priv; high_priv = (getuid() == 0) && (geteuid() == 0); /* * Try modern oom interface */ snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", getpid()); if ((fd = open(path, O_WRONLY)) >= 0) { char *str; ssize_t n; if (killable) str = "1000"; else str = high_priv ? "-1000" : "0"; n = write(fd, str, strlen(str)); (void)close(fd); if (n < 0) pr_failed_dbg(name, "can't set oom_score_adj"); else return; } /* * Fall back to old oom interface */ snprintf(path, sizeof(path), "/proc/%d/oom_adj", getpid()); if ((fd = open(path, O_WRONLY)) >= 0) { char *str; ssize_t n; if (killable) str = high_priv ? "-17" : "-16"; else str = "15"; n = write(fd, str, strlen(str)); (void)close(fd); if (n < 0) pr_failed_dbg(name, "can't set oom_adj"); } return; } #else void set_oom_adjustment(const char *name, bool killable) { (void)name; (void)killable; } #endif stress-ng-0.03.15/stress-sem.c0000664000175000017500000000755112466243156014543 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_semaphore_posix_procs = DEFAULT_SEMAPHORE_PROCS; void stress_set_semaphore_posix_procs(const char *optarg) { opt_semaphore_posix_procs = get_uint64_byte(optarg); check_range("sem-procs", opt_semaphore_posix_procs, MIN_SEMAPHORE_PROCS, MAX_SEMAPHORE_PROCS); } /* * stress_semaphore_posix_init() * initialize a POSIX semaphore */ void stress_semaphore_posix_init(void) { /* create a mutex */ if (sem_init(&shared->sem_posix, 1, 1) >= 0) { shared->sem_posix_init = true; return; } if (opt_sequential) { pr_inf(stderr, "Semaphore init failed: errno=%d: (%s), " "skipping semaphore stressor\n", errno, strerror(errno)); } else { pr_err(stderr, "Semaphore init failed: errno=%d: (%s)\n", errno, strerror(errno)); } } /* * stress_semaphore_posix_destroy() * destory a POSIX semaphore */ void stress_semaphore_posix_destroy(void) { if (shared->sem_posix_init) { if (sem_destroy(&shared->sem_posix) < 0) { pr_err(stderr, "Semaphore destroy failed: errno=%d (%s)\n", errno, strerror(errno)); } } } /* * semaphore_posix_thrash() * exercise the semaphore */ static void semaphore_posix_thrash( const char *name, const uint64_t max_ops, uint64_t *counter) { do { int i; for (i = 0; i < 1000; i++) { if (sem_wait(&shared->sem_posix) < 0) { pr_failed_dbg(name, "sem_wait"); break; } (*counter)++; sem_post(&shared->sem_posix); if (!opt_do_run) break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * semaphore_posix_spawn() * spawn a process */ static int semaphore_posix_spawn( const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { semaphore_posix_thrash(name, max_ops, counter); exit(EXIT_SUCCESS); } return pid; } /* * stress_sem_posix() * stress system by POSIX sem ops */ int stress_sem_posix( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_SEMAPHORE_PROCS]; uint64_t i; (void)instance; if (!shared->sem_posix_init) { pr_err(stderr, "%s: aborting, semaphore not initialised\n", name); return EXIT_FAILURE; } memset(pids, 0, sizeof(pids)); for (i = 0; i < opt_semaphore_posix_procs; i++) { pids[i] = semaphore_posix_spawn(name, max_ops, counter); if (pids[i] < 0) goto reap; } semaphore_posix_thrash(name, max_ops, counter); reap: for (i = 0; i < opt_semaphore_posix_procs; i++) { if (pids[i] > 0) { int status; (void)kill(pids[i], SIGKILL); waitpid(pids[i], &status, 0); } } return EXIT_SUCCESS; } stress-ng-0.03.15/stress-chmod.c0000664000175000017500000001144712466243156015050 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" static mode_t modes[] = { #ifdef S_ISUID S_ISUID, #endif #ifdef S_ISGID S_ISGID, #endif #ifdef S_ISVTX S_ISVTX, #endif #ifdef S_IRUSR S_IRUSR, #endif #ifdef S_IWUSR S_IWUSR, #endif #ifdef S_IXUSR S_IXUSR, #endif #ifdef S_IRGRP S_IRGRP, #endif #ifdef S_IWGRP S_IWGRP, #endif #ifdef S_IXGRP S_IXGRP, #endif #ifdef S_IROTH S_IROTH, #endif #ifdef S_IWOTH S_IWOTH, #endif #ifdef S_IXOTH S_IXOTH, #endif 0 }; /* * BSD systems can return EFTYPE which we can ignore * as a "known" error on invalid chmod mode bits */ #ifdef EFTYPE #define CHECK(x) if ((x) && (errno != EFTYPE)) return -1 #else #define CHECK(x) if (x) return -1 #endif /* * do_fchmod() * fchmod the 4 different masks from a mode flag, namely: * mode flag * all mode flags or'd together * inverse mode flag * inverse all mode flags or'd together */ static int do_fchmod(const int fd, const int i, const mode_t mask, const mode_t all_mask) { CHECK(fchmod(fd, modes[i]) < 0); CHECK(fchmod(fd, mask) < 0); CHECK(fchmod(fd, modes[i] ^ all_mask) < 0); CHECK(fchmod(fd, mask ^ all_mask) < 0); return 0; } /* * do_chmod() * chmod the 4 different masks from a mode flag, namely: * mode flag * all mode flags or'd together * inverse mode flag * inverse all mode flags or'd together */ static int do_chmod(const char *filename, const int i, const mode_t mask, const mode_t all_mask) { CHECK(chmod(filename, modes[i]) < 0); CHECK(chmod(filename, mask) < 0); CHECK(chmod(filename, modes[i] ^ all_mask) < 0); CHECK(chmod(filename, mask ^ all_mask) < 0); return 0; } /* * stress_chmod * stress chmod */ int stress_chmod( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t ppid = getppid(); int i, fd = -1, rc = EXIT_FAILURE, retries = 0; mode_t all_mask = 0; char filename[PATH_MAX], dirname[PATH_MAX]; /* * Allow for multiple workers to chmod the *same* file */ stress_temp_dir(dirname, sizeof(dirname), name, ppid, 0); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_failed_err(name, "mkdir"); return EXIT_FAILURE; } } (void)stress_temp_filename(filename, sizeof(filename), name, ppid, 0, 0); do { errno = 0; /* * Try and open the file, it may be impossible momentarily because * other chmod stressors have already created it and changed the * permission bits. If so, wait a while and retry (ugh). */ if ((fd = open(filename, O_CREAT | O_APPEND | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { if (errno == EPERM || errno == EACCES) { (void)usleep(100000); continue; } pr_failed_err(name, "open"); goto tidy; } break; } while (opt_do_run && ++retries < 100); if (retries > 0) pr_dbg(stderr, "%s: chmod: file %s took %d retries to create (instance %" PRIu32 ")\n", name, filename, retries, instance); for (i = 0; modes[i]; i++) all_mask |= modes[i]; do { mode_t mask = 0; for (i = 0; modes[i]; i++) { mask |= modes[i]; if (do_fchmod(fd, i, mask, all_mask) < 0) { pr_fail(stderr, "%s fchmod: errno=%d (%s)\n", name, errno, strerror(errno)); } if (do_chmod(filename, i, mask, all_mask) < 0) { if (errno == ENOENT || errno == ENOTDIR) { /* File was removed during test by another worker */ rc = EXIT_SUCCESS; goto tidy; } pr_fail(stderr, "%s chmod: errno=%d (%s)\n", name, errno, strerror(errno)); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy: (void)fchmod(fd, 0666); if (fd >= 0) (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return rc; } stress-ng-0.03.15/stress-procfs.c0000664000175000017500000000560312466243156015247 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" #define PROC_BUF_SZ (4096) #if defined(__linux__) /* * stress_proc_read() * read a proc file */ static inline void stress_proc_read(const char *path) { int fd, i; char buffer[PROC_BUF_SZ]; if ((fd = open(path, O_RDONLY)) < 0) return; /* Limit to 4K * 4K of data to read per file */ for (i = 0; i < 4096; i++) { if (!opt_do_run) break; if (read(fd, buffer, PROC_BUF_SZ) < PROC_BUF_SZ) break; } (void)close(fd); } /* * stress_proc_dir() * read directory */ static void stress_proc_dir( const char *path, const bool recurse, const int depth) { DIR *dp; struct dirent *d; if (!opt_do_run) return; /* Don't want to go too deep */ if (depth > 8) return; dp = opendir(path); if (dp == NULL) return; while ((d = readdir(dp)) != NULL) { char name[PATH_MAX]; if (!opt_do_run) break; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; switch (d->d_type) { case DT_DIR: if (recurse) { snprintf(name, sizeof(name), "%s/%s", path, d->d_name); stress_proc_dir(name, recurse, depth + 1); } break; case DT_REG: snprintf(name, sizeof(name), "%s/%s", path, d->d_name); stress_proc_read(name); break; default: break; } } (void)closedir(dp); } /* * stress_procfs * stress reading all of /proc */ int stress_procfs( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; do { stress_proc_dir("/proc/self", true, 0); if (!opt_do_run) break; stress_proc_dir("/proc", false, 0); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-poll.c0000664000175000017500000001136612466243156014724 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #define MAX_PIPES (5) #define POLL_BUF (4) /* * pipe_read() * read a pipe with some verification and checking */ static int pipe_read(int fd, int n) { char buf[POLL_BUF]; ssize_t ret; ret = read(fd, buf, sizeof(buf)); if (opt_flags & OPT_FLAGS_VERIFY) { if (ret < 0) { pr_fail(stderr, "pipe read error detected\n"); return ret; } if (ret > 0) { ssize_t i; for (i = 0; i < ret; i++) { if (buf[i] != '0' + n) { pr_fail(stderr, "pipe read error, expecting different data on pipe\n"); return ret; } } } } return ret; } /* * stress_poll() * stress system by rapid polling system calls */ int stress_poll( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int pipefds[MAX_PIPES][2]; int i; pid_t pid; int ret = EXIT_SUCCESS; (void)instance; for (i = 0; i < MAX_PIPES; i++) { if (pipe(pipefds[i]) < 0) { pr_failed_dbg(name, "pipe"); while (--i >= 0) { (void)close(pipefds[i][0]); (void)close(pipefds[i][1]); } return EXIT_FAILURE; } } pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); ret = EXIT_FAILURE; goto tidy; } else if (pid == 0) { /* Child writer */ for (i = 0; i < MAX_PIPES; i++) (void)close(pipefds[i][0]); do { char buf[POLL_BUF]; ssize_t ret; /* Write on a randomly chosen pipe */ i = (mwc() >> 8) % MAX_PIPES; memset(buf, '0' + i, sizeof(buf)); ret = write(pipefds[i][1], buf, sizeof(buf)); if (ret < (ssize_t)sizeof(buf)) { pr_failed_dbg(name, "write"); goto abort; } } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: for (i = 0; i < MAX_PIPES; i++) (void)close(pipefds[i][1]); exit(EXIT_SUCCESS); } else { /* Parent read */ int maxfd = 0, status; struct pollfd fds[MAX_PIPES]; fd_set rfds; FD_ZERO(&rfds); for (i = 0; i < MAX_PIPES; i++) { fds[i].fd = pipefds[i][0]; fds[i].events = POLLIN; fds[i].revents = 0; FD_SET(pipefds[i][0], &rfds); if (pipefds[i][0] > maxfd) maxfd = pipefds[i][0]; } do { struct timeval tv; int ret; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; /* First, stress out poll */ ret = poll(fds, MAX_PIPES, 1); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0) && (errno != EINTR)) { pr_fail(stderr, "poll failed with error: %d (%s)\n", errno, strerror(errno)); } if (ret > 0) { for (i = 0; i < MAX_PIPES; i++) { if (fds[i].revents == POLLIN) { pipe_read(fds[i].fd, i); } } (*counter)++; } if (!opt_do_run || (max_ops && *counter >= max_ops)) break; /* Second, stress out select */ tv.tv_sec = 0; tv.tv_usec = 20000; ret = select(maxfd + 1, &rfds, NULL, NULL, &tv); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret < 0) && (errno != EINTR)) { pr_fail(stderr, "select failed with error: %d (%s)\n", errno, strerror(errno)); } if (ret > 0) { for (i = 0; i < MAX_PIPES; i++) { if (FD_ISSET(pipefds[i][0], &rfds)) { if (pipe_read(pipefds[i][0], i) < 0) break; } FD_SET(pipefds[i][0], &rfds); } (*counter)++; } if (!opt_do_run || (max_ops && *counter >= max_ops)) break; /* Third, stress zero sleep, this is like a select zero timeout */ (void)sleep(0); } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } tidy: for (i = 0; i < MAX_PIPES; i++) { (void)close(pipefds[i][0]); (void)close(pipefds[i][1]); } return ret; } stress-ng-0.03.15/stress-sysinfo.c0000664000175000017500000000575012466243156015450 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #if defined (__linux__) #include #include #endif #include #include "stress-ng.h" #define check_do_run() \ if (!opt_do_run) \ break; \ /* * stress on system information * stress system by rapid fetches of system information */ int stress_sysinfo( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int n_mounts; char *mnts[128]; (void)instance; n_mounts = mount_get(mnts, SIZEOF_ARRAY(mnts)); if (n_mounts < 0) { pr_err(stderr, "%s: failed to get mount points\n", name); return EXIT_FAILURE; } pr_dbg(stderr, "%s: found %d mount points\n", name, n_mounts); do { struct tms tms_buf; clock_t clk; #if defined (__linux__) int ret; struct sysinfo sysinfo_buf; struct statfs statfs_buf; int i; #endif #if defined (__linux__) ret = sysinfo(&sysinfo_buf); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: sysinfo failed: errno=%d (%s)\n", name, errno, strerror(errno)); } check_do_run(); for (i = 0; i < n_mounts; i++) { check_do_run(); if (!mnts[i]) continue; ret = statfs(mnts[i], &statfs_buf); /* Mount may have been removed, so purge it */ if ((ret < 0) && (errno == ENOENT)) { free(mnts[i]); mnts[i] = NULL; continue; } if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { if (errno != ENOSYS && errno != EOVERFLOW) { pr_fail(stderr, "%s: statfs on %s failed: errno=%d (%s)\n", name, mnts[i], errno, strerror(errno)); } } } check_do_run(); #endif clk = times(&tms_buf); if ((clk == (clock_t)-1) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: times failed: errno=%d (%s)\n", name, errno, strerror(errno)); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); mount_free(mnts, n_mounts); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-sigfpe.c0000664000175000017500000000436012466243156015227 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" static sigjmp_buf jmp_env; /* * stress_fpehandler() * SIGFPE handler */ static void stress_fpehandler(int dummy) { (void)dummy; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } /* * stress_sigfpe * stress by generating floating point errors */ int stress_sigfpe( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; for (;;) { struct sigaction new_action; int ret; memset(&new_action, 0, sizeof new_action); new_action.sa_handler = stress_fpehandler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGFPE, &new_action, NULL) < 0) { pr_failed_err(name, "sigfpe"); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); /* * We return here if we get SIGFPE, so * first check if we need to terminate */ if (!opt_do_run || (max_ops && *counter >= max_ops)) break; if (ret) (*counter)++; /* SIGFPE occurred */ else uint64_put(1 / uint64_zero()); /* force division by zero */ } return EXIT_SUCCESS; } stress-ng-0.03.15/limit.c0000664000175000017500000000434612466243156013553 0ustar kingking/* * Copyright (C) 2014-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" static const int limits[] = { #ifdef RLIMIT_AS RLIMIT_AS, #endif #ifdef RLIMIT_CPU RLIMIT_CPU, #endif #ifdef RLIMIT_DATA RLIMIT_DATA, #endif #ifdef RLIMIT_FSIZE RLIMIT_FSIZE, #endif #ifdef RLIMIT_LOCKS RLIMIT_LOCKS, #endif #ifdef RLIMIT_MEMLOCK RLIMIT_MEMLOCK, #endif #ifdef RLIMIT_MSGQUEUE RLIMIT_MSGQUEUE, #endif #ifdef RLIMIT_NICE RLIMIT_NICE, #endif #ifdef RLIMIT_NOFILE RLIMIT_NOFILE, #endif #ifdef RLIMIT_NPROC RLIMIT_NPROC, #endif #ifdef RLIMIT_RSS RLIMIT_RSS, #endif #ifdef RLIMIT_RTPRIO RLIMIT_RTPRIO, #endif #ifdef RLIMIT_RTTIME RLIMIT_RTTIME, #endif #ifdef RLIMIT_SIGPENDING RLIMIT_SIGPENDING, #endif #ifdef RLIMIT_STACK RLIMIT_STACK #endif }; /* * set_max_limits() * push rlimits to maximum values allowed * so we can stress a system to the maximum, * we ignore any rlimit errors. */ void set_max_limits(void) { size_t i; for (i = 0; i < SIZEOF_ARRAY(limits); i++) { struct rlimit rlim; if (getrlimit(limits[i], &rlim) < 0) continue; rlim.rlim_cur = rlim.rlim_max; (void)setrlimit(limits[i], &rlim); } } stress-ng-0.03.15/stress-eventfd.c0000664000175000017500000000540112466243156015402 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined (__linux__) #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_eventfd * stress eventfd read/writes */ int stress_eventfd( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int fd1, fd2; (void)instance; fd1 = eventfd(0, 0); if (fd1 < 0) { pr_failed_dbg(name, "eventfd"); return EXIT_FAILURE; } fd2 = eventfd(0, 0); if (fd1 < 0) { pr_failed_dbg(name, "eventfd"); (void)close(fd1); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); (void)close(fd1); (void)close(fd2); return EXIT_FAILURE; } else if (pid == 0) { for (;;) { uint64_t val; if (read(fd1, &val, sizeof(val)) < (ssize_t)sizeof(val)) { pr_failed_dbg(name, "child read"); break; } val = 1; if (write(fd2, &val, sizeof(val)) < (ssize_t)sizeof(val)) { pr_failed_dbg(name, "child write"); break; } } (void)close(fd1); (void)close(fd2); exit(EXIT_SUCCESS); } else { int status; do { uint64_t val = 1; if (write(fd1, &val, sizeof(val)) < (ssize_t)sizeof(val)) { if (errno != EINTR) pr_failed_dbg(name, "parent write"); break; } if (read(fd2, &val, sizeof(val)) < (ssize_t)sizeof(val)) { if (errno != EINTR) pr_failed_dbg(name, "parent read"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); (void)close(fd1); (void)close(fd2); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-mincore.c0000664000175000017500000000510312466243156015402 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) #define VEC_MAX_SIZE (64) /* * stress_mincore() * stress mincore system call */ int stress_mincore( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { volatile uint8_t *addr = 0; const size_t page_size = stress_get_pagesize(); const ptrdiff_t mask = ~(page_size - 1); (void)instance; do { int i; for (i = 0; (i < 100) && opt_do_run; i++) { int ret, redo = 0; unsigned char vec[1]; if (opt_flags & OPT_FLAGS_MINCORE_RAND) if (addr < (uint8_t *)page_size) addr = (uint8_t *)((ptrdiff_t)(mwc() & mask)); redo: errno = 0; ret = mincore((void *)addr, page_size, vec); if (ret < 0) { switch (errno) { case ENOMEM: /* Page not mapped */ break; case EAGAIN: if (++redo < 100) goto redo; /* fall through */ default: pr_fail(stderr, "%s: mincore on address %p error: %d %s\n ", name, addr, errno, strerror(errno)); return EXIT_FAILURE; } } if (opt_flags & OPT_FLAGS_MINCORE_RAND) addr = (uint8_t *)(ptrdiff_t) (((ptrdiff_t)addr >> 1) & mask); else addr += page_size; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-clock.c0000664000175000017500000001170512466243156015046 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #if _POSIX_C_SOURCE >= 199309L #include "stress-ng.h" static const int clocks[] = { #ifdef CLOCK_REALTIME CLOCK_REALTIME, #endif #ifdef CLOCK_REALTIME_COARSE CLOCK_REALTIME_COARSE, #endif #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC, #endif #ifdef CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC_RAW, #endif #ifdef CLOCK_BOOTTIME CLOCK_BOOTTIME, #endif #ifdef CLOCK_PROCESS_CPUTIME_ID CLOCK_PROCESS_CPUTIME_ID, #endif #ifdef CLOCK_THREAD_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID #endif }; #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) static const int clocks_nanosleep[] = { #ifdef CLOCK_REALTIME CLOCK_REALTIME, #endif #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC #endif }; #endif static const int timers[] = { #ifdef CLOCK_REALTIME CLOCK_REALTIME, #endif #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC #endif }; /* * stress_clock() * stress system by rapid clocking system calls */ int stress_clock( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; do { size_t i; struct timespec t; int ret; /* * Exercise clock_getres and clock_gettime for each clock */ for (i = 0; i < SIZEOF_ARRAY(clocks); i++) { ret = clock_getres(clocks[i], &t); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: clock_getres failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); ret = clock_gettime(clocks[i], &t); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: clock_gettime failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); } #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) /* * Exercise clock_nanosleep for each clock */ for (i = 0; i < SIZEOF_ARRAY(clocks_nanosleep); i++) { t.tv_sec = 0; t.tv_nsec = 0; /* * Calling with TIMER_ABSTIME will force * clock_nanosleep() to return immediately */ ret = clock_nanosleep(clocks_nanosleep[i], TIMER_ABSTIME, &t, NULL); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: clock_nanosleep failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); } #endif #if _POSIX_C_SOURCE >= 199309L && defined(__linux__) /* * Stress the timers */ for (i = 0; i < SIZEOF_ARRAY(timers); i++) { timer_t timer_id; struct itimerspec its; struct sigevent sevp; int64_t loops = 1000000; memset(&sevp, 0, sizeof(sevp)); sevp.sigev_notify = SIGEV_NONE; ret = timer_create(timers[i], &sevp, &timer_id); if (ret < 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "%s: timer_create failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); continue; } /* One shot mode, for 50000 ns */ its.it_value.tv_sec = 0; its.it_value.tv_nsec = 50000; its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; ret = timer_settime(timer_id, 0, &its, NULL); if (ret < 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "%s: timer_settime failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); goto timer_delete; } do { ret = timer_gettime(timer_id, &its); if (ret < 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "%s: timer_gettime failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); goto timer_delete; } loops--; } while ((loops > 0) && opt_do_run && (its.it_value.tv_nsec != 0)); timer_delete: ret = timer_delete(timer_id); if (ret < 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "%s: timer_delete failed for timer %zu, errno=%d (%s)\n", name, i, errno, strerror(errno)); break; } } #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/mounts.c0000664000175000017500000000453112466243156013756 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include "stress-ng.h" /* * mount_add() * add a new mount point to table */ int mount_add( char *mnts[], const int max, int *n, const char *name) { char *mnt; if (*n >= max) return 0; mnt = strdup(name); if (mnt == NULL) return -1; mnts[*n] = mnt; (*n)++; return 0; } /* * mount_free() * free mount info */ void mount_free(char *mnts[], const int n) { int i; for (i = 0; i < n; i++) { free(mnts[i]); mnts[i] = NULL; } } /* * mount_get() * populate mnts with up to max mount points * from /etc/mtab */ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) int mount_get(char *mnts[], const int max) { int n = 0; mount_add(mnts, max, &n, "/"); mount_add(mnts, max, &n, "/dev"); mount_add(mnts, max, &n, "/tmp"); return n; } #else int mount_get(char *mnts[], const int max) { FILE *mounts; struct mntent* mount; int n = 0; mounts = setmntent("/etc/mtab", "r"); /* Failed, so assume / is available */ if (mounts == NULL) { mount_add(mnts, max, &n, "/"); return n; } while ((mount = getmntent(mounts)) != NULL) mount_add(mnts, max, &n, mount->mnt_dir); (void)endmntent(mounts); return n; } #endif stress-ng-0.03.15/time.c0000664000175000017500000000270012466243156013363 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include /* * timeval_to_double() * convert timeval to seconds as a double */ double timeval_to_double(const struct timeval *tv) { return (double)tv->tv_sec + ((double)tv->tv_usec / 1000000.0); } /* * time_now() * time in seconds as a double */ double time_now(void) { struct timeval now; gettimeofday(&now, NULL); return timeval_to_double(&now); } stress-ng-0.03.15/Makefile0000664000175000017500000000716312466243156013731 0ustar kingking# # Copyright (C) 2013-2015 Canonical, Ltd. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # VERSION=0.03.15 # # Codename "stressed silicon" # CFLAGS += -Wall -Wextra -DVERSION='"$(VERSION)"' -O2 BINDIR=/usr/bin MANDIR=/usr/share/man/man1 SRC = stress-affinity.c \ stress-aio.c \ stress-bigheap.c \ stress-brk.c \ stress-bsearch.c \ stress-cache.c \ stress-chmod.c \ stress-clock.c \ stress-cpu.c \ stress-dentry.c \ stress-dir.c \ stress-dup.c \ stress-epoll.c \ stress-eventfd.c \ stress-fallocate.c \ stress-fault.c \ stress-fifo.c \ stress-flock.c \ stress-fork.c \ stress-fstat.c \ stress-futex.c \ stress-get.c \ stress-hdd.c \ stress-hsearch.c \ stress-inotify.c \ stress-iosync.c \ stress-kill.c \ stress-lease.c \ stress-lsearch.c \ stress-link.c \ stress-lockf.c \ stress-malloc.c \ stress-memcpy.c \ stress-mincore.c \ stress-mmap.c \ stress-mremap.c \ stress-msg.c \ stress-mq.c \ stress-nice.c \ stress-noop.c \ stress-null.c \ stress-open.c \ stress-pipe.c \ stress-poll.c \ stress-procfs.c \ stress-pthread.c \ stress-qsort.c \ stress-rdrand.c \ stress-rename.c \ stress-seek.c \ stress-sem.c \ stress-sem-sysv.c \ stress-sendfile.c \ stress-shm-sysv.c \ stress-sigfd.c \ stress-sigfpe.c \ stress-sigsegv.c \ stress-sigq.c \ stress-socket.c \ stress-splice.c \ stress-stack.c \ stress-switch.c \ stress-sysinfo.c \ stress-timer.c \ stress-tsearch.c \ stress-udp.c \ stress-urandom.c \ stress-utime.c \ stress-vecmath.c \ stress-vm.c \ stress-vm-rw.c \ stress-vm-splice.c \ stress-wait.c \ stress-yield.c \ stress-zero.c \ coredump.c \ helper.c \ io-priority.c \ limit.c \ log.c \ madvise.c \ mincore.c \ mounts.c \ mwc.c \ net.c \ out-of-memory.c \ parse-opts.c \ proc-name.c \ sched.c \ time.c \ stress-ng.c OBJS = $(SRC:.c=.o) .SUFFIXES: .c .o .o: stress-ng.h Makefile .c.o: stress-ng.h Makefile $(SRC) @echo $(CC) $(CFLAGS) -c -o $@ $< @$(CC) $(CFLAGS) -c -o $@ $< stress-ng: $(OBJS) $(CC) $(CPPFLAGS) $(CFLAGS) $(OBJS) -lm -lpthread -lrt -o $@ $(LDFLAGS) stress-cpu.o: stress-cpu.c @echo $(CC) $(CFLAGS) -c -o $@ $< @echo "_Decimal32 x;" > test-decimal.c @$(CC) $(CPPFLAGS) -c -o test-decimal.o test-decimal.c 2> /dev/null || true @if [ -e test-decimal.o ]; then \ $(CC) $(CFLAGS) -DSTRESS_FLOAT_DECIMAL -c -o $@ $< ;\ else \ $(CC) $(CFLAGS) -c -o $@ $< ;\ fi @rm -f test-decimal.c test-decimal.o $(OBJS): stress-ng.h Makefile stress-ng.1.gz: stress-ng.1 gzip -c $< > $@ dist: rm -rf stress-ng-$(VERSION) mkdir stress-ng-$(VERSION) cp -rp Makefile $(SRC) stress-ng.h stress-ng.1 \ COPYING syscalls.txt mascot \ stress-ng-$(VERSION) tar -zcf stress-ng-$(VERSION).tar.gz stress-ng-$(VERSION) rm -rf stress-ng-$(VERSION) clean: rm -f stress-ng $(OBJS) stress-ng.1.gz rm -f stress-ng-$(VERSION).tar.gz rm -f test-decimal.c install: stress-ng stress-ng.1.gz mkdir -p ${DESTDIR}${BINDIR} cp stress-ng ${DESTDIR}${BINDIR} mkdir -p ${DESTDIR}${MANDIR} cp stress-ng.1.gz ${DESTDIR}${MANDIR} stress-ng-0.03.15/stress-aio.c0000664000175000017500000001353212466243156014523 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined (__linux__) #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" #define BUFFER_SZ (16) static uint64_t opt_aio_requests = DEFAULT_AIO_REQUESTS; /* per request async I/O data */ typedef struct { int request; /* Request slot */ int status; /* AIO error status */ struct aiocb aiocb; /* AIO cb */ uint8_t buffer[BUFFER_SZ]; /* Associated read/write buffer */ volatile uint64_t count; /* Signal handled count */ } io_req_t; void stress_set_aio_requests(const char *optarg) { opt_aio_requests = get_uint64(optarg); check_range("aio-requests", opt_aio_requests, MIN_AIO_REQUESTS, MAX_AIO_REQUESTS); } /* * aio_fill_buffer() * fill buffer with some known pattern */ static inline void aio_fill_buffer( const int request, uint8_t *const buffer, const size_t size) { register size_t i; for (i = 0; i < size; i++) buffer[i] = request + i; } /* * aio_signal_handler() * handle an async I/O signal */ static void aio_signal_handler(int sig, siginfo_t *si, void *ucontext) { io_req_t *io_req = (io_req_t *)si->si_value.sival_ptr; (void)sig; (void)si; (void)ucontext; if (io_req) io_req->count++; } /* * aio_issue_cancel() * cancel an in-progress async I/O request */ static void aio_issue_cancel(io_req_t *io_req) { int ret; if (io_req->status != EINPROGRESS) return; ret = aio_cancel(io_req->aiocb.aio_fildes, &io_req->aiocb); switch (ret) { case AIO_CANCELED: case AIO_ALLDONE: break; case AIO_NOTCANCELED: pr_dbg(stderr, "async I/O request %d not cancelled\n", io_req->request); break; default: pr_err(stderr, "%d error: %d %s\n", io_req->request, errno, strerror(errno)); } } /* * issue_aio_request() * construct an AIO request and action it */ static int issue_aio_request( const int fd, const off_t offset, io_req_t *const io_req, const int request, int (*aio_func)(struct aiocb *aiocbp) ) { int ret; io_req->request = request; io_req->status = EINPROGRESS; io_req->aiocb.aio_fildes = fd; io_req->aiocb.aio_buf = io_req->buffer; io_req->aiocb.aio_nbytes = BUFFER_SZ; io_req->aiocb.aio_reqprio = 0; io_req->aiocb.aio_offset = offset; io_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; io_req->aiocb.aio_sigevent.sigev_signo = SIGUSR1; io_req->aiocb.aio_sigevent.sigev_value.sival_ptr = io_req; ret = aio_func(&io_req->aiocb); if (ret < 0) { pr_err(stderr, "failed to issue aio request: %d (%s)\n", errno, strerror(errno)); } return ret; } /* * stress_aio * stress asynchronous I/O */ int stress_aio( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd, rc = EXIT_FAILURE; io_req_t *io_reqs; struct sigaction sa; uint64_t i, total = 0; char filename[PATH_MAX]; const pid_t pid = getpid(); if ((io_reqs = calloc((size_t)opt_aio_requests, sizeof(io_req_t))) == NULL) { pr_err(stderr, "%s: cannot allocate io request structures\n", name); return EXIT_FAILURE; } if (stress_temp_dir_mk(name, pid, instance) < 0) { free(io_reqs); return EXIT_FAILURE; } (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); goto finish; } (void)unlink(filename); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_SIGINFO; sa.sa_sigaction = aio_signal_handler; if (sigaction(SIGUSR1, &sa, NULL) < 0) { pr_failed_err(name, "sigaction"); } /* Kick off requests */ for (i = 0; i < opt_aio_requests; i++) { aio_fill_buffer(i, io_reqs[i].buffer, BUFFER_SZ); if (issue_aio_request(fd, i * BUFFER_SZ, &io_reqs[i], i, aio_write) < 0) goto cancel; } do { usleep(250000); /* wait until a signal occurs */ for (i = 0; i < opt_aio_requests; i++) { if (io_reqs[i].status != EINPROGRESS) continue; io_reqs[i].status = aio_error(&io_reqs[i].aiocb); switch (io_reqs[i].status) { case ECANCELED: case 0: /* Succeeded or cancelled, so redo another */ (*counter)++; if (issue_aio_request(fd, i * BUFFER_SZ, &io_reqs[i], i, (mwc() & 0x20) ? aio_read : aio_write) < 0) goto cancel; break; case EINPROGRESS: break; default: /* Something went wrong */ pr_failed_err(name, "aio_error"); goto cancel; } } } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; cancel: for (i = 0; i < opt_aio_requests; i++) { aio_issue_cancel(&io_reqs[i]); total += io_reqs[i].count; } (void)close(fd); finish: pr_dbg(stderr, "total of %" PRIu64 " async I/O signals caught (instance %d)\n", total, instance); (void)stress_temp_dir_rm(name, pid, instance); free(io_reqs); return rc; } #endif stress-ng-0.03.15/stress-ng.10000664000175000017500000016373212466243156014305 0ustar kingking.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH STRESS-NG 1 "January 2, 2014" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .\" .\" left margin - right margin minus a fudge factor .nr SZ ((\n[.l] - \n[.i]) / 1n - 31) .nr SM ((\n[.l] - \n[.i]) / 1n - 41) .nr SV ((\n[.l] - \n[.i]) / 1n - 30) .SH NAME stress\-ng \- a tool to load and stress a computer system .br .SH SYNOPSIS .B stress\-ng [\fIOPTION \fR[\fIARG\fR]] ... .br .SH DESCRIPTION stress\-ng will stress test a computer system in various selectable ways. It was designed to exercise various physical subsystems of a computer as well as the various operating system kernel interfaces. stress-ng also has a wide range of CPU specific stress tests that exercise floating point, integer, bit manipulation and control flow. .PP stress-ng was originally intended to make a machine work hard and trip hardware issues such as thermal overruns as well as operating system bugs that only occur when a system is being thrashed hard. Use stress-ng with caution as some of the tests can make a system run hot on poorly designed hardware and also can cause excessive system thrashing which may be difficult to stop. .PP stress-ng can also measure test throughput rates; this can be useful to observe performance changes across different operating system releases or types of hardware. However, it has never been intended to be used as a precise benchmark test suite, so do NOT use it in this manner. .PP Running stress-ng with root privileges will adjust out of memory settings on Linux systems to make the stressors unkillable in low memory situations, so use this judiciously. With the appropriate privilege, stress-ng can allow the ionice class and ionice levels to be adjusted, again, this should be used with care. .PP One can specify the number of processes to invoke per type of stress test; specifying a negative or zero value will select the number of online processors as defined by sysconf(_SC_NPROCESSORS_ONLN). .SH OPTIONS .TP .B \-\-affinity N start N processes that rapidly change CPU affinity (only on Linux). Rapidly switching CPU affinity can contribute to poor cache behaviour. .TP .B \-\-affinity\-ops N stop affinity processes after N bogo affinity operations (only on Linux). .TP .B \-\-affinity\-rand switch CPU affinity randomly rather than the default of sequentially. .TP .B \-\-aio N start N processes that issue multiple small asynchronous I/O writes and reads on a relatively small temporary file. This will just hit the file system cache and soak up a lot of user and kernel time in issuing and handling I/O requests. By default, each process will handle 16 concurrent I/O requests. .TP .B \-\-aio\-ops N stop asynchronous I/O workers after N bogo asynchronous I/O requests. .TP .B \-\-aio\-requests N specify the number of asynchronous I/O requests each process should issue, the default is 16; 1 to 4096 are allowed. .TP .B \-a N, \-\-all N start N instances of each stress test. .TP .B \-b N, \-\-backoff N wait N microseconds between the start of each stress process. This allows one to ramp up the stress tests over time. .TP .B \-B N, \-\-bigheap N start N processes that grow their heaps by reallocating memory. If the out of memory killer (OOM) on Linux kills the process or the allocation fails then the allocating process starts all over again. Note that the OOM adjustment for the process is set so that the OOM killer will treat these processes as the first candidate processes to kill. .TP .B \-\-bigheap\-ops N stop the big heap processes after N bogo allocation operations are completed. .TP .B \-\-bigheap\-growth N specify amount of memory to grow heap by per iteration. Size can be from 4K to 64MB. Default is 64K. .TP .B \-\-brk N start N processes that grow the data segment by one page at a time using multiple brk(2) calls. Each successfully allocated new page is touched to ensure it is resident in memory. If an out of memory condition occurs then the test will reset the data segment to the point before it started and repeat the data segment resizing over again. The process adjusts the out of memory setting so that it may be killed by the out of memory (OOM) killer before other processes. If it is killed by the OOM killer then it will be automatically re-started by a monitoring parent process. .TP .B \-\-brk\-ops N stop the brk stressor after N bogo brk operations. .TP .B \-\-brk\-notouch do not touch each newly allocated data segment page. This disables the default of touching each newly allocated page and hence avoids the kernel from necessarily backing the page with real physical memory. .TP .B \-\-bsearch N start N processes that binary search a sorted array of 32 bit integers using bsearch(3). By default, there are 65536 elements in the array. This is a useful method to exercise random access of memory and processor cache. .TP .B \-\-bsearch\-ops N stop the bsearch processes after N bogo bsearch operations are completed. .TP .B \-\-bsearch\-size N specify the size (number of 32 bit integers) in the array to bsearch. Size can be from 1K to 4M. .TP .B \-C N, \-\-cache N start N processes that perform random wide spread memory read and writes to thrash the CPU cache. The code does not intelligently determine the CPU cache configuration and so it may be sub-optimal in producing hit-miss read/write activity for some processors. .TP .B \-\-cache\-fence force write serialization on each store operation (x86 only). This is a no-op for non-x86 architectures. .TP .B \-\-cache\-flush force flush cache on each store operation (x86 only). This is a no-op for non-x86 architectures. .TP .B \-\-cache\-ops N stop cache thrash processes after N bogo cache thrash operations. .TP .B \-\-chmod N start N processes that change the file mode bits via chmod(2) and fchmod(2) on the same file. The greater the value for N then the more contention on the single file. The stressor will work through all the combination of mode bits. .TP .B \-\-chmod\-ops N stop after N chmod bogo operations. .TP .B \-\-class name specify the class of stressors to run. Stressors are classified into one or more of the following classes: cpu, cpu-cache, io, interrupt, memory, network, os, scheduler and vm. Some stressors fall into just one class. For example the 'get' stressor is just in the 'os' class. Other stressors fall into more than one class, for example, the 'lsearch' stressor falls into the 'cpu', 'cpu-cache' and 'memory' classes as it exercises all these three. Selecting a specific class will run all the stressors that fall into that class only when run with the \-\-sequential option. .TP .B \-\-clock N start N processes exercising clocks and POSIX timers. For all known clock types this will exercise clock_getres(2), clock_gettime(2) and clock_nanosleep(2). For all known timers it will create a 50000ns timer and busy poll this until it expires. This stressor will cause frequent context switching. .TP .B \-\-clock\-ops N stop clock stress processes after N bogo operations. .TP .B \-c N, \-\-cpu N start N processes exercising the CPU by sequentially working through all the different CPU stress methods. Instead of exercising all the CPU stress methods, one can specify a specific CPU stress method with the \-\-cpu\-method option. .TP .B \-\-cpu\-ops N stop cpu stress processes after N bogo operations. .TP .B \-l P, \-\-cpu\-load P load CPU with P percent loading. 0 is effectively a sleep (no load) and 100 is full loading. The loading loop is broken into compute time (load%) and sleep time (100% - load%). Accuracy depends on the overall load of the processor and the responsiveness of the scheduler, so the actual load may be different from the desired load. Note that the number of bogo CPU operations may not be linearly scaled with the load as some systems employ CPU frequency scaling and so heavier loads produce an increased CPU frequency and greater CPU bogo operations. .TP .B \-\-cpu\-method method specify a cpu stress method. By default, all the stress methods are exercised sequentially, however one can specify just one method to be used if required. Available cpu stress methods are described as follows: .TS expand; lB2 lBw(\n[SZ]n) l l. Method Description all T{ iterate over all the below cpu stress methods T} ackermann T{ Ackermann function: compute A(3, 10), where: A(m, n) = n + 1 if m = 0; A(m - 1, 1) if m > 0 and n = 0; A(m - 1, A(m, n - 1)) if m > 0 and n > 0 T} bitops T{ various bit operations from bithack, namely: reverse bits, parity check, bit count, round to nearest power of 2 T} cfloat T{ 1000 iterations of a mix of floating point complex operations T} cdouble T{ 1000 iterations of a mix of double floating point complex operations T} clongdouble T{ 1000 iterations of a mix of long double floating point complex operations T} correlate T{ perform a 16384 \(mu 1024 correlation of random doubles T} crc T{ compute 1024 rounds of CCITT CRC16 on random data T} decimal32 T{ 1000 iterations of a mix of 32 bit decimal floating point operations (GCC only) T} decimal64 T{ 1000 iterations of a mix of 64 bit decimal floating point operations (GCC only) T} decimal128 T{ 1000 iterations of a mix of 128 bit decimal floating point operations (GCC only) T} djb2a T{ 128 rounds of hash DJB2a (Dan Bernstein hash using the xor variant) on 128 to 1 bytes of random strings T} double T{ 1000 iterations of a mix of double precision floating point operations T} euler T{ compute e using n \[eq] (1 + (1 \[di] n)) \[ua] n T} explog T{ iterate on n \[eq] exp(log(n) \[di] 1.00002) T} fibonacci T{ compute Fibonacci sequence of 0, 1, 1, 2, 5, 8... T} fft T{ 4096 sample Fast Fourier Transform T} float T{ 1000 iterations of a mix of floating point operations T} fnv1a T{ 128 rounds of hash FNV-1a (Fowler–Noll–Vo hash using the xor then multiply variant) on 128 to 1 bytes of random strings T} gamma T{ calculate the Euler\-Mascheroni constant \(*g using the limiting difference between the harmonic series (1 + 1/2 + 1/3 + 1/4 + 1/5 ... + 1/n) and the natural logarithm ln(n), for n = 80000. T} gcd T{ compute GCD of integers T} gray T{ calculate binary to gray code and gray code back to binary for integers from 0 to 65535 T} hamming T{ compute Hamming H(8,4) codes on 262144 lots of 4 bit data. This turns 4 bit data into 8 bit Hamming code containing 4 parity bits. For data bits d1..d4, parity bits are computed as: p1 = d2 + d3 + d4 p2 = d1 + d3 + d4 p3 = d1 + d2 + d4 p4 = d1 + d2 + d3 T} hanoi T{ solve a 21 disc Towers of Hanoi stack using the recursive solution T} hyperbolic T{ compute sinh(\(*h) \(mu cosh(\(*h) + sinh(2\(*h) + cosh(3\(*h) for float, double and long double hyperbolic sine and cosine functions where \(*h = 0 to 2\(*p in 1500 steps T} idct T{ 8 \(mu 8 IDCT (Inverse Discrete Cosine Transform) T} int8 T{ 1000 iterations of a mix of 8 bit integer operations T} int16 T{ 1000 iterations of a mix of 16 bit integer operations T} int32 T{ 1000 iterations of a mix of 32 bit integer operations T} int64 T{ 1000 iterations of a mix of 64 bit integer operations T} int128 T{ 1000 iterations of a mix of 128 bit integer operations (GCC only) T} int32float T{ 1000 iterations of a mix of 32 bit integer and floating point operations T} int32double T{ 1000 iterations of a mix of 32 bit integer and double precision floating point operations T} int32longdouble T{ 1000 iterations of a mix of 32 bit integer and long double precision floating point operations T} int64float T{ 1000 iterations of a mix of 64 bit integer and floating point operations T} int64double T{ 1000 iterations of a mix of 64 bit integer and double precision floating point operations T} int64longdouble T{ 1000 iterations of a mix of 64 bit integer and long double precision floating point operations T} int128float T{ 1000 iterations of a mix of 128 bit integer and floating point operations (GCC only) T} int128double T{ 1000 iterations of a mix of 128 bit integer and double precision floating point operations (GCC only) T} int128longdouble T{ 1000 iterations of a mix of 128 bit integer and long double precision floating point operations (GCC only) T} int128decimal32 T{ 1000 iterations of a mix of 128 bit integer and 32 bit decimal floating point operations (GCC only) T} int128decimal64 T{ 1000 iterations of a mix of 128 bit integer and 64 bit decimal floating point operations (GCC only) T} int128decimal128 T{ 1000 iterations of a mix of 128 bit integer and 128 bit decimal floating point operations (GCC only) T} jenkin T{ Jenkin's integer hash on 128 rounds of 128..1 bytes of random data T} jmp T{ Simple unoptimised compare >, <, == and jmp branching T} ln2 T{ compute ln(2) based on series: 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 ... T} longdouble T{ 1000 iterations of a mix of long double precision floating point operations T} loop T{ simple empty loop T} matrixprod T{ matrix product of two 128 \(mu 128 matrices of double floats. Testing on 64 bit x86 hardware shows that this is provides a good mix of memory, cache and floating point operations and is probably the best CPU method to use to make a CPU run hot. T} nsqrt T{ compute sqrt() of long doubles using Newton-Raphson T} omega T{ compute the omega constant defined by \(*We\[ua]\(*W = 1 using efficient iteration of \(*Wn+1 = (1 + \(*Wn) / (1 + e\[ua]\(*Wn) T} phi T{ compute the Golden Ratio \(*f using series T} pi T{ compute \(*p using the Srinivasa Ramanujan fast convergence algorithm T} pjw T{ 128 rounds of hash pjw function on 128 to 1 bytes of random strings T} prime T{ find all the primes in the range 1..1000000 using a slightly optimised brute force na\[:i]ve trial division search T} psi T{ compute \(*q (the reciprocal Fibonacci constant) using the sum of the reciprocals of the Fibonacci numbers T} rand T{ 16384 iterations of rand(), where rand is the MWC pseudo random number generator. The MWC random function concatenates two 16 bit multiply\-with\-carry generators: x(n) = 36969 \(mu x(n - 1) + carry, y(n) = 18000 \(mu y(n - 1) + carry mod 2 \[ua] 16 .br and has period of around 2 \[ua] 60 T} rgb T{ convert RGB to YUV and back to RGB (CCIR 601) T} sdbm T{ 128 rounds of hash sdbm (as used in the SDBM database and GNU awk) on 128 to 1 bytes of random strings T} sieve T{ find the primes in the range 1..10000000 using the sieve of Eratosthenes T} sqrt T{ compute sqrt(rand()), where rand is the MWC pseudo random number generator T} trig T{ compute sin(\(*h) \(mu cos(\(*h) + sin(2\(*h) + cos(3\(*h) for float, double and long double sine and cosine functions where \(*h = 0 to 2\(*p in 1500 steps T} zeta T{ compute the Riemann Zeta function \[*z](s) for s = 2.0..10.0 T} .TE .RS .PP Note that some of these methods try to exercise the CPU with computations found in some real world use cases. However, the code has not been optimised on a per-architecture basis, so may be a sub-optimal compared to hand-optimised code used in some applications. They do try to represent the typical instruction mixes found in these use cases. .RE .TP .B \-D N, \-\-dentry N start N processes that create and remove directory entries. This should create file system meta data activity. The directory entry names are suffixed by a gray-code encoded number to try to mix up the hashing of the namespace. .TP .B \-\-dentry\-ops N stop denty thrash processes after N bogo dentry operations. .TP .B \-\-dentry\-order O specify unlink order of dentries, can be one of forward, reverse or stride. By default, dentries are unlinked in the order they were created, however, the reverse order option will unlink them from last to first and the stride option will unlink them by stepping around order in a quasi-random pattern. .TP .B \-\-dentries N create N dentries per dentry thrashing loop, default is 2048. .TP .B \-\-dir N start N processes that create and remove directories using mkdir and rmdir. .TP .B \-\-dir\-ops N stop directory thrash processes after N bogo directory operations. .TP .B \-n, \-\-dry\-run parse options, but don't run stress tests. A no-op. .TP .B \-\-dup N start N processes that perform dup(2) and then close(2) operations on /dev/zero. The maximum opens at one time is system defined, so the test will run up to this maximum, or 65536 open file descriptors, which ever comes first. .TP .B \-\-dup\-ops N stop the dup stress processes after N bogo open operations. .TP .B \-\-epoll N start N stressors that perform various related socket stress activity using epoll_wait to monitor and handle new connections. This involves client/server processes performing rapid connect, send/receives and disconnects on the local host. Using epoll allows a large number of connections to be efficiently handled, however, this can lead to the connection table filling up and blocking further socket connections, hence impacting on the epoll bogo op stats. For ipv4 and ipv6 domains, multiple servers are spawned on multiple ports. The epoll stressor is for Linux only. .TP .B \-\-epoll\-domain D specifty the domain to use, the default is unix (aka local). Currently ipv4, ipv6 and unix are supported. .TP .B \-\-epoll\-port P start at socket port P. For N epoll worker processes, ports P to (P * 4) - 1 are used for ipv4, ipv6 domains and ports P to P - 1 are used for the unix domain. .TP .B \-\-epoll\-ops N stop epoll stress processes after N bogo operations. .TP .B \-\-eventfd N start N parent and child worker processes that read and write 8 byte event messages between them via the eventfd mechanism (Linux only). .TP .B \-\-eventfd\-ops N stop eventfd workers after N bogo operations. .TP .B \-F N, \-\-fallocate N start N processes continually fallocating (preallocating file space) and ftuncating (file truncating) temporary files. .TP .B \-\-fallocate\-ops N stop fallocate stress processes after N bogo fallocate operations. .TP .B \-\-fault N start N processes that generates minor and major page faults. .TP .B \-\-fault\-ops N stop the page fault processes after N bogo page fault operations. .TP .B \-\-fifo N start N workers that exercise a named pipe transmitting 64 bit integers. .TP .B \-\-fifo-ops N stop fifo workers after N bogo pipe write operations. .TP .B \-\-fifo-readers N for each worker, create N fifo reader processes that read the named pipe using simple blocking reads. .TP .B \-\-flock N start N processes locking on a single file. .TP .B \-\-flock\-ops N stop flock stress processes after N bogo flock operations. .TP .B \-f N, \-\-fork N start N processes continually forking children that immediately exit. .TP .B \-\-fork\-ops N stop fork stress processes after N bogo operations. .TP .B \-\-fork\-max P create P processes and then wait for them to exit per iteration. The default is just 1; higher values will create many temporary zombie processes that are waiting to be reaped. One can potentially fill up the the process table using high values for \-\-fork\-max and \-\-fork. .TP .B \-\-fstat N start N processes fstat'ing files in a directory (default is /dev). .TP .B \-\-fstat\-ops N stop fstat stress process after N bogo fstat operations. .TP .B \-\-fstat\-dir directory specify the directory to fstat to override the default of /dev. All the files in the directory will be fstat'd repeatedly. .TP .B \-\-futex N start N stressors that rapidly exercise the futex system call. Each stressor has two processes, a futex waiter and a futex waker. The waiter waits with a very small timeout to stress the timeout and rapid polled futex waiting. This is a Linux specific stress option. .TP .B \-\-futex\-ops N stop futex stressors after N bogo successful futex wait operations. .TP .B \-\-get N start N stressors that call all the get*(2) system calls. .TP .B \-\-get\-ops N stop get stressors after N bogo get operations. .TP .B \-d N, \-\-hdd N start N processes continually writing and removing temporary files. .TP .B \-\-hdd\-bytes N write N bytes for each hdd process, the default is 1 GB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-hdd\-opts list specify various stress test options as a comma separated list. Options are as follows: .TS expand; lB lBw(\n[SZ]n) l l. Option Description direct T{ try to minimize cache effects of the I/O. File I/O writes are performed directly from user space buffers and synchronous transfer is also attempted. To guarantee synchronous I/O, also use the sync option. T} dsync T{ ensure output has been transferred to underlying hardware and file metadata has been updated. This is equivalent to each write(2) being followed by a call to fdatasync(2). T} noatime T{ do not update the file last access timestamp, this can reduce metadata writes. T} sync T{ ensure output has been transferred to underlying hardware. This is equivalent to a each write(2) being followed by a call to fdatasync(2). T} wr\-seq T{ write data sequentially. This is the default if no write modes are specified. T} wr\-rnd T{ write data randomly. The wr\-seq option cannot be used at the same time. T} rd\-seq T{ read data sequentially. By default, written data is not read back, however, this option will force it to be read back sequentially. T} rd\-rnd T{ read data randomly. By default, written data is not read back, however, this option will force it to be read back randonly. T} fadv\-normal T{ advise kernel there are no explicit access pattern for the data. This is the default advice assumption. T} fadv\-seq T{ advise kernel to expect sequential access patterns for the data. T} fadv\-rnd T{ advise kernel to expect random access patterns for the data. T} fadv\-noreuse T{ advise kernel to expect the data to be accessed only once. T} fadv\-willneed T{ advise kernel to expect the data to be accessed in the near future. T} fadv\-dontneed T{ advise kernel to expect the data will not be accessed in the near future. T} .TE .br Note that some of these options are mutually exclusive, for example, there can be only one method of writing or reading. Also, fadvise flags may be mutually exclusive, for example fadv-willneed cannot be used with fadv-dontneed. .TP .B \-\-hdd\-ops N stop hdd stress processes after N bogo operations. .TP .B \-\-hdd\-sync .B \-\-hdd\-write\-size N specify size of each write in bytes. Size can be from 1 byte to 4MB. .TP .B \-h, \-\-help show help. .TP .B \-\-hsearch N start N processes that search a 80% full hash table using hsearch(3). By default, there are 8192 elements inserted into the hash table. This is a useful method to exercise access of memory and processor cache. .TP .B \-\-hsearch\-ops N stop the hsearch processes after N bogo hsearch operations are completed. .TP .B \-\-hsearch\-size N specify the number of hash entries to be inserted into the hash table. Size can be from 1K to 4M. .TP .B \-\-inotify N start N processes performing file system activities such as making/deleting files/directories, moving files, etc. to stress exercise the various inotify events (Linux only). .TP .B \-\-inotify\-ops N stop inotify stress processes after N inotify bogo operations. .TP .B \-i N, \-\-io N start N processes continuously calling sync(2) to commit buffer cache to disk. This can be used in conjunction with the \-\-hdd options. .TP .B \-\-io\-ops N stop io stress processes after N bogo operations. .TP .B \-\-ionice\-class class specify ionice class (only on Linux). Can be idle (default), besteffort, be, realtime, rt. .TP .B \-\-ionice\-level level specify ionice level (only on Linux). For idle, 0 is the only possible option. For besteffort or realtime values 0 (hightest priority) to 7 (lowest priority). See ionice(1) for more details. .TP .B \-k, \-\-keep\-name by default, stress-ng will attempt to change the name of the stress processes according to their functionality; this option disables this and keeps the process names to be the name of the parent process, that is, stress-ng. .TP .B \-\-kill N start N processes sending SIGUSR1 kill signals to a SIG_IGN signal handler. Most of the process time will end up in kernel space. .TP .B \-\-kill\-ops N stop kill processes after N bogo kill operations. .TP .B \-\-lease N start N processes locking, unlocking and breaking leases via the fcntl(2) F_SETLEASE operation. The parent processes continually lock and unlock a lease on a file while a user selectable number of child processes open the file with a non-blocking open to generate SIGIO lease breaking notifications to the parent. This stressor is only available if F_SETLEASE, F_WRLCK and F_UNLCK support is provided by fcntl(2). .TP .B \-\-lease\-ops N stop lease stressors after N bogo operations. .TP .B \-\-lease\-breakers N start N lease breaker child processes per lease stressor. Normally one child is plenty to force many SIGIO lease breaking notification signals to the parent, however, this option allows one to specify more child processes if required. .TP .B \-\-link N start N processes creating and removing hardlinks. .TP .B \-\-link\-ops N stop link stress processes after N bogo operations. .TP .B \-\-lockf N start N processes randomly locking regions of a file using the POSIX lockf(3) locking mechanism. A single 4K file is locked in one of two randonly chosen 2K regions at offsets 0 and 2K. .TP .B \-\-lockf\-ops N stop lockf stress processes after N bogo lockf operations. .TP .B \-\-lockf\-nonblock instead of using blocking F_LOCK lockf(3) commands, use non-blocking F_TLOCK commands and re-try if the lock failed. This creates extra system call overhead and CPU utilisation as the number of lockf stressors increases and hence increases locking contention. .TP .B \-\-lsearch N start N processes that linear search a unsorted array of 32 bit integers using lsearch(3). By default, there are 8192 elements in the array. This is a useful method to exercise sequential access of memory and processor cache. .TP .B \-\-lsearch\-ops N stop the lsearch processes after N bogo lsearch operations are completed. .TP .B \-\-malloc N start N processes continuously calling malloc(3), calloc(3), realloc(3) and free(3). By default, up to 65536 allocations can be active at any point, but this can be altered with the \-\-malloc\-max option. Allocation, reallocation and freeing are chosen at random; 50% of the time memory is allocation (via malloc, calloc or realloc) and 50% of the time allocations are free'd. Allocation sizes are also random, with the maximum allocation size controlled by the \-\-malloc\-bytes option, the default size being 64K. The stressor is re-started if it is killed by the out of mememory (OOM) killer. .TP .B \-\-malloc\-bytes N maximum per allocation/reallocation size. Allocations are randomly selected from from 1 to N bytes. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. Large allocation sizes cause the memory allocator to use mmap(2) rather than expanding the heap using brk(2). .TP .B \-\-malloc\-max N maximum number of active allocations allowed. Allocations are chosen at ramdom and placed in an allocation slot. Because about 50%/50% split between allocation and freeing, typically half of the allocation slots are in use at any one time. .TP .B \-\-malloc\-ops N stop after N malloc bogo operations. One bogo operations relates to a successfull malloc(3), calloc(3) or realloc(3). .TP .B \-\-lsearch\-size N specify the size (number of 32 bit integers) in the array to lsearch. Size can be from 1K to 4M. .TP .B \-\-metrics output number of bogo operations in total performed by the stress processes. Note that these are not a reliable metric of performance or throughput and have not been designed to be used for benchmarking whatsoever. The metrics are just a useful way to observe how a system behaves when under various kinds of load. .RS .PP The following columns of information are output: .TS expand; lB lBw(\n[SM]n) l l. Column Heading Explanation T{ bogo ops T} T{ number of iterations of the stressor during the run. This is metric of how much overall "work" has been achieved in bogo operations. T} T{ real time (secs) T} T{ average wall clock duration (in seconds) of the stressor. This is the total wall clock time of all the instances of that particular stressor divided by the number of these stressors being run. T} T{ usr time (secs) T} T{ total user time (in seconds) consumed running all the instances of the stressor. T} T{ sys time (secs) T} T{ total system time (in seconds) consumed running all the instances of the stressor. T} T{ bogo ops/s (real time) T} T{ total bogo operations per second based on wall clock run time. The wall clock time reflects the apparent run time. The more processors one has on a system the more the work load can be distributed onto these and hence the wall clock time will reduce and the bogo ops rate will increase. This is essentially the "apparent" bogo ops rate of the system. T} T{ bogo ops/s (usr+sys time) T} T{ total bogo operations per second based on cumulative user and system time. This is the real bogo ops rate of the system taking into consideration the actual time execution time of the stressor across all the processors. Generally this will decrease as one adds more concurrent stressors due to contention on cache, memory, execution units, buses and I/O devices. T} .TE .RE .TP .B -\-metrics\-brief enable metrics and only output metrics that are non-zero. .TP .B \-\-memcpy N start N processes that copy 2MB of data from a shared region to a buffer using memcpy(3) and then move the data in the buffer with memmove(3) with 3 different alignments. This will exercise processor cache and system memory. .TP .B \-\-memcpy\-ops N stop memcpy stress processes after N bogo memcpy operations. .TP .B \-\-mincore N start N processes that walk through all of memory 1 page at a time checking of the page mapped and also is resident in memory using mincore(2). .TP .B \-\-mincore\-ops N stop after N mincore bogo operations. One mincore bogo op is equivalent to a 1000 mincore(2) calls. .TP .B \-\-mincore\-random instead of walking through pages sequentially, select pages at random. The chosen address is iterated over by shifting it right one place and checked by mincore until the address is less or equal to the page size. .TP .B \-\-mmap N start N processes continuously calling mmap(2)/munmap(2). The initial mapping is a large chunk (size specified by \-\-mmap\-bytes) followed by pseudo-random 4K unmappings, then pseudo-random 4K mappings, and then linear 4K unmappings. Note that this can cause systems to trip the kernel OOM killer on Linux systems if not enough physical memory and swap is not available. The MAP_POPULATE option is used to populate pages into memory on systems that support this. By default, anonymous mappings are used, however, the \-\-mmap\-file and \-\-mmap\-async options allow one to perform file based mappings if desired. .TP .B \-\-mmap\-ops N stop mmap stress processes after N bogo operations. .TP .B \-\-mmap\-async enable file based memory mapping and use asynchronous msync'ing on each page, see \-\-mmap\-file. .TP .B \-\-mmap\-bytes N allocate N bytes per mmap stress process, the default is 256MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-mmap\-file enable file based memory mapping and by default use synchronous msync'ing on each page. .TP .B \-\-mmap\-mprotect change protection settings on each page of memory. Each time a page or a group of pages are mapped or remapped then this option will make the pages read-only, write-only, exec-only, and read-write. .TP .B \-\-mremap N start N processes continuously calling mmap(2), mremap(2) and munmap(2). The initial anonymous mapping is a large chunk (size specified by \-\-mremap\-bytes) and then iteratively halved in size by remapping all the way down to a page size and then back up to the original size. This stressor is only available for Linux. .TP .B \-\-mremap\-ops N stop mremap stress processes after N bogo operations. .TP .B \-\-mremap\-bytes N initially allocate N bytes per remmap stress process, the default is 256MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-msg N start N sender and receiver processes that continually send and receive messages using System V message IPC. .TP .B \-\-msg\-ops N stop after N bogo message send operations completed. .TP .B \-\-mq N start N sender and receiver processes that continually send and receive messages using POSIX message queues. (Linux only). .TP .B \-\-mq\-ops N stop after N bogo POSIX message send operations completed. .TP .B \-\-mq\-size N specify size of POSIX message queue. The default size is 10 messages and most Linux systems this is the maximum allowed size for normal users. If the given size is greater than the allowed message queue size then a warning is issued and the maximum allowed size is used instead. .TP .B \-\-nice N start N cpu consuming processes that exercise the available nice levels. Each iteration forks off a child process that runs through the all the nice levels running a busy loop for 0.1 seconds per level and then exits. .TP .B \-\-nice\-ops N stop after N nice bogo nice loops .TP .B \-\-no\-advise from version 0.02.26 stress-ng automatically calls madvise(2) with random advise options before each mmap and munmap to stress the the vm subsystem a little harder. The \-\-no\-advise option turns this default off. .TP .B \-\-null N start N processes writing to /dev/null. .TP .B \-\-null\-ops N stop null stress processes after N /dev/null bogo write operations. .TP .B \-o N, \-\-open N start N processes that perform open(2) and then close(2) operations on /dev/zero. The maximum opens at one time is system defined, so the test will run up to this maximum, or 65536 open file descriptors, which ever comes first. .TP .B \-\-open\-ops N stop the open stress processes after N bogo open operations. .TP .B \-\-page\-in touch allocated pages that are not in core, forcing them to be paged back in. This is a useful option to force all the allocated pages to be paged in when using the bigheap, mmap and vm stressors. It will severely degrade performance when the memory in the system is less than the allocated buffer sizes. This uses mincore(2) to determine the pages that are not in core and hence need touching to page them back in. .TP .B \-p N, \-\-pipe N start N stressors that perform large pipe writes and reads to exercise pipe I/O. This exercises memory write and reads as well as context switching. Each stressor has two processes, a reader and a writer. .TP .B \-\-pipe\-ops N stop pipe stress processes after N bogo pipe write operations. .TP .B \-P N, \-\-poll N start N processes that perform zero timeout polling via the poll(2), select(2) and sleep(3) calls. This wastes system and user time doing nothing. .TP .B \-\-poll\-ops N stop poll stress processes after N bogo poll operations. .TP .B \-\-procfs N start N processes that read files from /proc and recursively read files from /proc/self (Linux only). .TP .B \-\-procfs\-ops N stop procfs reading after N bogo read operations. Note, since the number of entries may vary between kernels, this bogo ops metric is probably very misleading. .TP .B \-\-pthread N start N workers that iteratively creates and terminates multiple pthreads (the default is 16 pthreads 16 worker). In each iteration, each newly created pthread waits until the worker has created all the pthreads and then they all terminate together. .TP .B \-\-pthread\-ops N stop pthread workers after N bogo pthread create operations. .TP .B \-\-pthread\-max N create N pthreads per worker. If the product of the number of pthreads by the number of workers is greater than the soft limit of allowed pthreads then the maximum is re-adjusted down to the maximum allowed. .TP .B \-Q, \-\-qsort N start N processes that sort 32 bit integers using qsort. .TP .B \-\-qsort\-ops N stop qsort stress processes after N bogo qsorts. .TP .B \-\-qsort\-size N specify number of 32 bit integers to sort, default is 262144 (256 \(mu 1024). .TP .B \-q, \-\-quiet do not show any output. .TP .B \-r N, \-\-random N start N random stress processes. .TP .B \-\-rdrand N start N processes that read the Intel hardware random number generator (Intel Ivybridge processors upwards). .TP .B \-\-rdrand\-ops N stop rdrand stress processes after N bogo rdrand operations (1 bogo op = 2048 random bits successfully read). .TP .B \-R N, \-\-rename N start N processes that each create a file and then repeatedly rename it. .TP .B \-\-rename\-ops N stop rename stress processes after N bogo rename operations. .TP .B \-\-sched scheduler select the named scheduler (only on Linux). To see the list of available schedulers use: stress\-ng \-\-sched which .TP .B \-\-sched\-prio prio select the scheduler priority level (only on Linux). If the scheduler does not support this then the default priority level of 0 is chosen. .TP .B \-\-seek N start N processes that randomly seeks and performs 512 byte read/write I/O operations on a file. The default file size is 16 GB. .TP .B \-\-seek\-ops N stop seek stress processes after N bogo seek operations. .TP .B \-\-seek\-size N specify the size of the file in bytes. Small file sizes allow the I/O to occur in the cache, causing greater CPU load. Large file sizes force more I/O operations to drive causing more wait time and more I/O on the drive. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-sem N start N workers that perform POSIX semaphore wait and post operations. By default, a parent and 4 children are started per worker to provide some contention on the semaphore. This stresses fast semaphore operations and produces rapid context switching. .TP .B \-\-sem\-ops N stop semaphore stress processes after N bogo semaphore operations. .TP .B \-\-sem\-procs N start N child processes per worker to provide contention on the semaphore, the default is 4 and a maximum of 64 are allowed. .TP .B \-\-sem\-sysv N start N workers that perform System V semaphore wait and post operations. By default, a parent and 4 children are started per worker to provide some contention on the semaphore. This stresses fast semaphore operations and produces rapid context switching. .TP .B \-\-sem\-sysv\-ops N stop semaphore stress processes after N bogo System V semaphore operations. .TP .B \-\-sem\-sysv\-procs N start N child processes per worker to provide contention on the System V semaphore, the default is 4 and a maximum of 64 are allowed. .TP .B \-\-sendfile N start N processes that send an empty file to /dev/null. This operation spends nearly all the time in the kernel. The default sendfile size is 4MB. The sendfile options are for Linux only. .TP .B \-\-sendfile\-ops N stop sendfile stressors after N sendfile bogo operations. .TP .B \-\-sendfile\-size S specify the size to be copied with each sendfile call. The default size is 4MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-sequential N sequentially run all the stressors one by one for a default of 60 seconds. The number of each individual stressors to be started is N. If N is zero, then a stressor for each processor that is on-line is executed. Use the \-\-timeout option to specify the duration to run each stressor. .TP .B \-\-shm\-sysv N start N processes that allocate shared memory using the System V shared memory interface. By default, the test will repeatedly create and destroy 8 shared memory segments, each of which is 8MB in size. .TP .B \-\-shm\-sysv\-ops N stop after N shared memory create and destroy bogo operations are complete. .TP .B \-\-shm\-sysv\-bytes N specify the size of the shared memory segment to be created. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-shm\-sysv\-segs N specify the number of shared memory segments to be created. .TP .B \-\-sigfd N start N processess that generate SIGUSR1 signals and are handled by reads by a child process using a file descriptor set up using signalfd(2). (Linux only). This will generate a heavy context switch load. .TP .B \-\-sigfd\-ops stop sigfd processes after N bogo SIGUSR1 signals are sent. .TP .B \-\-sigfpe N start N processes that rapidly cause division by zero SIGFPE faults. .TP .B \-\-sigfpe\-ops N stop sigfpe stress processes after N bogo SIGFPE faults. .TP .B \-\-sigsegv N start N processes that rapidly create and catch segmentation faults. .TP .B \-\-sigsegv\-ops N stop sigsegv stress processes after N bogo segmentation faults. .TP .B \-\-sigq N start N processes that rapidly send SIGUSR1 signals using sigqueue(3) to child processes that wait for the signal via sigwaitinfo(2). .TP .B \-\-sigq\-ops N stop sigq stress processes after N bogo signal send operations. .TP .B \-S N, \-\-sock N start N stressors that perform various socket stress activity. This involves a pair of client/server processes performing rapid connect, send and receives and disconnects on the local host. .TP .B \-\-sock\-domain D specifty the domain to use, the default is ipv4. Currently ipv4, ipv6 and unix are supported. .TP .B \-\-sock\-port P start at socket port P. For N socket worker processes, ports P to P - 1 are used. .TP .B \-\-sock\-ops N stop socket stress processes after N bogo operations. .TP .B \-\-splice N move data from /dev/zero to /dev/null through a pipe without any copying between kernel address space and user address space using splice(2). This is only available for Linux. .TP .B \-\-splice-ops N stop after N bogo splice operations. .TP .B \-\-splice-bytes N transfer N bytes per splice call, the default is 64K. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-stack N start N processes that rapidly cause and catch stack overflows by use of alloca(3). .TP .B \-\-stack\-ops N stop stack stress processes after N bogo stack overflows. .TP .B \-s N, \-\-switch N start N processes that send messages via pipe to a child to force context switching. .TP .B \-\-switch\-ops N stop context switching processes after N bogo operations. .TP .B \-\-symlink N start N processes creating and removing symbolic links. .TP .B \-\-symlink\-ops N stop symlink stress processes after N bogo operations. .TP .B \-\-sysinfo N start N processes that continually read system and process specific information. This reads the process user and system times using the times(2) system call. For Linux systems, it also reads overall system statistics using the sysinfo(2) system call and also the file system statistics for all mounted file systems using statfs(2). .TP .B \-\-sysinfo\-ops N stop the sysinfo stressors after N bogo operations. .TP .B \-t N, \-\-timeout N stop stress test after N seconds. One can also specify the units of time in seconds, minutes, hours, days or years with the suffix s, m, h, d or y. .TP .B \-T N, \-\-timer N start N processes creating timer events at a default rate of 1Mhz (Linux only); this can create a many thousands of timer clock interrupts. .TP .B \-\-timer\-ops N stop timer stress processes after N bogo timer events (Linux only). .TP .B \-\-timer\-freq F run timers at F Hz; range from 1000 to 1000000000 Hz (Linux only). By selecting an appropriate frequency stress-ng can generate hundreds of thousands of interrupts per second. .TP .B \-\-times show the cumulative user and system times of all the child processes at the end of the stress run. The percentage of utilisation of available CPU time is also calculated from the number of on-line CPUs in the system. .TP .B \-\-tsearch N start N processes that insert, search and delete 32 bit integers on a binary tree using tsearch(3), tfind(3) and tdelete(3). By default, there are 65536 randomized integers used in the tree. This is a useful method to exercise random access of memory and processor cache. .TP .B \-\-tsearch\-ops N stop the tsearch processes after N bogo tree operations are completed. .TP .B \-\-tsearch\-size N specify the size (number of 32 bit integers) in the array to tsearch. Size can be from 1K to 4M. .TP .B \-\-udp N start N stressors that transmit data using UDP. This involves a pair of client/server processes performing rapid connect, send and receives and disconnects on the local host. .TP .B \-\-udp\-domain D specifty the domain to use, the default is ipv4. Currently ipv4, ipv6 and unix are supported. .TP .B \-\-udp\-port P start at port P. For N udp worker processes, ports P to P - 1 are used. .TP .B \-\-udp\-ops N stop udp stress processes after N bogo operations. .TP .B \-u N, \-\-urandom N start N processes reading /dev/urandom (Linux only). This will load the kernel random number source. .TP .B \-\-urandom\-ops N stop urandom stress processes after N urandom bogo read operations (Linux only). .TP .B \-\-utime N start N processes updating file timestamps. This is mainly CPU bound when the default is used as the system flushes metadata changes only periodically. .TP .B \-\-utime\-ops N stop utime stress processes after N utime bogo operations. .TP .B \-\-utime\-fsync force metadata changes on each file timestamp update to be flushed to disk. This forces the test to become I/O bound and will result in many dirty metadata writes. .TP .B \-\-vecmath N start N processes that perform various unsigned integer math operations on various 128 bit vectors. A mix of vector math operations are performed on the following vectors: 16 x 8 bits, 8 x 16 bits, 4 x 32 bits, 2 x 64 bits. The metrics produced by this mix depend on the processor architecture and the vector math optimisations produced by the compiler. .TP .B \-\-vecmath\-ops N stop after N bogo vector integer math operations. .TP .B \-v, \-\-verbose show all debug, warnings and normal information output. .TP .B \-\-verify verify results when a test is run. This is not available on all tests. This will sanity check the computations or memory contents from a test run and report to stderr any unexpected failures. .TP .B \-V, \-\-version show version. .TP .B \-\-vfork N start N processes continually vforking children that immediately exit. .TP .B \-\-vfork\-ops N stop vfork stress processes after N bogo operations. .TP .B \-\-vfork\-max P create P processes and then wait for them to exit per iteration. The default is just 1; higher values will create many temporary zombie processes that are waiting to be reaped. One can potentially fill up the the process table using high values for \-\-vfork\-max and \-\-vfork. .TP .B \-m N, \-\-vm N start N processes continuously calling mmap(2)/munmap(2) and writing to the allocated memory. Note that this can cause systems to trip the kernel OOM killer on Linux systems if not enough physical memory and swap is not available. .TP .B \-\-vm\-bytes N mmap N bytes per vm process, the default is 256MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-vm\-stride N deprecated since version 0.03.02 .TP .B \-\-vm\-ops N stop vm stress processes after N bogo operations. .TP .B \-\-vm\-hang N sleep N seconds before unmapping memory, the default is zero seconds. Specifying 0 will do an infinite wait. .TP .B \-\-vm\-keep don't continually unmap and map memory, just keep on re-writing to it. .TP .B \-\-vm\-locked Lock the pages of the mapped region into memory using mmap MAP_LOCKED (since Linux 2.5.37). This is similar to locking memory as described in mlock(2). .TP .B \-\-vm\-method m specify a vm stress method. By default, all the stress methods are exercised sequentially, however one can specify just one method to be used if required. Each of the vm stressors have 3 phases: .RS .PP 1. Initialised. The anonymously memory mapped region is set to a known pattern. .PP 2. Exercised. Memory is modified in a known predictable way. Some vm stressors alter memory sequentially, some use small or large strides to step along memory. .PP 3. Checked. The modified memory is checked to see if it matches the expected result. .PP The vm methods containing 'prime' in their name have a stride of the largest prime less than 2^64, allowing to them to thoroughly step through memory and touch all locations just once while also doing without touching memory cells next to each other. This strategy exercises the cache and page non-locality. .PP Since the memory being exercised is virtually mapped then there is no guarantee of touching page addresses in any particular physical order. These stressors should not be used to test that all the system's memory is working correctly either, use tools such as memtest86 instead. .PP The vm stress methods are intended to exercise memory in ways to possibly find memory issues and to try to force thermal errors. .PP Available vm stress methods are described as follows: .TS expand; lB2 lBw(\n[SV]n) l l. Method Description all T{ iterate over all the vm stress methods as listed below. T} flip T{ sequentially work through memory 8 times, each time just one bit in memory flipped (inverted). This will effectively invert each byte in 8 passes. T} galpat-0 T{ galloping pattern zeros. This sets all bits to 0 and flips just 1 in 4096 bits to 1. It then checks to see if the 1s are pulled down to 0 by their neighbours or of the neighbours have been pulled up to 1. T} galpat-1 T{ galloping pattern ones. This sets all bits to 1 and flips just 1 in 4096 bits to 0. It then checks to see if the 0s are pulled up to 1 by their neighbours or of the neighbours have been pulled down to 0. T} gray T{ fill the memory with sequential gray codes (these only change 1 bit at a time between adjacent bytes) and then check if they are set correctly. T} incdec T{ work sequentially through memory twice, the first pass increments each byte by a specific value and the second pass decrements each byte back to the original start value. The increment/decrement value changes on each invocation of the stressor. T} inc-nybble T{ initialise memory to a set value (that changes on each invocation of the stressor) and then sequentially work through each byte incrementing the bottom 4 bits by 1 and the top 4 bits by 15. T} rand-set T{ sequentially work through memory in 64 bit chunks setting bytes in the chunk to the same 8 bit random value. The random value changes on each chunk. Check that the values have not changed. T} rand-sum T{ sequentially set all memory to random values and then summate the number of bits that have changed from the original set values. T} read64 T{ sequentially read memory using 32 x 64 bit reads per bogo loop. Each loop equates to one bogo operation. This exercises raw memory reads. T} ror T{ fill memory with a random pattern and then sequentially rotate 64 bits of memory right by one bit, then check the final load/rotate/stored values. T} swap T{ fill memory in 64 byte chunks with random patters. Then swap each 64 chunk with a randomly chosen chunk. Finally, reverse the swap to put the chunks back to their original place and check if the data is correct. This exercises adjacent and random memory load/stores. T} move-inv T{ sequentially fill memory 64 bits of memory at a time with random values, and then check if the memory is set correctly. Next, sequentially invert each 64 bit pattern and again check if the memory is set as expected. T} modulo-x T{ fill memory with 23 iterations. Each iteration starts one byte further along from the start of the memory and steps along in 23 byte strides. In each stride, the first byte is set to a random pattern and all other bytes are set to the inverse. Then it checks see if the first byte contains the expected random pattern. This exercises cache store/reads as well as seeing if neighbouring cells influence each other. T} prime-0 T{ iterate 8 times by stepping through memory in very large prime strides clearing just on bit at a time in every byte. Then check to see if all bits are set to zero. T} prime-1 T{ iterate 8 times by stepping through memory in very large prime strides setting just on bit at a time in every byte. Then check to see if all bits are set to one. T} prime-gray-0 T{ first step through memory in very large prime strides clearing just on bit (based on a gray code) in every byte. Next, repeat this but clear the other 7 bits. Then check to see if all bits are set to zero. T} prime-gray-1 T{ first step through memory in very large prime strides setting just on bit (based on a gray code) in every byte. Next, repeat this but set the other 7 bits. Then check to see if all bits are set to one. T} walk-0d T{ for each byte in memory, walk through each data line setting them to low (and the others are set high) and check that the written value is as expected. This checks if any data lines are stuck. T} walk-1d T{ for each byte in memory, walk through each data line setting them to high (and the others are set low) and check that the written value is as expected. This checks if any data lines are stuck. T} walk-0a T{ in the given memory mapping, work through a range of specially chosen addresses working through address lines to see if any address lines are stuck low. This works best with physical memory addressing, however, exercising these virtual addresses has some value too. T} walk-1a T{ in the given memory mapping, work through a range of specially chosen addresses working through address lines to see if any address lines are stuck high. This works best with physical memory addressing, however, exercising these virtual addresses has some value too. T} write64 T{ sequentially write memory using 32 x 64 bit writes per bogo loop. Each loop equates to one bogo operation. This exercises raw memory writes. Note that memory writes are not checked at the end of each test iteration. T} zero-one T{ set all memory bits to zero and then check if any bits are not zero. Next, set all the memory bits to one and check if any bits are not one. T} .TE .RE .TP .B \-\-vm\-populate populate (prefault) page tables for the memory mappings; this can stress swapping. Only available on systems that support MAP_POPULATE (since Linux 2.5.46). .TP .B \-\-vm\-rw N start N workers that transfer memory to/from a parent/child using process_vm_writev(2) and process_vm_readv(2). This is feature is only supported on Linux. Memory transfers are only verified if the \-\-verify option is enabled. .TP .B \-\-vm\-rw\-ops N stop vm\-rw workers after N memory read/writes. .TP .B \-\-vm\-rw\-bytes N mmap N bytes per vm\-rw process, the default is 16MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-vm\-splice N move data from memory to /dev/null through a pipe without any copying between kernel address space and user address space using vmsplice(2) and splice(2). This is only available for Linux. .TP .B \-\-vm\-splice-ops N stop after N bogo vm\-splice operations. .TP .B \-\-vm\-splice-bytes N transfer N bytes per vmsplice call, the default is 64K. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-wait N start N workers that spawn off two children; one spins in a pause(2) loop, the other continually stops and continues the first. The controlling process waits on the first child to be resumed by the delivery of SIGCONT using waitpid(2) and waitid(2). .TP .B \-\-wait\-ops N stop after N bogo wait operations. .TP .B \-y N, \-\-yield N start N process that call sched_yield(2). This should force rapid context switching. .TP .B \-\-yield\-ops N stop yield stress processes after N sched_yield(2) bogo operations. .TP .B \-\-zero N start N processes reading /dev/zero. .TP .B \-\-zero\-ops N stop zero stress processes after N /dev/zero bogo read operations. .LP .SH EXAMPLES .LP stress\-ng \-\-cpu 4 \-\-io 2 \-\-vm 1 \-\-vm\-bytes 1G \-\-timeout 60s .IP runs for 60 seconds with 4 cpu stressors, 2 io stressors and 1 vm stressor using 1GB of virtual memory. .LP stress\-ng \-\-cpu 8 \-\-cpu\-ops 800000 .IP runs 8 cpu stressors and stops after 800000 bogo operations. .LP stress\-ng \-\-sequential 2 \-\-timeout 2m \-\-metrics .IP run 2 simultaneous instances of all the stressors sequentially one by one, each for 2 minutes and summaries with performance metrics at the end. .LP stress\-ng \-\-cpu 4 \-\-cpu-method fft \-\-cpu-ops 10000 \-\-metrics\-brief .IP run 4 FFT cpu stressors, stop after 10000 bogo operations and produce a summary just for the FFT results. .LP stress\-ng \-\-cpu 0 \-\-cpu-method all \-t 1h .IP run cpu stressors on all online CPUs working through all the available CPU stressors for 1 hour. .LP stress\-ng \-\-all 4 \-\-timeout 5m .IP run 4 instances of all the stressors for 5 minutes. .LP stress\-ng \-\-random 64 .IP run 64 stressors that are randomly chosen from all the available stressors. .LP stress\-ng \-\-cpu 64 \-\-cpu\-method all \-\-verify \-t 10m \-\-metrics\-brief .IP run 64 instances of all the different cpu stressors and verify that the computations are correct for 10 minutes with a bogo operations summary at the end. .LP stress\-ng \-\-sequential 0 \-t 10m .IP run all the stressors one by one for 10 minutes, with the number of instances of each stressor matching the number of online CPUs. .LP stress\-ng \-\-sequential 8 \-\-class io \-t 5m \-\-times .IP run all the stressors in the io class one by one for 5 minutes each, with 8 instances of each stressor running concurrently and show overall time utilisation statistics at the end of the run. .SH BUGS File bug reports at: https://launchpad.net/ubuntu/+source/stress-ng/+filebug .SH SEE ALSO .BR bsearch (3), .BR fallocate (2), .BR fcntl(2), .BR flock (2), .BR ftruncate (2), .BR hsearch (3), .BR ionice (1), .BR ioprio_set (2), .BR lsearch (3), .BR pthreads (7), .BR qsort (3), .BR sched_yield (2), .BR sched_setaffinity (2), .BR stress (1), .BR slice (2), .BR tsearch (3) .SH AUTHOR stress\-ng was written by Colin King and is a clean room re-implementation and extension of the original stress tool by Amos Waterland . .SH NOTES Note that the stress-ng cpu, io, vm and hdd tests are different implementations of the original stress tests and hence may produce different stress characteristics. stress-ng does not support any GPU stress tests. .PP The bogo operations metrics may change with each release because of bug fixes to the code, new features, compiler optimisations or changes in system call performance. .SH COPYRIGHT Copyright \(co 2013-2015 Canonical Ltd. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. stress-ng-0.03.15/stress-flock.c0000664000175000017500000000531612466243156015052 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #if defined (_POSIX_PRIORITY_SCHEDULING) || defined (__linux__) #include #endif #include "stress-ng.h" /* * stress_flock * stress file locking */ int stress_flock( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd; pid_t ppid = getppid(); char filename[PATH_MAX]; char dirname[PATH_MAX]; /* * There will be a race to create the directory * so EEXIST is expected on all but one instance */ (void)stress_temp_dir(dirname, sizeof(dirname), name, ppid, instance); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_failed_err(name, "mkdir"); return EXIT_FAILURE; } } /* * Lock file is based on parent pid and instance 0 * as we need to share this among all the other * stress flock processes */ (void)stress_temp_filename(filename, sizeof(filename), name, ppid, 0, 0); retry: if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { if ((errno == ENOENT) && opt_do_run) { /* Race, sometimes we need to retry */ goto retry; } /* Not sure why this fails.. report and abort */ pr_failed_err(name, "open"); (void)rmdir(dirname); return EXIT_FAILURE; } do { if (flock(fd, LOCK_EX) < 0) continue; #if defined(_POSIX_PRIORITY_SCHEDULING) sched_yield(); #endif (void)flock(fd, LOCK_UN); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-epoll.c0000664000175000017500000003262212466243156015067 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef AF_INET6 #include #endif #ifdef AF_UNIX #include #endif #include #include #if defined(_POSIX_PRIORITY_SCHEDULING) #include #endif #include "stress-ng.h" #define MAX_EPOLL_EVENTS (1024) #define MAX_SERVERS (4) static int opt_epoll_domain = AF_UNIX; static int opt_epoll_port = DEFAULT_EPOLL_PORT; static int max_servers = 1; static timer_t epoll_timerid; typedef void (epoll_func_t)( const int child, uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid); /* * stress_set_epoll_port() * set the default port base */ void stress_set_epoll_port(const char *optarg) { stress_set_net_port("epoll-port", optarg, MIN_EPOLL_PORT, MAX_EPOLL_PORT - (STRESS_PROCS_MAX * MAX_SERVERS), &opt_epoll_port); } /* * stress_set_epoll_domain() * set the socket domain option */ int stress_set_epoll_domain(const char *name) { int ret; ret = stress_set_net_domain("epoll-domain", name, &opt_epoll_domain); switch (opt_epoll_domain) { case AF_INET: case AF_INET6: max_servers = 4; break; case AF_UNIX: default: max_servers = 1; } return ret; } /* * epoll_timer_handler() * catch timer signal and cancel if no more runs flagged */ static void epoll_timer_handler(int sig) { (void)sig; /* Cancel timer if we detect no more runs */ if (!opt_do_run) { struct itimerspec timer; timer.it_value.tv_sec = 0; timer.it_value.tv_nsec = 0; timer.it_interval.tv_sec = timer.it_value.tv_sec; timer.it_interval.tv_nsec = timer.it_value.tv_nsec; timer_settime(epoll_timerid, 0, &timer, NULL); } } /* * handle_socket_sigalrm() * catch SIGALRM */ static void handle_socket_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * epoll_spawn() * spawn a process */ static int epoll_spawn( epoll_func_t func, const int child, uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { func(child, counter, instance, max_ops, name, ppid); exit(EXIT_SUCCESS); } return pid; } /* * epoll_set_fd_nonblock() * set non-blocking mode on fd */ static int epoll_set_fd_nonblock(const int fd) { int flags; if ((flags = fcntl(fd, F_GETFL, 0)) < 0) return -1; if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) return -1; return 0; } /* * epoll_recv_data() * receive data on fd */ static void epoll_recv_data(const int fd) { for (;;) { char buf[8192]; ssize_t n; n = recv(fd, buf, sizeof(buf), 0); if (n == -1) { if (errno != EAGAIN) (void)close(fd); break; } else if (n == 0) { (void)close(fd); break; } } } /* * epoll_ctl_add() * add fd to epoll list */ static int epoll_ctl_add(const int efd, const int fd) { struct epoll_event event; memset(&event, 0, sizeof(event)); event.data.fd = fd; event.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event) < 0) return -1; return 0; } /* * epoll_notification() * handle accept notification on sfd, add * fd's to epoll event list */ static int epoll_notification( const char *name, const int efd, const int sfd) { for (;;) { struct sockaddr saddr; socklen_t slen = sizeof(saddr); int fd; if ((fd = accept(sfd, &saddr, &slen)) < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* all incoming connections handled so finish */ return 0; } if ((errno == EMFILE) || (errno == ENFILE)) { /* out of file descriptors! */ return 0; } pr_failed_err(name, "accept"); return -1; } /* * Add non-blocking fd to epoll event list */ if (epoll_set_fd_nonblock(fd) < 0) { pr_failed_err(name, "setting socket to non-blocking"); (void)close(fd); return -1; } if (epoll_ctl_add(efd, fd) < 0) { pr_failed_err(name, "epoll ctl add"); (void)close(fd); return -1; } } return 0; } /* * epoll_client() * rapidly try to connect to server(s) and * send a relatively short message */ static int epoll_client( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid) { int port_counter = 0; uint64_t connect_timeouts = 0; struct sigaction new_action; struct sigevent sev; struct itimerspec timer; struct sockaddr *addr; new_action.sa_flags = 0; new_action.sa_handler = epoll_timer_handler; sigemptyset(&new_action.sa_mask); if (sigaction(SIGRTMIN, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return -1; } do { char buf[4096]; int fd; int retries = 0; int ret = -1; int port = opt_epoll_port + port_counter + (max_servers * instance); socklen_t addr_len = 0; /* Cycle through the servers */ port_counter = (port_counter + 1) % max_servers; retry: if (!opt_do_run) break; if ((fd = socket(opt_epoll_domain, SOCK_STREAM, 0)) < 0) { pr_failed_dbg(name, "socket"); return -1; } sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &epoll_timerid; if (timer_create(CLOCK_REALTIME, &sev, &epoll_timerid) < 0) { pr_failed_err(name, "timer_create"); (void)close(fd); return -1; } /* * Allow 1 second for connection to occur, * connect can block if the connection table * fills up because we're waiting for TIME-OUTs * to occur on previously closed connections */ timer.it_value.tv_sec = 0; timer.it_value.tv_nsec = 250000000; timer.it_interval.tv_sec = timer.it_value.tv_sec; timer.it_interval.tv_nsec = timer.it_value.tv_nsec; if (timer_settime(epoll_timerid, 0, &timer, NULL) < 0) { pr_failed_err(name, "timer_settime"); (void)close(fd); return -1; } errno = 0; stress_set_sockaddr(name, instance, ppid, opt_epoll_domain, port, &addr, &addr_len); ret = connect(fd, addr, addr_len); /* No longer need timer */ if (timer_delete(epoll_timerid) < 0) { pr_failed_err(name, "timer_delete"); (void)close(fd); return -1; } if (ret < 0) { switch (errno) { case EINTR: connect_timeouts++; break; case ECONNREFUSED: /* No servers yet running */ case ENOENT: /* unix domain not yet created */ break; default: pr_dbg(stderr, "%s: connect failed: %d (%s)\n", name, errno, strerror(errno)); break; } (void)close(fd); usleep(1000); /* Twiddle fingers for a moment */ retries++; if (retries > 100) { /* Sigh, give up.. */ pr_failed_dbg(name, "connect"); return -1; } goto retry; } retries = 0; memset(buf, 'A' + (*counter % 26), sizeof(buf)); if (send(fd, buf, sizeof(buf), 0) < 0) { (void)close(fd); pr_failed_dbg(name, "send"); break; } (void)close(fd); #if defined(_POSIX_PRIORITY_SCHEDULING) sched_yield(); #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); #ifdef AF_UNIX if (opt_epoll_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif if (connect_timeouts) pr_dbg(stderr, "%s: %" PRIu64 " x 0.25 second connect timeouts, " "connection table full (instance %" PRIu32 ")\n", name, connect_timeouts, instance); return EXIT_SUCCESS; } /* * epoll_server() * wait on connections and read data */ static void epoll_server( const int child, uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid) { int efd = -1, sfd = -1, rc = EXIT_SUCCESS; int so_reuseaddr = 1; int port = opt_epoll_port + child + (max_servers * instance); struct sigaction new_action; struct epoll_event *events = NULL; struct sockaddr *addr; socklen_t addr_len = 0; new_action.sa_handler = handle_socket_sigalrm; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); rc = EXIT_FAILURE; goto die; } if ((sfd = socket(opt_epoll_domain, SOCK_STREAM, 0)) < 0) { pr_failed_err(name, "socket"); rc = EXIT_FAILURE; goto die; } if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_failed_err(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, opt_epoll_domain, port, &addr, &addr_len); if (bind(sfd, addr, addr_len) < 0) { pr_failed_err(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (epoll_set_fd_nonblock(sfd) < 0) { pr_failed_err(name, "setting socket to non-blocking"); rc = EXIT_FAILURE; goto die_close; } if (listen(sfd, SOMAXCONN) < 0) { pr_failed_err(name, "listen"); rc = EXIT_FAILURE; goto die_close; } if ((efd = epoll_create1(0)) < 0) { pr_failed_err(name, "epoll_create1"); rc = EXIT_FAILURE; goto die_close; } if (epoll_ctl_add(efd, sfd) < 0) { pr_failed_err(name, "epoll ctl add"); rc = EXIT_FAILURE; goto die_close; } if ((events = calloc(MAX_EPOLL_EVENTS, sizeof(struct epoll_event))) == NULL) { pr_failed_err(name, "epoll ctl add"); rc = EXIT_FAILURE; goto die_close; } do { int n, i; memset(events, 0, MAX_EPOLL_EVENTS * sizeof(struct epoll_event)); errno = 0; /* * Wait for 100ms for an event, allowing us to * to break out if opt_do_run has been changed */ n = epoll_wait(efd, events, MAX_EPOLL_EVENTS, 100); if (n < 0) { if (errno != EINTR) { pr_failed_err(name, "epoll_wait"); rc = EXIT_FAILURE; goto die_close; } break; } for (i = 0; i < n; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* * Error has occurred or fd is not * for reading anymore.. so reap fd */ (void)close(events[i].data.fd); } else if (sfd == events[i].data.fd) { /* * The listening socket has notification(s) * pending, so handle incomming connections */ if (epoll_notification(name, efd, sfd) < 0) break; } else { /* * The fd has data available, so read it */ epoll_recv_data(events[i].data.fd); } } } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: if (efd != -1) (void)close(efd); if (sfd != -1) (void)close(sfd); die: #ifdef AF_UNIX if (opt_epoll_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif free(events); exit(rc); } /* * stress_epoll * stress by heavy socket I/O */ int stress_epoll( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_SERVERS], ppid = getppid(); int i, rc = EXIT_SUCCESS; if (max_servers == 1) { pr_dbg(stderr, "%s: process [%d] using socket port %d\n", name, getpid(), opt_epoll_port + instance); } else { pr_dbg(stderr, "%s: process [%d] using socket ports %d..%d\n", name, getpid(), opt_epoll_port + (max_servers * instance), opt_epoll_port + (max_servers * (instance + 1)) - 1); } /* * Spawn off servers to handle multi port connections. * The (src address, src port, dst address, dst port) tuple * is kept in the connection table for a default of 60 seconds * which means for many fast short connections we can * fill this table up and new connections get blocked until * this table empties. One strategy is to reduce TIME_WAIT (not * good) so the easiest way forward is to just increase the * number of ports being listened to to increase the tuple * range and hence allow more connections. See * http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html * Typically, we are limited to ~500 connections per second * on a default Linux configuration. */ memset(pids, 0, sizeof(pids)); for (i = 0; i < max_servers; i++) { pids[i] = epoll_spawn(epoll_server, i, counter, instance, max_ops, name, ppid); if (pids[i] < 0) { pr_failed_dbg(name, "fork"); goto reap; } } epoll_client(counter, instance, max_ops, name, ppid); reap: for (i = 0; i < max_servers; i++) { int status; if (pids[i] > 0) { (void)kill(pids[i], SIGKILL); if (waitpid(pids[i], &status, 0) < 0) { pr_failed_dbg(name, "waitpid"); } } } return rc; } #endif stress-ng-0.03.15/proc-name.c0000664000175000017500000000260412466243156014311 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include "stress-ng.h" #if defined (__linux__) #include /* * set_proc_name() * Set process name, we don't care if it fails */ void set_proc_name(const char *name) { if (!(opt_flags & OPT_FLAGS_KEEP_NAME)) (void)prctl(PR_SET_NAME, name); } #else void set_proc_name(const char *name) { (void)name; /* No-op */ } #endif stress-ng-0.03.15/stress-noop.c0000664000175000017500000000262312466243156014725 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" /* * stress_noop() * stress that does nowt */ int stress_noop( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)counter; (void)instance; (void)max_ops; (void)name; return EXIT_SUCCESS; } stress-ng-0.03.15/stress-pipe.c0000664000175000017500000000617212466243156014712 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * pipe_memset() * set pipe data to be incrementing chars from val upwards */ static inline void pipe_memset(char *buf, char val, const size_t sz) { size_t i; for (i = 0; i < sz; i++) *buf++ = val++; } /* * pipe_memchk() * check pipe data contains incrementing chars from val upwards */ static inline int pipe_memchk(char *buf, char val, const size_t sz) { size_t i; for (i = 0; i < sz; i++) if (*buf++ != val++) return 1; return 0; } /* * stress_pipe * stress by heavy pipe I/O */ int stress_pipe( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int pipefds[2]; (void)instance; if (pipe(pipefds) < 0) { pr_failed_dbg(name, "pipe"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { (void)close(pipefds[0]); (void)close(pipefds[1]); pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { int val = 0; (void)close(pipefds[1]); for (;;) { char buf[PIPE_BUF]; ssize_t n; n = read(pipefds[0], buf, sizeof(buf)); if (n <= 0) { pr_failed_dbg(name, "read"); break; } if (!strcmp(buf, PIPE_STOP)) break; if ((opt_flags & OPT_FLAGS_VERIFY) && pipe_memchk(buf, val++, (size_t)n)) { pr_fail(stderr, "pipe read error detected, failed to read expected data\n"); } } (void)close(pipefds[0]); exit(EXIT_SUCCESS); } else { char buf[PIPE_BUF]; int val = 0, status; /* Parent */ (void)close(pipefds[0]); do { pipe_memset(buf, val++, sizeof(buf)); if (write(pipefds[1], buf, sizeof(buf)) < 0) { pr_failed_dbg(name, "write"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); strncpy(buf, PIPE_STOP, sizeof(buf)); if (write(pipefds[1], buf, sizeof(buf)) <= 0) pr_failed_dbg(name, "termination write"); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } return EXIT_SUCCESS; } stress-ng-0.03.15/stress-timer.c0000664000175000017500000000665312466243156015101 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include "stress-ng.h" #if defined (__linux__) static volatile uint64_t timer_counter = 0; static timer_t timerid; static uint64_t opt_timer_freq; /* * stress_set_timer_freq() * set timer frequency from given option */ void stress_set_timer_freq(const char *optarg) { opt_timer_freq = get_uint64(optarg); check_range("timer-freq", opt_timer_freq, MIN_TIMER_FREQ, MAX_TIMER_FREQ); } /* * stress_timer_handler() * catch timer signal and cancel if no more runs flagged */ static void stress_timer_handler(int sig) { (void)sig; timer_counter++; /* Cancel timer if we detect no more runs */ if (!opt_do_run) { struct itimerspec timer; timer.it_value.tv_sec = 0; timer.it_value.tv_nsec = 0; timer.it_interval.tv_sec = timer.it_value.tv_sec; timer.it_interval.tv_nsec = timer.it_value.tv_nsec; timer_settime(timerid, 0, &timer, NULL); } } /* * stress_timer * stress timers */ int stress_timer( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct sigaction new_action; struct sigevent sev; struct itimerspec timer; const double rate_ns = opt_timer_freq ? 1000000000 / opt_timer_freq : 1000000000; (void)instance; new_action.sa_flags = 0; new_action.sa_handler = stress_timer_handler; sigemptyset(&new_action.sa_mask); if (sigaction(SIGRTMIN, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) { pr_failed_err(name, "timer_create"); return EXIT_FAILURE; } timer.it_value.tv_sec = (long long int)rate_ns / 1000000000; timer.it_value.tv_nsec = (long long int)rate_ns % 1000000000; timer.it_interval.tv_sec = timer.it_value.tv_sec; timer.it_interval.tv_nsec = timer.it_value.tv_nsec; if (timer_settime(timerid, 0, &timer, NULL) < 0) { pr_failed_err(name, "timer_settime"); return EXIT_FAILURE; } do { struct timespec req; req.tv_sec = 0; req.tv_nsec = 10000000; (void)nanosleep(&req, NULL); *counter = timer_counter; } while (opt_do_run && (!max_ops || timer_counter < max_ops)); if (timer_delete(timerid) < 0) { pr_failed_err(name, "timer_delete"); return EXIT_FAILURE; } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-open.c0000664000175000017500000000422512466243156014713 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_open() * stress system by rapid open/close calls */ int stress_open( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fds[STRESS_FD_MAX]; struct rlimit rlim; rlim_t i, opened = 0; (void)instance; (void)name; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) rlim.rlim_cur = STRESS_FD_MAX; /* Guess */ /* Determine max number of free file descriptors we have */ for (i = 0; i < rlim.rlim_cur; i++) { if (fcntl((int)i, F_GETFL) > -1) opened++; } rlim.rlim_cur -= opened; do { for (i = 0; i < rlim.rlim_cur; i++) { fds[i] = open("/dev/zero", O_RDONLY); if (fds[i] < 0) break; if (!opt_do_run) break; (*counter)++; } for (i = 0; i < rlim.rlim_cur; i++) { if (fds[i] < 0) break; if (!opt_do_run) break; (void)close(fds[i]); } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/mwc.c0000664000175000017500000000334512466243156013221 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include "stress-ng.h" mwc_t __mwc = { MWC_SEED_W, MWC_SEED_Z }; /* * mwc_seed() * set mwc seeds */ void mwc_seed(const uint64_t w, const uint64_t z) { __mwc.w = w; __mwc.z = z; } /* * mwc_reseed() * dirty mwc reseed */ void mwc_reseed(void) { struct timeval tv; int i, n; __mwc.z = 0; if (gettimeofday(&tv, NULL) == 0) __mwc.z = (uint64_t)tv.tv_sec ^ (uint64_t)tv.tv_usec; __mwc.z += ~((unsigned char *)&__mwc.z - (unsigned char *)&tv); __mwc.w = (uint64_t)getpid() ^ (uint64_t)getppid()<<12; n = (int)__mwc.z % 1733; for (i = 0; i < n; i++) (void)mwc(); } stress-ng-0.03.15/stress-seek.c0000664000175000017500000000634212466243156014703 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_seek_size = DEFAULT_SEEK_SIZE; void stress_set_seek_size(const char *optarg) { opt_seek_size = get_uint64_byte(optarg); check_range("seek-size", opt_seek_size, MIN_SEEK_SIZE, MAX_SEEK_SIZE); } /* * stress_seek * stress I/O via random seeks and read/writes */ int stress_seek( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint64_t i; const pid_t pid = getpid(); int fd, rc = EXIT_FAILURE; char filename[PATH_MAX]; uint8_t buf[512]; uint64_t len = opt_seek_size - sizeof(buf); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; for (i = 0; i < sizeof(buf); i++) buf[i] = (uint8_t)mwc(); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); goto finish; } (void)unlink(filename); /* Generate file with hole at the end */ if (lseek(fd, (off_t)len, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); goto close_finish; } if (write(fd, buf, sizeof(buf)) < 0) { pr_failed_err(name, "write"); goto close_finish; } do { uint64_t offset; uint8_t tmp[512]; ssize_t ret; offset = mwc() % len; if (lseek(fd, (off_t)offset, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); goto close_finish; } if (write(fd, buf, sizeof(buf)) < 0) { pr_failed_err(name, "write"); goto close_finish; } offset = mwc() % len; if (lseek(fd, (off_t)offset, SEEK_SET) < 0) { pr_failed_err(name, "lseek"); goto close_finish; } if ((ret = read(fd, tmp, sizeof(tmp))) < 0) { pr_failed_err(name, "read"); goto close_finish; } if ((ret != sizeof(tmp)) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "incorrect read size, expecting 512 bytes"); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; close_finish: (void)close(fd); finish: (void)stress_temp_dir_rm(name, pid, instance); return rc; } stress-ng-0.03.15/stress-vm-rw.c0000664000175000017500000001505212466243156015022 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #if defined(__linux__) #include "stress-ng.h" typedef struct { void *addr; /* Buffer to read/write to */ uint8_t val; /* Value to check */ } addr_msg_t; static size_t opt_vm_rw_bytes = DEFAULT_VM_RW_BYTES; void stress_set_vm_rw_bytes(const char *optarg) { opt_vm_rw_bytes = (size_t)get_uint64_byte(optarg); check_range("vm-rw-bytes", opt_vm_rw_bytes, MIN_VM_RW_BYTES, MAX_VM_RW_BYTES); } /* * stress_vm_rw * stress vm_read_v/vm_write_v */ int stress_vm_rw( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int pipe_wr[2], pipe_rd[2]; const size_t page_size = stress_get_pagesize(); const size_t sz = opt_vm_rw_bytes & ~(page_size - 1); (void)instance; if (pipe(pipe_wr) < 0) { pr_failed_dbg(name, "pipe"); return EXIT_FAILURE; } if (pipe(pipe_rd) < 0) { (void)close(pipe_wr[0]); (void)close(pipe_wr[1]); pr_failed_dbg(name, "pipe"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { (void)close(pipe_wr[0]); (void)close(pipe_wr[1]); (void)close(pipe_rd[0]); (void)close(pipe_rd[1]); pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { /* Child */ uint8_t *buf; int ret = EXIT_SUCCESS; addr_msg_t msg_rd, msg_wr; /* Close unwanted ends */ (void)close(pipe_wr[0]); (void)close(pipe_rd[1]); buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (buf == MAP_FAILED) { pr_failed_dbg(name, "mmap"); ret = EXIT_FAILURE; goto cleanup; } for (;;) { uint8_t *ptr, *end = buf + sz; int ret; msg_wr.addr = buf; msg_wr.val = 0; /* Send address of buffer to parent */ ret = write(pipe_wr[1], &msg_wr, sizeof(msg_wr)); if (ret < 0) { if (errno != EBADF) pr_failed_dbg(name, "write"); break; } /* Wait for parent to populate data */ ret = read(pipe_rd[0], &msg_rd, sizeof(msg_rd)); if (ret == 0) break; if (ret != sizeof(msg_rd)) { pr_failed_dbg(name, "read"); break; } if (opt_flags & OPT_FLAGS_VERIFY) { /* Check memory altered by parent is sane */ for (ptr = buf; ptr < end; ptr += page_size) { if (*ptr != msg_rd.val) { pr_fail(stderr, "%s: memory at %p: %d vs %d\n", name, ptr, *ptr, msg_rd.val); goto cleanup; } *ptr = 0; } } } cleanup: /* Tell parent we're done */ msg_wr.addr = 0; msg_wr.val = 0; if (write(pipe_wr[1], &msg_wr, sizeof(msg_wr)) <= 0) { if (errno != EBADF) pr_dbg(stderr, "%s: failed to write termination message " "over pipe: errno=%d (%s)\n", name, errno, strerror(errno)); } (void)close(pipe_wr[0]); (void)close(pipe_wr[1]); (void)close(pipe_rd[0]); (void)close(pipe_rd[1]); (void)munmap(buf, sz); exit(ret); } else { /* Parent */ int status; uint8_t val = 0; uint8_t *localbuf; addr_msg_t msg_rd, msg_wr; localbuf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (localbuf == MAP_FAILED) { (void)close(pipe_wr[0]); (void)close(pipe_wr[1]); (void)close(pipe_rd[0]); (void)close(pipe_rd[1]); pr_failed_dbg(name, "mmap"); exit(EXIT_FAILURE); } /* Close unwanted ends */ (void)close(pipe_wr[1]); (void)close(pipe_rd[0]); do { struct iovec local[1], remote[1]; uint8_t *ptr, *end = localbuf + sz; int ret; /* Wait for address of child's buffer */ ret = read(pipe_wr[0], &msg_rd, sizeof(msg_rd)); if (ret == 0) break; if (ret != sizeof(msg_rd)) { pr_failed_dbg(name, "read"); break; } /* Child telling us it's terminating? */ if (!msg_rd.addr) break; /* Perform read from child's memory */ local[0].iov_base = localbuf; local[0].iov_len = sz; remote[0].iov_base = msg_rd.addr; remote[0].iov_len = sz; if (process_vm_readv(pid, local, 1, remote, 1, 0) < 0) { pr_failed_dbg(name, "process_vm_readv"); break; } if (opt_flags & OPT_FLAGS_VERIFY) { /* Check data is sane */ for (ptr = localbuf; ptr < end; ptr += page_size) { if (*ptr) { pr_fail(stderr, "%s: memory at %p: %d vs %d\n", name, ptr, *ptr, msg_rd.val); goto fail; } *ptr = 0; } /* Set memory */ for (ptr = localbuf; ptr < end; ptr += page_size) *ptr = val; } /* Write to child's memory */ msg_wr = msg_rd; local[0].iov_base = localbuf; local[0].iov_len = sz; remote[0].iov_base = msg_rd.addr; remote[0].iov_len = sz; if (process_vm_writev(pid, local, 1, remote, 1, 0) < 0) { pr_failed_dbg(name, "process_vm_writev"); break; } msg_wr.val = val; val++; /* Inform child that memory has been changed */ ret = write(pipe_rd[1], &msg_wr, sizeof(msg_wr)); if (ret < 0) { if (errno != EBADF) pr_failed_dbg(name, "write"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); fail: /* Tell child we're done */ msg_wr.addr = NULL; msg_wr.val = 0; if (write(pipe_wr[0], &msg_wr, sizeof(msg_wr)) < 0) { if (errno != EBADF) pr_dbg(stderr, "%s: failed to write termination message " "over pipe: errno=%d (%s)\n", name, errno, strerror(errno)); } (void)close(pipe_wr[0]); (void)close(pipe_wr[1]); (void)close(pipe_rd[0]); (void)close(pipe_rd[1]); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); (void)munmap(localbuf, sz); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-cache.c0000664000175000017500000000614412466243156015017 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #if defined (_POSIX_PRIORITY_SCHEDULING) || defined (__linux__) #include #endif #include "stress-ng.h" /* The compiler optimises out the unused cache flush and mfence calls */ #define CACHE_WRITE(flag) \ for (j = 0; j < MEM_CACHE_SIZE; j++) { \ mem_cache[i] += mem_cache[(MEM_CACHE_SIZE - 1) - i] + r;\ if ((flag) & OPT_FLAGS_CACHE_FLUSH) { \ clflush(&mem_cache[i]); \ } \ if ((flag) & OPT_FLAGS_CACHE_FENCE) { \ mfence(); \ } \ i = (i + 32769) & (MEM_CACHE_SIZE - 1); \ if (!opt_do_run) \ break; \ } /* * stress_cache() * stress cache by psuedo-random memory read/writes and * if possible change CPU affinity to try to cause * poor cache behaviour */ int stress_cache( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { unsigned long total = 0; #if defined(__linux__) unsigned long int cpu = 0; cpu_set_t mask; #endif (void)instance; uint8_t *mem_cache = shared->mem_cache; do { uint64_t i = mwc() & (MEM_CACHE_SIZE - 1); uint64_t r = mwc(); register int j; if ((r >> 13) & 1) { switch (opt_flags & OPT_FLAGS_CACHE_MASK) { case OPT_FLAGS_CACHE_FLUSH: CACHE_WRITE(OPT_FLAGS_CACHE_FLUSH); break; case OPT_FLAGS_CACHE_FENCE: CACHE_WRITE(OPT_FLAGS_CACHE_FENCE); break; case OPT_FLAGS_CACHE_FENCE | OPT_FLAGS_CACHE_FLUSH: CACHE_WRITE(OPT_FLAGS_CACHE_FLUSH | OPT_FLAGS_CACHE_FENCE); break; default: CACHE_WRITE(0); break; } } else { for (j = 0; j < MEM_CACHE_SIZE; j++) { total += mem_cache[i] + mem_cache[(MEM_CACHE_SIZE - 1) - i]; i = (i + 32769) & (MEM_CACHE_SIZE - 1); if (!opt_do_run) break; } } #if defined(__linux__) cpu++; cpu %= stress_get_processors_online(); CPU_ZERO(&mask); CPU_SET(cpu, &mask); sched_setaffinity(0, sizeof(mask), &mask); #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_dbg(stderr, "%s: total [%lu]\n", name, total); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-affinity.c0000664000175000017500000000415112466243156015561 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include "stress-ng.h" /* * stress on sched_affinity() * stress system by changing CPU affinity periodically */ int stress_affinity( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { unsigned long int cpu = 0; cpu_set_t mask; (void)instance; (void)name; do { cpu = (opt_flags & OPT_FLAGS_AFFINITY_RAND) ? (mwc() >> 4) : cpu + 1; cpu %= stress_get_processors_online(); CPU_ZERO(&mask); CPU_SET(cpu, &mask); if (sched_setaffinity(0, sizeof(mask), &mask) < 0) { pr_fail(stderr, "failed to move to CPU %lu\n", cpu); } else { /* Now get and check */ CPU_ZERO(&mask); CPU_SET(cpu, &mask); sched_getaffinity(0, sizeof(mask), &mask); if ((opt_flags & OPT_FLAGS_VERIFY) && (!CPU_ISSET(cpu, &mask))) pr_fail(stderr, "failed to move to CPU %lu\n", cpu); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-utime.c0000664000175000017500000000476112466243156015102 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_utime() * stress system by setting file utime */ int stress_utime( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char filename[PATH_MAX]; int fd; const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); if ((fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { pr_err(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } do { #if defined(__linux__) if (futimens(fd, NULL) < 0) { pr_dbg(stderr, "%s: futimens failed: errno=%d: (%s)\n", name, errno, strerror(errno)); break; } #endif if (utime(filename, NULL) < 0) { pr_dbg(stderr, "%s: utime failed: errno=%d: (%s)\n", name, errno, strerror(errno)); break; } /* forces metadata writeback */ if (opt_flags & OPT_FLAGS_UTIME_FSYNC) (void)fsync(fd); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); (void)unlink(filename); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } stress-ng-0.03.15/sched.c0000664000175000017500000000664212466243156013524 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #if (defined(_POSIX_PRIORITY_SCHEDULING) || defined(__linux__)) && !defined(__OpenBSD__) #include #endif #include "stress-ng.h" #if (defined(_POSIX_PRIORITY_SCHEDULING) || defined(__linux__)) && !defined(__OpenBSD__) /* * set_sched() * are sched settings valid, if so, set them */ void set_sched(const int sched, const int sched_priority) { #if defined (SCHED_FIFO) || defined (SCHED_RR) int min, max; #endif int rc; struct sched_param param; switch (sched) { case UNDEFINED: /* No preference, don't set */ return; #if defined (SCHED_FIFO) || defined (SCHED_RR) case SCHED_FIFO: case SCHED_RR: min = sched_get_priority_min(sched); max = sched_get_priority_max(sched); if ((sched_priority == UNDEFINED) || (sched_priority > max) || (sched_priority < min)) { fprintf(stderr, "Scheduler priority level must be set between %d and %d\n", min, max); exit(EXIT_FAILURE); } param.sched_priority = sched_priority; break; #endif default: if (sched_priority != UNDEFINED) fprintf(stderr, "Cannot set sched priority for chosen scheduler, defaulting to 0\n"); param.sched_priority = 0; } pr_dbg(stderr, "setting scheduler class %d, priority %d\n", sched, param.sched_priority); rc = sched_setscheduler(getpid(), sched, ¶m); if (rc < 0) { fprintf(stderr, "Cannot set scheduler priority: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } #else void set_sched(const int sched, const int sched_priority) { (void)sched; (void)sched_priority; } #endif /* * get_opt_sched() * get scheduler policy */ int get_opt_sched(const char *const str) { #ifdef SCHED_OTHER if (!strcmp("other", str)) return SCHED_OTHER; #endif #ifdef SCHED_BATCH if (!strcmp("batch", str)) return SCHED_BATCH; #endif #ifdef SCHED_IDLE if (!strcmp("idle", str)) return SCHED_IDLE; #endif #ifdef SCHED_FIFO if (!strcmp("fifo", str)) return SCHED_FIFO; #endif #ifdef SCHED_RR if (!strcmp("rr", str)) return SCHED_RR; #endif if (strcmp("which", str)) fprintf(stderr, "Invalid sched option: %s\n", str); fprintf(stderr, "Available scheduler options are:" #ifdef SCHED_OTHER " other" #endif #ifdef SCHED_BATCH " batch" #endif #ifdef SCHED_IDLE " idle" #endif #ifdef SCHED_FIFO " fifo" #endif #ifdef SCHED_FIFO " rr" #endif "\n"); exit(EXIT_FAILURE); } stress-ng-0.03.15/stress-dir.c0000664000175000017500000000525212466243156014531 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_dir_tidy() * remove all dentries */ static void stress_dir_tidy( const uint64_t n, const char *name, const pid_t pid, const uint64_t instance) { uint64_t i; for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t gray_code = (i >> 1) ^ i; (void)stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); (void)rmdir(path); } } /* * stress_dir * stress directory mkdir and rmdir */ int stress_dir( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; do { uint64_t i, n = DEFAULT_DIRS; for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t gray_code = (i >> 1) ^ i; (void)stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); if (mkdir(path, S_IRUSR | S_IWUSR) < 0) { pr_failed_err(name, "mkdir"); n = i; break; } if (!opt_do_run || (max_ops && *counter >= max_ops)) goto abort; (*counter)++; } stress_dir_tidy(n, name, pid, instance); if (!opt_do_run) break; sync(); } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: /* force unlink of all files */ pr_tidy(stderr, "%s: removing %" PRIu32 " directories\n", name, DEFAULT_DIRS); stress_dir_tidy(DEFAULT_DIRS, name, pid, instance); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-socket.c0000664000175000017500000001275212466243156015246 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef AF_INET6 #include #endif #ifdef AF_UNIX #include #endif #include "stress-ng.h" static int opt_socket_domain = AF_INET; static int opt_socket_port = DEFAULT_SOCKET_PORT; void stress_set_socket_port(const char *optarg) { stress_set_net_port("sock-port", optarg, MIN_SOCKET_PORT, MAX_SOCKET_PORT - STRESS_PROCS_MAX, &opt_socket_port); } /* * stress_set_socket_domain() * set the socket domain option */ int stress_set_socket_domain(const char *name) { return stress_set_net_domain("sock-domain", name, &opt_socket_domain); } /* * handle_socket_sigalrm() * catch SIGALRM */ static void handle_socket_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_socket * stress by heavy socket I/O */ int stress_socket( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid, ppid = getppid(); int rc = EXIT_SUCCESS; pr_dbg(stderr, "%s: process [%d] using socket port %d\n", name, getpid(), opt_socket_port + instance); pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { /* Child, client */ struct sockaddr *addr; do { char buf[SOCKET_BUF]; int fd; int retries = 0; socklen_t addr_len = 0; retry: if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { pr_failed_dbg(name, "socket"); /* failed, kick parent to finish */ (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } stress_set_sockaddr(name, instance, ppid, opt_socket_domain, opt_socket_port, &addr, &addr_len); if (connect(fd, addr, addr_len) < 0) { (void)close(fd); usleep(10000); retries++; if (retries > 100) { /* Give up.. */ pr_failed_dbg(name, "connect"); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } goto retry; } retries = 0; do { ssize_t n = recv(fd, buf, sizeof(buf), 0); if (n == 0) break; if (n < 0) { if (errno != EINTR) pr_failed_dbg(name, "recv"); break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); #ifdef AF_UNIX if (opt_socket_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif /* Inform parent we're all done */ (void)kill(getppid(), SIGALRM); exit(EXIT_SUCCESS); } else { /* Parent, server */ char buf[SOCKET_BUF]; int fd, status; int so_reuseaddr = 1; struct sigaction new_action; socklen_t addr_len = 0; struct sockaddr *addr; new_action.sa_handler = handle_socket_sigalrm; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { pr_failed_dbg(name, "socket"); rc = EXIT_FAILURE; goto die; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_failed_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, opt_socket_domain, opt_socket_port, &addr, &addr_len); if (bind(fd, addr, addr_len) < 0) { pr_failed_dbg(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (listen(fd, 10) < 0) { pr_failed_dbg(name, "listen"); rc = EXIT_FAILURE; goto die_close; } do { int sfd = accept(fd, (struct sockaddr *)NULL, NULL); if (sfd >= 0) { size_t i; memset(buf, 'A' + (*counter % 26), sizeof(buf)); for (i = 16; i < sizeof(buf); i += 16) { ssize_t ret = send(sfd, buf, i, 0); if (ret < 0) { if (errno != EINTR) pr_failed_dbg(name, "send"); break; } } (void)close(sfd); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: (void)close(fd); die: #ifdef AF_UNIX if (opt_socket_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif if (pid) { (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } } return rc; } stress-ng-0.03.15/syscalls.txt0000664000175000017500000000420512466243156014661 0ustar kingkingSyscall Stressor accept sock bind sock brk bigheap brk brk chmod chmod clock_getres clock clock_gettime clock clock_nanosleep clock close dentry connect sock endmntent sysinfo epoll_create1 epoll epoll_ctl_add epoll epoll_wait epoll eventfd eventfd fchmod chmod fcntl open, lockf flock flock fork fork fstat fallocate fsync fallocate ftruncate fallocate futex futex futimens wait getegid get geteuid get getgid get getgroups get getmntent sysinfo getpgid get getpgrp get getpid get getppid get getpriority get getpwd get getresgid get getresuid get getrlimit get getrlimit nice getrusage get getsid get gettid get gettimeofday get getuid get inotify_add_watch inotify inotify_init inotify inotify_rm_watch inotify kill kill listen sock mkdir dir mkstemp hdd madvise mmap madvise vm mincore bigheap mincore mincore mincore mmap mincore vm mmap bigheap mmap mmap mprotect mmap msgctl msg msgget msg msgrcv msg msgsnd msg munmap mmap mq_open mq mq_send mq mq_receive mq mq_unlink mq mq_close mq nanosleep timer open dentry open open pipe pipe pipe switch poll poll posix_fallocate fallocate /proc proc process_vm_readv vm_rw process_vm_writev vm_rw read pipe read zero recv sock rename rename rmdir dir sbrk brk sched_getaffinity affinity sched_setaffinity affinity sched_yield yield select poll sem_destroy sem sem_init sem sem_post sem sem_wait sem send sock sendfile sendfile setmntent sysinfo setpriority nice setsockopt sock sigaction sigfpe siglongjmp sigfpe sigqueue sigq sigsetjmp sigfpe sigwaitinfo sigfpe socket sock statfs sysinfo stat fstat sync iosync sysinfo sysinfo timer_create clock timer_create timer timer_delete clock timer_delete timer timer_gettime clock timer_settime timer times sysinfo unlink dentry unlink hdd unlink unlink vfork vfork waitid wait waitpid fork waitpid wait write hdd write null write pipe pread aio pwrite aio stress-ng-0.03.15/stress-fork.c0000664000175000017500000000652112466243156014714 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_fork_max = DEFAULT_FORKS; static uint64_t opt_vfork_max = DEFAULT_VFORKS; /* * stress_set_fork_max() * set maximum number of forks allowed */ void stress_set_fork_max(const char *optarg) { opt_fork_max = get_uint64_byte(optarg); check_range("fork-max", opt_fork_max, MIN_FORKS, MAX_FORKS); } /* * stress_set_vfork_max() * set maximum number of vforks allowed */ void stress_set_vfork_max(const char *optarg) { opt_vfork_max = get_uint64_byte(optarg); check_range("vfork-max", opt_vfork_max, MIN_VFORKS, MAX_VFORKS); } /* * stress_fork_fn() * stress by forking and exiting using * fork function fork_fn (fork or vfork) */ int stress_fork_fn( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, pid_t (*fork_fn)(void), const uint64_t fork_max) { (void)instance; (void)name; pid_t pids[MAX_FORKS]; do { unsigned int i; memset(pids, 0, sizeof(pids)); for (i = 0; i < fork_max; i++) { pids[i] = fork_fn(); if (pids[i] == 0) { /* Child, immediately exit */ _exit(0); } if (!opt_do_run) break; } for (i = 0; i < fork_max; i++) { if (pids[i] > 0) { int status; /* Parent, wait for child */ waitpid(pids[i], &status, 0); (*counter)++; } } for (i = 0; i < fork_max; i++) { if ((pids[i] < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "fork failed\n"); } } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } /* * stress_fork() * stress by forking and exiting */ int stress_fork( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { return stress_fork_fn(counter, instance, max_ops, name, fork, opt_fork_max); } #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) /* * stress_vfork() * stress by vforking and exiting */ int stress_vfork( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { return stress_fork_fn(counter, instance, max_ops, name, vfork, opt_vfork_max); } #endif stress-ng-0.03.15/stress-cpu.c0000664000175000017500000012073612466243156014547 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include "stress-ng.h" #define GAMMA (0.57721566490153286060651209008240243104215933593992L) #define OMEGA (0.5671432904097838729999686622L) #define PSI (3.35988566624317755317201130291892717968890513373L) /* Some awful *BSD math lib workarounds */ #if defined(__NetBSD__) #define rintl rint #define logl log #define expl exp #define powl pow #define cosl cos #define sinl sin #define coshl cosh #define sinhl sinh #define ccosl ccos #define csinl csin #define cabsl cabs #define sqrtl sqrt #endif #if defined(__FreeBSD__) #define ccosl ccos #define csinl csin #define cpow pow #define powl pow #endif /* * the CPU stress test has different classes of cpu stressor */ typedef void (*stress_cpu_func)(void); typedef struct { const char *name; /* human readable form of stressor */ const stress_cpu_func func; /* the stressor function */ } stress_cpu_stressor_info_t; static int32_t opt_cpu_load = 100; static stress_cpu_stressor_info_t *opt_cpu_stressor; static stress_cpu_stressor_info_t cpu_methods[]; void stress_set_cpu_load(const char *optarg) { opt_cpu_load = opt_long("cpu load", optarg); if ((opt_cpu_load < 0) || (opt_cpu_load > 100)) { fprintf(stderr, "CPU load must in the range 0 to 100.\n"); exit(EXIT_FAILURE); } } /* * stress_cpu_sqrt() * stress CPU on square roots */ static void stress_cpu_sqrt(void) { int i; for (i = 0; i < 16384; i++) { uint64_t rnd = mwc(); double r = sqrt((double)rnd) * sqrt((double)rnd); if ((opt_flags & OPT_FLAGS_VERIFY) && (uint64_t)rint(r) != rnd) { pr_fail(stderr, "sqrt error detected on sqrt(%" PRIu64 ")\n", rnd); if (!opt_do_run) break; } } } /* * We need to stop gcc optimising out the loop additions.. sigh */ #if __GNUC__ && !defined(__clang__) static void stress_cpu_loop(void) __attribute__((optimize("-O0"))); #endif /* * stress_cpu_loop() * simple CPU busy loop */ static void stress_cpu_loop(void) { uint32_t i, i_sum = 0; const uint32_t sum = 134209536UL; for (i = 0; i < 16384; i++) { i_sum += i; #if __GNUC__ __asm__ __volatile__(""); /* Stop optimising out */ #endif } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "cpu loop 0..16383 sum was %" PRIu32 " and " "did not match the expected value of %" PRIu32 "\n", i_sum, sum); } /* * stress_cpu_gcd() * compute Greatest Common Divisor */ static void stress_cpu_gcd(void) { uint32_t i, i_sum = 0; const uint32_t sum = 63000868UL; for (i = 0; i < 16384; i++) { register uint32_t a = i, b = i % (3 + (1997 ^ i)); while (b != 0) { register uint32_t r = b; b = a % b; a = r; } i_sum += a; #if __GNUC__ __asm__ __volatile__(""); /* Stop optimising out */ #endif } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "gcd error detected, failed modulo or assigment operations\n"); } /* * stress_cpu_bitops() * various bit manipulation hacks from bithacks * https://graphics.stanford.edu/~seander/bithacks.html */ static void stress_cpu_bitops(void) { uint32_t i, i_sum = 0; const uint32_t sum = 0x8aadcaab; for (i = 0; i < 16384; i++) { { uint32_t r, v, s = (sizeof(v) * 8) - 1; /* Reverse bits */ r = v = i; for (v >>= 1; v; v >>= 1, s--) { r <<= 1; r |= v & 1; } r <<= s; i_sum += r; } { /* parity check */ uint32_t v = i; v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; i_sum += v; } { /* Brian Kernighan count bits */ uint32_t j, v = i; for (j = 0; v; j++) v &= v - 1; i_sum += j; } { /* round up to nearest highest power of 2 */ uint32_t v = i - 1; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; i_sum += v; } } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "bitops error detected, failed bitops operations\n"); } /* * stress_cpu_trig() * simple sin, cos trig functions */ static void stress_cpu_trig(void) { int i; long double d_sum = 0.0; for (i = 0; i < 1500; i++) { long double theta = (2.0 * M_PI * (double)i)/1500.0; { d_sum += (cosl(theta) * sinl(theta)); d_sum += (cos(theta) * sin(theta)); d_sum += (cosf(theta) * sinf(theta)); } { long double theta2 = theta * 2.0; d_sum += cosl(theta2); d_sum += cos(theta2); d_sum += cosf(theta2); } { long double theta3 = theta * 3.0; d_sum += sinl(theta3); d_sum += sin(theta3); d_sum += sinf(theta3); } } double_put(d_sum); } /* * stress_cpu_hyperbolic() * simple hyperbolic sinh, cosh functions */ static void stress_cpu_hyperbolic(void) { int i; double d_sum = 0.0; for (i = 0; i < 1500; i++) { long double theta = (2.0 * M_PI * (double)i)/1500.0; { d_sum += (coshl(theta) * sinhl(theta)); d_sum += (cosh(theta) * sinh(theta)); d_sum += (coshf(theta) * sinhf(theta)); } { long double theta2 = theta * 2.0; d_sum += coshl(theta2); d_sum += cosh(theta2); d_sum += coshf(theta2); } { long double theta3 = theta * 3.0; d_sum += sinhl(theta3); d_sum += sinh(theta3); d_sum += sinhf(theta3); } } double_put(d_sum); } /* * stress_cpu_rand() * generate lots of pseudo-random integers */ static void stress_cpu_rand(void) { int i; uint32_t i_sum = 0; const uint32_t sum = 0xc253698c; MWC_SEED(); for (i = 0; i < 16384; i++) i_sum += mwc(); if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "rand error detected, failed sum of pseudo-random values\n"); } /* * stress_cpu_nsqrt() * iterative Newton–Raphson square root */ static void stress_cpu_nsqrt(void) { int i; const long double precision = 1.0e-12; const int max_iter = 56; for (i = 0; i < 16384; i++) { long double n = (double)i; long double lo = (n < 1.0) ? n : 1.0; long double hi = (n < 1.0) ? 1.0 : n; long double rt; int j = 0; while ((j++ < max_iter) && ((hi - lo) > precision)) { long double g = (lo + hi) / 2.0; if ((g * g) > n) hi = g; else lo = g; } rt = (lo + hi) / 2.0; if (opt_flags & OPT_FLAGS_VERIFY) { if (j >= max_iter) pr_fail(stderr, "Newton-Raphson sqrt computation took more iterations than expected\n"); if ((int)rintl(rt * rt) != i) pr_fail(stderr, "Newton-Rapshon sqrt not accurate enough\n"); } } } /* * stress_cpu_phi() * compute the Golden Ratio */ static void stress_cpu_phi(void) { long double phi; /* Golden ratio */ const long double precision = 1.0e-15; const long double phi_ = (1.0 + sqrtl(5.0)) / 2.0; register uint64_t a, b; const uint64_t mask = 1ULL << 63; int i; /* Pick any two starting points */ a = mwc() % 99; b = mwc() % 99; /* Iterate until we approach overflow */ for (i = 0; (i < 64) && !((a | b) & mask); i++) { /* Find nth term */ register uint64_t c = a + b; a = b; b = c; } /* And we have the golden ratio */ phi = (long double)b / (long double)a; if ((opt_flags & OPT_FLAGS_VERIFY) && (fabsl(phi - phi_) > precision)) pr_fail(stderr, "Golden Ratio phi not accurate enough\n"); } /* * fft_partial() * partial Fast Fourier Transform */ static void fft_partial(double complex *data, double complex *tmp, const int n, const int m) { if (m < n) { const int m2 = m * 2; int i; fft_partial(tmp, data, n, m2); fft_partial(tmp + m, data + m, n, m2); for (i = 0; i < n; i += m2) { double complex v = tmp[i]; double complex t = cexp((-I * M_PI * (double)i) / (double)n) * tmp[i + m]; data[i / 2] = v + t; data[(i + n) / 2] = v - t; } } } /* * stress_cpu_fft() * Fast Fourier Transform */ static void stress_cpu_fft(void) { double complex buf[FFT_SIZE], tmp[FFT_SIZE]; int i; for (i = 0; i < FFT_SIZE; i++) buf[i] = (double complex)(i % 63); memcpy(tmp, buf, sizeof(double complex) * FFT_SIZE); fft_partial(buf, tmp, FFT_SIZE, 1); } /* * stress_cpu_euler() * compute e using series */ static void stress_cpu_euler(void) { long double e = 1.0, last_e = e; long double fact = 1.0; long double precision = 1.0e-20; int n = 1; do { last_e = e; fact *= n; n++; e += (1.0 / fact); } while ((n < 25) && (fabsl(e - last_e) > precision)); if ((opt_flags & OPT_FLAGS_VERIFY) && (n >= 25)) pr_fail(stderr, "euler computation took more iterations than expected\n"); } /* * random_buffer() * fill a uint8_t buffer full of random data * buffer *must* be multiple of 4 bytes in size */ static void random_buffer(uint8_t *data, const size_t len) { size_t i; for (i = 0; i < len / 4; i++) { uint32_t v = (uint32_t)mwc(); *data++ = v; v >>= 8; *data++ = v; v >>= 8; *data++ = v; v >>= 8; *data++ = v; } } /* * stress_cpu_hash_generic() * stress test generic string hash function */ static void stress_cpu_hash_generic( const char *name, uint32_t (*hash_func)(const char *str), const uint32_t result) { char buffer[128]; size_t i; uint32_t i_sum = 0; MWC_SEED(); random_buffer((uint8_t *)buffer, sizeof(buffer)); /* Make it ASCII range ' '..'_' */ for (i = 0; i < sizeof(buffer); i++) buffer[i] = (buffer[i] & 0x3f) + ' '; for (i = sizeof(buffer) - 1; i; i--) { buffer[i] = '\0'; i_sum += hash_func(buffer); } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != result)) pr_fail(stderr, "%s error detected, failed hash %s sum\n", name, name); } /* * jenkin() * Jenkin's hash on random data * http://www.burtleburtle.net/bob/hash/doobs.html */ static uint32_t jenkin(const uint8_t *data, const size_t len) { uint8_t i; register uint32_t h = 0; for (i = 0; i < len; i++) { h += *data++; h += h << 10; h ^= h >> 6; } h += h << 3; h ^= h >> 11; h += h << 15; return h; } /* * stress_cpu_jenkin() * multiple iterations on jenkin hash */ static void stress_cpu_jenkin(void) { uint8_t buffer[128]; size_t i; uint32_t i_sum = 0; const uint32_t sum = 0x96673680; MWC_SEED(); random_buffer(buffer, sizeof(buffer)); for (i = 0; i < sizeof(buffer); i++) i_sum += jenkin(buffer, sizeof(buffer)); if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "jenkin error detected, failed hash jenkin sum\n"); } /* * pjw() * Hash a string, from Aho, Sethi, Ullman, Compiling Techniques. */ static uint32_t pjw(const char *str) { uint32_t h = 0; while (*str) { uint32_t g; h = (h << 4) + (*str); if (0 != (g = h & 0xf0000000)) { h = h ^ (g >> 24); h = h ^ g; } str++; } return h; } /* * stress_cpu_pjw() * stress test hash pjw */ static void stress_cpu_pjw(void) { stress_cpu_hash_generic("pjw", pjw, 0xa89a91c0); } /* * djb2a() * Hash a string, from Dan Bernstein comp.lang.c (xor version) */ static uint32_t djb2a(const char *str) { uint32_t hash = 5381; int c; while ((c = *str++)) { /* (hash * 33) ^ c */ hash = ((hash << 5) + hash) ^ c; } return hash; } /* * stress_cpu_djb2a() * stress test hash djb2a */ static void stress_cpu_djb2a(void) { stress_cpu_hash_generic("djb2a", djb2a, 0x6a60cb5a); } /* * fnv1a() * Hash a string, using the improved 32 bit FNV-1a hash */ static uint32_t fnv1a(const char *str) { uint32_t hash = 5381; const uint32_t fnv_prime = 16777619; /* 2^24 + 2^9 + 0x93 */ int c; while ((c = *str++)) { hash ^= c; hash *= fnv_prime; } return hash; } /* * stress_cpu_fnv1a() * stress test hash fnv1a */ static void stress_cpu_fnv1a(void) { stress_cpu_hash_generic("fnv1a", fnv1a, 0x8ef17e80); } /* * sdbm() * Hash a string, using the sdbm data base hash and also * apparently used in GNU awk. */ static uint32_t sdbm(const char *str) { uint32_t hash = 0; int c; while ((c = *str++)) hash = c + (hash << 6) + (hash << 16) - hash; return hash; } /* * stress_cpu_sdbm() * stress test hash sdbm */ static void stress_cpu_sdbm(void) { stress_cpu_hash_generic("sdbm", sdbm, 0x46357819); } /* * stress_cpu_idct() * compute 8x8 Inverse Discrete Cosine Transform */ static void stress_cpu_idct(void) { const double invsqrt2 = 1.0 / sqrt(2.0); const double pi_over_16 = M_PI / 16.0; const int sz = 8; int i, j, u, v; float data[sz][sz], idct[sz][sz]; /* * Set up DCT */ for (i = 0; i < sz; i++) { for (j = 0; j < sz; j++) { data[i][j] = (i + j == 0) ? 2040: 0; } } for (i = 0; i < sz; i++) { const double pi_i = (i + i + 1) * pi_over_16; for (j = 0; j < sz; j++) { const double pi_j = (j + j + 1) * pi_over_16; double sum = 0.0; for (u = 0; u < sz; u++) { const double cos_pi_i_u = cos(pi_i * u); for (v = 0; v < sz; v++) { const double cos_pi_j_v = cos(pi_j * v); sum += (data[u][v] * (u ? 1.0 : invsqrt2) * (v ? 1.0 : invsqrt2) * cos_pi_i_u * cos_pi_j_v); } } idct[i][j] = 0.25 * sum; } } /* Final output should be a 8x8 matrix of values 255 */ for (i = 0; i < sz; i++) { for (j = 0; j < sz; j++) { if (((int)idct[i][j] != 255) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "IDCT error detected, IDCT[%d][%d] was %d, expecting 255\n", i, j, (int)idct[i][j]); } if (!opt_do_run) return; } } } #define int_ops(a, b, c1, c2, c3) \ do { \ a += b; \ b ^= a; \ a >>= 1; \ b <<= 2; \ b -= a; \ a ^= ~0; \ b ^= ~(c1); \ a *= 3; \ b *= 7; \ a += 2; \ b -= 3; \ a /= 77; \ b /= 3; \ a <<= 1; \ b <<= 2; \ a |= 1; \ b |= 3; \ a *= mwc(); \ b ^= mwc(); \ a += mwc(); \ b -= mwc(); \ a /= 7; \ b /= 9; \ a |= (c2); \ b &= (c3); \ } while (0); #define C1 (0xf0f0f0f0f0f0f0f0ULL) #define C2 (0x1000100010001000ULL) #define C3 (0xffeffffefebefffeULL) /* * Generic int stressor macro */ #define stress_cpu_int(_type, _sz, _a, _b, _c1, _c2, _c3) \ static void stress_cpu_int ## _sz(void) \ { \ const _type mask = ~0; \ const _type a_final = _a; \ const _type b_final = _b; \ const _type c1 = _c1 & mask; \ const _type c2 = _c2 & mask; \ const _type c3 = _c3 & mask; \ register _type a, b; \ int i; \ \ MWC_SEED(); \ a = mwc(); \ b = mwc(); \ \ for (i = 0; i < 1000; i++) { \ int_ops(a, b, c1, c2, c3) \ } \ \ if ((opt_flags & OPT_FLAGS_VERIFY) && \ ((a != a_final) || (b != b_final))) \ pr_fail(stderr, "int" # _sz " error detected, " \ "failed int" # _sz \ " math operations\n"); \ } \ /* For compilers that support int128 .. */ #if defined(STRESS_INT128) #define _UINT128(hi, lo) ((((__uint128_t)hi << 64) | (__uint128_t)lo)) stress_cpu_int(__uint128_t, 128, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3)) #endif stress_cpu_int(uint64_t, 64, \ 0x1ee5773113afd25aULL, 0x174df454b030714cULL, C1, C2, C3) stress_cpu_int(uint32_t, 32, \ 0x1ce9b547UL, 0xa24b33aUL, C1, C2, C3) stress_cpu_int(uint16_t, 16, \ 0x1871, 0x07f0, C1, C2, C3) stress_cpu_int(uint8_t, 8, \ 0x12, 0x1a, C1, C2, C3) #define float_ops(_type, a, b, c, d, sin, cos) \ do { \ a = a + b; \ b = a * c; \ c = a - b; \ d = a / b; \ a = c / (_type)0.1923; \ b = c + a; \ c = b * (_type)3.12; \ d = d + b + (_type)sin(a); \ a = (b + c) / c; \ b = b * c; \ c = c + (_type)1.0; \ d = d - (_type)sin(c); \ a = a * (_type)cos(b); \ b = b + (_type)cos(c); \ c = (_type)sin(a) / (_type)2.344; \ b = d - (_type)1.0; \ } while (0) /* * Generic floating point stressor macro */ #define stress_cpu_fp(_type, _name, _sin, _cos) \ static void stress_cpu_ ## _name(void) \ { \ int i; \ _type a = 0.18728, b = mwc(), c = mwc(), d; \ \ for (i = 0; i < 1000; i++) { \ float_ops(_type, a, b, c, d, \ _sin, _cos); \ } \ double_put(a + b + c + d); \ } stress_cpu_fp(float, float, sinf, cosf) stress_cpu_fp(double, double, sin, cos) stress_cpu_fp(long double, longdouble, sinl, cosl) #if defined(STRESS_FLOAT_DECIMAL) stress_cpu_fp(_Decimal32, decimal32, sinf, cosf) stress_cpu_fp(_Decimal64, decimal64, sin, cos) stress_cpu_fp(_Decimal128, decimal128, sinl, cosl) #endif /* * Generic complex stressor macro */ #define stress_cpu_complex(_type, _name, _csin, _ccos) \ static void stress_cpu_ ## _name(void) \ { \ int i; \ _type a = 0.18728 + I * 0.2762, \ b = mwc() - I * 0.11121, \ c = mwc() + I * mwc(), d; \ \ for (i = 0; i < 1000; i++) { \ float_ops(_type, a, b, c, d, \ _csin, _ccos); \ } \ double_put(a + b + c + d); \ } stress_cpu_complex(complex float, complex_float, csinf, ccosf) stress_cpu_complex(complex double, complex_double, csin, ccos) stress_cpu_complex(complex long double, complex_long_double, csinl, ccosl) #define int_float_ops(_ftype, flt_a, flt_b, flt_c, flt_d, \ _sin, _cos, int_a, int_b, _c1, _c2, _c3) \ do { \ int_a += int_b; \ int_b ^= int_a; \ flt_a = flt_a + flt_b; \ int_a >>= 1; \ int_b <<= 2; \ flt_b = flt_a * flt_c; \ int_b -= int_a; \ int_a ^= ~0; \ flt_c = flt_a - flt_b; \ int_b ^= ~(_c1); \ int_a *= 3; \ flt_d = flt_a / flt_b; \ int_b *= 7; \ int_a += 2; \ flt_a = flt_c / (_ftype)0.1923; \ int_b -= 3; \ int_a /= 77; \ flt_b = flt_c + flt_a; \ int_b /= 3; \ int_a <<= 1; \ flt_c = flt_b * (_ftype)3.12; \ int_b <<= 2; \ int_a |= 1; \ flt_d = flt_d + flt_b + (_ftype)_sin(flt_a); \ int_b |= 3; \ int_a *= mwc(); \ flt_a = (flt_b + flt_c) / flt_c; \ int_b ^= mwc(); \ int_a += mwc(); \ flt_b = flt_b * flt_c; \ int_b -= mwc(); \ int_a /= 7; \ flt_c = flt_c + (_ftype)1.0; \ int_b /= 9; \ flt_d = flt_d - (_ftype)_sin(flt_c); \ int_a |= (_c2); \ flt_a = flt_a * (_ftype)_cos(flt_b); \ flt_b = flt_b + (_ftype)_cos(flt_c); \ int_b &= (_c3); \ flt_c = (_ftype)_sin(flt_a) / (_ftype)2.344; \ flt_b = flt_d - (_ftype)1.0; \ } while (0) /* * Generic integer and floating point stressor macro */ #define stress_cpu_int_fp(_inttype, _sz, _ftype, _name, _a, _b, \ _c1, _c2, _c3, _sinf, _cosf) \ static void stress_cpu_int ## _sz ## _ ## _name(void) \ { \ int i; \ _inttype int_a, int_b; \ const _inttype mask = ~0; \ const _inttype a_final = _a; \ const _inttype b_final = _b; \ const _inttype c1 = _c1 & mask; \ const _inttype c2 = _c2 & mask; \ const _inttype c3 = _c3 & mask; \ _ftype flt_a = 0.18728, flt_b = mwc(), \ flt_c = mwc(), flt_d; \ \ MWC_SEED(); \ int_a = mwc(); \ int_b = mwc(); \ \ for (i = 0; i < 1000; i++) { \ int_float_ops(_ftype, flt_a, flt_b, flt_c, flt_d,\ _sinf, _cosf, int_a, int_b, c1, c2, c3);\ } \ if ((opt_flags & OPT_FLAGS_VERIFY) && \ ((int_a != a_final) || (int_b != b_final))) \ pr_fail(stderr, "int" # _sz " error detected, " \ "failed int" # _sz \ " math operations\n"); \ \ double_put(flt_a + flt_b + flt_c + flt_d); \ } stress_cpu_int_fp(uint32_t, 32, float, float, 0x1ce9b547UL, 0xa24b33aUL, C1, C2, C3, sinf, cosf) stress_cpu_int_fp(uint32_t, 32, double, double, 0x1ce9b547UL, 0xa24b33aUL, C1, C2, C3, sin, cos) stress_cpu_int_fp(uint32_t, 32, long double, longdouble, 0x1ce9b547UL, 0xa24b33aUL, C1, C2, C3, sinl, cosl) stress_cpu_int_fp(uint64_t, 64, float, float, 0x1ee5773113afd25aULL, 0x174df454b030714cULL, C1, C2, C3, sinf, cosf) stress_cpu_int_fp(uint64_t, 64, double, double, 0x1ee5773113afd25aULL, 0x174df454b030714cULL, C1, C2, C3, sin, cos) stress_cpu_int_fp(uint64_t, 64, long double, longdouble, 0x1ee5773113afd25aULL, 0x174df454b030714cULL, C1, C2, C3, sinl, cosl) #if defined(STRESS_INT128) stress_cpu_int_fp(__uint128_t, 128, float, float, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sinf, cosf) stress_cpu_int_fp(__uint128_t, 128, double, double, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sin, cos) stress_cpu_int_fp(__uint128_t, 128, long double, longdouble, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sinl, cosl) #if defined(STRESS_FLOAT_DECIMAL) stress_cpu_int_fp(__uint128_t, 128, _Decimal32, decimal32, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), (_Decimal32)sinf, (_Decimal32)cosf) stress_cpu_int_fp(__uint128_t, 128, _Decimal64, decimal64, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), (_Decimal64)sin, (_Decimal64)cos) stress_cpu_int_fp(__uint128_t, 128, _Decimal128, decimal128, _UINT128(0x1caaffe276809a64,0xf7a3387557025785), _UINT128(0x052970104c342020,0x4e4cc51e06b44800), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), (_Decimal128)sinl, (_Decimal128)cosl) #endif #endif /* * stress_cpu_rgb() * CCIR 601 RGB to YUV to RGB conversion */ static void stress_cpu_rgb(void) { int i; uint32_t rgb = mwc() & 0xffffff; uint8_t r = rgb >> 16; uint8_t g = rgb >> 8; uint8_t b = rgb; /* Do a 1000 colours starting from the rgb seed */ for (i = 0; i < 1000; i++) { float y,u,v; /* RGB to CCIR 601 YUV */ y = (0.299 * r) + (0.587 * g) + (0.114 * b); u = (b - y) * 0.565; v = (r - y) * 0.713; /* YUV back to RGB */ r = y + (1.403 * v); g = y - (0.344 * u) - (0.714 * v); b = y + (1.770 * u); /* And bump each colour to make next round */ r += 1; g += 2; b += 3; } uint64_put(r + g + b); } /* * stress_cpu_matrix_prod(void) * matrix product */ static void stress_cpu_matrix_prod(void) { int i, j, k; const int n = 128; long double a[n][n], b[n][n], r[n][n]; long double v = 1 / (long double)((uint32_t)~0); long double sum = 0.0; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { a[i][j] = (long double)mwc() * v; b[i][j] = (long double)mwc() * v; r[i][j] = 0.0; } } for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { for (k = 0; k < n; k++) { r[i][j] += a[i][k] * b[k][j]; } } } for (i = 0; i < n; i++) for (j = 0; j < n; j++) sum += r[i][j]; double_put(sum); } /* * stress_cpu_fibonacci() * compute fibonacci series */ static void stress_cpu_fibonacci(void) { const uint64_t fn_res = 0xa94fad42221f2702; register uint64_t f1 = 0, f2 = 1, fn; do { fn = f1 + f2; f1 = f2; f2 = fn; } while (!(fn & 0x8000000000000000ULL)); if ((opt_flags & OPT_FLAGS_VERIFY) && (fn_res != fn)) pr_fail(stderr, "fibonacci error detected, summation or assignment failure\n"); } /* * stress_cpu_psi * compute the constant psi, * the reciprocal Fibonacci constant */ static void stress_cpu_psi(void) { long double f1 = 0.0, f2 = 1.0; long double psi = 0.0, last_psi; long double precision = 1.0e-20; int i = 0; const int max_iter = 100; do { long double fn = f1 + f2; f1 = f2; f2 = fn; last_psi = psi; psi += 1.0 / f1; i++; } while ((i < max_iter) && (fabsl(psi - last_psi) > precision)); if (opt_flags & OPT_FLAGS_VERIFY) { if (fabsl(psi - PSI) > 1.0e-15) pr_fail(stderr, "calculation of reciprocal Fibonacci constant phi not as accurate as expected\n"); if (i >= max_iter) pr_fail(stderr, "calculation of reciprocal Fibonacci constant took more iterations than expected\n"); } double_put(psi); } /* * stress_cpu_ln2 * compute ln(2) using series */ static void stress_cpu_ln2(void) { long double ln2 = 0.0, last_ln2 = 0.0; long double precision = 1.0e-7; register int n = 1; const int max_iter = 10000; /* Not the fastest converging series */ do { last_ln2 = ln2; /* Unroll, do several ops */ ln2 += (long double)1.0 / (long double)n++; ln2 -= (long double)1.0 / (long double)n++; ln2 += (long double)1.0 / (long double)n++; ln2 -= (long double)1.0 / (long double)n++; ln2 += (long double)1.0 / (long double)n++; ln2 -= (long double)1.0 / (long double)n++; ln2 += (long double)1.0 / (long double)n++; ln2 -= (long double)1.0 / (long double)n++; } while ((n < max_iter) && (fabsl(ln2 - last_ln2) > precision)); if ((opt_flags & OPT_FLAGS_VERIFY) && (n >= max_iter)) pr_fail(stderr, "calculation of ln(2) took more iterations than expected\n"); double_put(ln2); } /* * ackermann() * a naive/simple implementation of the ackermann function */ static uint32_t ackermann(const uint32_t m, const uint32_t n) { if (m == 0) return n + 1; else if (n == 0) return ackermann(m - 1, 1); else return ackermann(m - 1, ackermann(m, n - 1)); } /* * stress_cpu_ackermann * compute ackermann function */ static void stress_cpu_ackermann(void) { uint32_t a = ackermann(3, 10); if ((opt_flags & OPT_FLAGS_VERIFY) && (a != 0x1ffd)) pr_fail(stderr, "ackermann error detected, ackermann(3,10) miscalculated\n"); } /* * stress_cpu_explog * compute exp(log(n)) */ static void stress_cpu_explog(void) { uint32_t i; double n = 1e6; for (i = 1; i < 100000; i++) n = exp(log(n) / 1.00002); } /* * Undocumented gcc-ism, force -O0 optimisation */ #if __GNUC__ && !defined(__clang__) static void stress_cpu_jmp(void) __attribute__((optimize("-O0"))); #endif /* * This could be a ternary operator, v = (v op val) ? a : b * but it may be optimised down, so force a compare and jmp * with -O0 and a if/else construct */ #define JMP(v, op, val, a, b) \ if (v op val) \ v = a; \ else \ v = b; \ /* * stress_cpu_jmp * jmp conditionals */ static void stress_cpu_jmp(void) { register int i, next = 0; for (i = 1; i < 1000; i++) { /* Force lots of compare jmps */ JMP(next, ==, 1, 2, 3); JMP(next, >, 2, 0, 1); JMP(next, <, 1, 1, 0); JMP(next, ==, 1, 2, 3); JMP(next, >, 2, 0, 1); JMP(next, <, 1, 1, 0); JMP(next, ==, 1, 2, 3); JMP(next, >, 2, 0, 1); JMP(next, <, 1, 1, 0); JMP(next, ==, 1, 2, 3); JMP(next, >, 2, 0, 1); JMP(next, <, 1, 1, 0); uint64_put(next + i); } } /* * ccitt_crc16() * perform naive CCITT CRC16 */ static uint16_t ccitt_crc16(const uint8_t *data, size_t n) { /* * The CCITT CRC16 polynomial is * 16 12 5 * x + x + x + 1 * * which is 0x11021, but to make the computation * simpler, this has been reversed to 0x8408 and * the top bit ignored.. * We can get away with a 17 bit polynomial * being represented by a 16 bit value because * we are assuming the top bit is always set. */ const uint16_t polynomial = 0x8408; uint16_t crc = ~0; if (!n) return 0; for (; n; n--) { uint8_t i; uint8_t val = (uint16_t)0xff & *data++; for (i = 8; i; --i, val >>= 1) { bool do_xor = 1 & (val ^ crc); crc >>= 1; crc ^= do_xor ? polynomial : 0; } } crc = ~crc; return (crc << 8) | (crc >> 8); } /* * stress_cpu_crc16 * compute 1024 rounds of CCITT CRC16 */ static void stress_cpu_crc16(void) { uint8_t buffer[1024]; size_t i; random_buffer(buffer, sizeof(buffer)); for (i = 0; i < sizeof(buffer); i++) uint64_put(ccitt_crc16(buffer, i)); } /* * zeta() * Riemann zeta function */ static inline long double complex zeta( const long double complex s, long double precision) { int i = 1; long double complex z = 0.0, zold = 0.0; do { zold = z; z += 1 / cpow(i++, s); } while (cabsl(z - zold) > precision); return z; } /* * stress_cpu_zeta() * stress test Zeta(2.0)..Zeta(10.0) */ static void stress_cpu_zeta(void) { long double precision = 0.00000001; double f; for (f = 2.0; f < 11.0; f += 1.0) double_put(zeta(f, precision)); } /* * stress_cpu_gamma() * stress Euler–Mascheroni constant gamma */ static void stress_cpu_gamma(void) { long double precision = 1.0e-10; long double sum = 0.0, k = 1.0, gamma = 0.0, gammaold; do { gammaold = gamma; sum += 1.0 / k; gamma = sum - logl(k); k += 1.0; } while (k < 1e6 && fabsl(gamma - gammaold) > precision); double_put(gamma); if (opt_flags & OPT_FLAGS_VERIFY) { if (fabsl(gamma - GAMMA) > 1.0e-5) pr_fail(stderr, "calculation of Euler-Mascheroni constant not as accurate as expected\n"); if (k > 80000.0) pr_fail(stderr, "calculation of Euler-Mascheroni constant took more iterations than expected\n"); } } /* * stress_cpu_correlate() * * Introduction to Signal Processing, * Prentice-Hall, 1995, ISBN: 0-13-209172-0. */ static void stress_cpu_correlate(void) { const size_t data_len = 16384; const size_t corr_len = data_len / 16; size_t i, j; double data_average = 0.0; double data[data_len], corr[corr_len + 1]; /* Generate some random data */ for (i = 0; i < data_len; i++) { data[i] = mwc(); data_average += data[i]; } data_average /= (double)data_len; /* And correlate */ for (i = 0; i <= corr_len; i++) { corr[i] = 0.0; for (j = 0; j < data_len - i; j++) { corr[i] += (data[i + j] - data_average) * (data[j] - data_average); } corr[i] /= (double)corr_len; double_put(corr[i]); } } /* * stress_cpu_sieve() * slightly optimised Sieve of Eratosthenes */ static void stress_cpu_sieve(void) { const uint32_t nsqrt = sqrt(SIEVE_SIZE); uint32_t sieve[(SIEVE_SIZE + 31) / 32]; uint32_t i, j; memset(sieve, 0xff, sizeof(sieve)); for (i = 2; i < nsqrt; i++) if (SIEVE_GETBIT(sieve, i)) for (j = i * i; j < SIEVE_SIZE; j += i) SIEVE_CLRBIT(sieve, j); /* And count up number of primes */ for (j = 0, i = 2; i < SIEVE_SIZE; i++) { if (SIEVE_GETBIT(sieve, i)) j++; } if ((opt_flags & OPT_FLAGS_VERIFY) && (j != 664579)) pr_fail(stderr, "sieve error detected, number of primes has been miscalculated\n"); } /* * is_prime() * return true if n is prime * http://en.wikipedia.org/wiki/Primality_test */ static inline bool is_prime(uint32_t n) { uint32_t i, max; if (n <= 3) return n >= 2; if ((n % 2 == 0) || (n % 3 == 0)) return false; max = sqrt(n) + 1; for (i = 5; i < max; i+= 6) if ((n % i == 0) || (n % (i + 2) == 0)) return false; return true; } /* * stress_cpu_prime() * */ static void stress_cpu_prime(void) { uint32_t i, nprimes = 0; for (i = 0; i < 1000000; i++) { if (is_prime(i)) nprimes++; } if ((opt_flags & OPT_FLAGS_VERIFY) && (nprimes != 78498)) pr_fail(stderr, "prime error detected, number of primes between 0 and 1000000 miscalculated\n"); } /* * stress_cpu_gray() * compute gray codes */ static void stress_cpu_gray(void) { uint32_t i; uint64_t sum = 0; for (i = 0; i < 0x10000; i++) { register uint32_t gray_code, mask; /* Binary to Gray code */ gray_code = (i >> 1) ^ i; sum += gray_code; /* Gray code back to binary */ for (mask = gray_code >> 1; mask; mask >>= 1) gray_code ^= mask; sum += gray_code; } if ((opt_flags & OPT_FLAGS_VERIFY) && (sum != 0xffff0000)) pr_fail(stderr, "gray code error detected, sum of gray codes " "between 0x00000 and 0x10000 miscalculated\n"); } /* * hanoi() * do a Hanoi move */ static uint32_t hanoi( const uint16_t n, const char p1, const char p2, const char p3) { if (n == 0) { /* Move p1 -> p2 */ return 1; } else { uint32_t m = hanoi(n - 1, p1, p3, p2); /* Move p1 -> p2 */ m += hanoi(n - 1, p3, p2, p1); return m; } } /* * stress_cpu_hanoi * stress with recursive Towers of Hanoi */ static void stress_cpu_hanoi(void) { uint32_t n = hanoi(20, 'X', 'Y', 'Z'); if ((opt_flags & OPT_FLAGS_VERIFY) && (n != 1048576)) pr_fail(stderr, "number of hanoi moves different from the expected number\n"); uint64_put(n); } /* * factorial() * compute n! */ static long double factorial(int n) { long double f = 1; while (n > 0) { f *= (long double)n; n--; } return f; } /* * stress_cpu_pi() * compute pi using the Srinivasa Ramanujan * fast convergence algorithm */ static void stress_cpu_pi(void) { long double s = 0.0, pi = 0.0, last_pi = 0.0; const long double precision = 1.0e-20; const long double c = 2.0 * sqrtl(2.0) / 9801.0; const int max_iter = 5; int k = 0; do { last_pi = pi; s += (factorial(4 * k) * ((26390.0 * (long double)k) + 1103)) / (powl(factorial(k), 4.0) * powl(396.0, 4.0 * k)); pi = 1 / (s * c); k++; } while ((k < max_iter) && (fabsl(pi - last_pi) > precision)); /* Quick sanity checks */ if (opt_flags & OPT_FLAGS_VERIFY) { if (k >= max_iter) pr_fail(stderr, "number of iterations to compute pi was more than expected\n"); if (fabsl(pi - M_PI) > 1.0e-15) pr_fail(stderr, "accuracy of computed pi is not as good as expected\n"); } double_put(pi); } /* * stress_cpu_omega() * compute the constant omega * See http://en.wikipedia.org/wiki/Omega_constant */ static void stress_cpu_omega(void) { long double omega = 0.5, last_omega = 0.0; const long double precision = 1.0e-20; const int max_iter = 6; int n = 0; /* Omega converges very quickly */ do { last_omega = omega; omega = (1 + omega) / (1 + expl(omega)); n++; } while ((n < max_iter) && (fabsl(omega - last_omega) > precision)); if (opt_flags & OPT_FLAGS_VERIFY) { if (n >= max_iter) pr_fail(stderr, "number of iterations to compute omega was more than expected\n"); if (fabsl(omega - OMEGA) > 1.0e-16) pr_fail(stderr, "accuracy of computed omega is not as good as expected\n"); } double_put(omega); } #define HAMMING(G, i, nybble, code) \ { \ int8_t res; \ res = (((G[3] >> i) & (nybble >> 3)) & 1) ^ \ (((G[2] >> i) & (nybble >> 2)) & 1) ^ \ (((G[1] >> i) & (nybble >> 1)) & 1) ^ \ (((G[0] >> i) & (nybble >> 0)) & 1); \ code ^= ((res & 1) << i); \ } /* * hamming84() * compute Hamming (8,4) codes */ static uint8_t hamming84(const uint8_t nybble) { /* * Hamming (8,4) Generator matrix * (4 parity bits, 4 data bits) * * p1 p2 p3 p4 d1 d2 d3 d4 * 0 1 1 1 1 0 0 0 * 1 0 1 1 0 1 0 0 * 1 1 0 1 0 0 1 0 * 1 1 1 0 0 0 0 1 * * Where: * d1..d4 = 4 data bits * p1..p4 = 4 parity bits: * p1 = d2 + d3 + d4 * p2 = d1 + d3 + d4 * p3 = d1 + d2 + d4 * p4 = d1 + d2 + d3 * * G[] is reversed to turn G[3-j] into G[j] to save a subtraction */ static const uint8_t G[] = { 0b11110001, 0b11010010, 0b10110100, 0b01111000, }; register uint8_t code = 0; /* Unrolled 8 bit loop x unrolled 4 bit loop */ HAMMING(G, 7, nybble, code); HAMMING(G, 6, nybble, code); HAMMING(G, 5, nybble, code); HAMMING(G, 4, nybble, code); HAMMING(G, 3, nybble, code); HAMMING(G, 2, nybble, code); HAMMING(G, 1, nybble, code); HAMMING(G, 0, nybble, code); return code; } /* * stress_cpu_hamming() * compute hamming code on 65536 x 4 nybbles */ static void stress_cpu_hamming(void) { uint32_t i; uint32_t sum = 0; for (i = 0; i < 65536; i++) { uint32_t encoded; /* 4 x 4 bits to 4 x 8 bits hamming encoded */ encoded = (hamming84((i >> 12) & 0xf) << 24) | (hamming84((i >> 8) & 0xf) << 16) | (hamming84((i >> 4) & 0xf) << 8) | (hamming84((i >> 0) & 0xf) << 0); sum += encoded; } if ((opt_flags & OPT_FLAGS_VERIFY) && (sum != 0xffff8000)) pr_fail(stderr, "hamming error detected, sum of 65536 hamming codes not correct\n"); } /* * stress_cpu_all() * iterate over all cpu stressors */ static void stress_cpu_all(void) { static int i = 1; /* Skip over stress_cpu_all */ cpu_methods[i++].func(); if (!cpu_methods[i].func) i = 1; } /* * Table of cpu stress methods */ static stress_cpu_stressor_info_t cpu_methods[] = { { "all", stress_cpu_all }, /* Special "all test */ { "ackermann", stress_cpu_ackermann }, { "bitops", stress_cpu_bitops }, { "crc16", stress_cpu_crc16 }, { "cdouble", stress_cpu_complex_double }, { "cfloat", stress_cpu_complex_float }, { "clongdouble", stress_cpu_complex_long_double }, { "correlate", stress_cpu_correlate }, #if defined(STRESS_FLOAT_DECIMAL) { "decimal32", stress_cpu_decimal32 }, { "decimal64", stress_cpu_decimal64 }, { "decimal128", stress_cpu_decimal128 }, #endif { "double", stress_cpu_double }, { "djb2a", stress_cpu_djb2a }, { "euler", stress_cpu_euler }, { "explog", stress_cpu_explog }, { "fibonacci", stress_cpu_fibonacci }, { "fnv1a", stress_cpu_fnv1a }, { "fft", stress_cpu_fft }, { "float", stress_cpu_float }, { "gamma", stress_cpu_gamma }, { "gcd", stress_cpu_gcd }, { "gray", stress_cpu_gray }, { "hamming", stress_cpu_hamming }, { "hanoi", stress_cpu_hanoi }, { "hyperbolic", stress_cpu_hyperbolic }, { "idct", stress_cpu_idct }, #if defined(STRESS_INT128) { "int128", stress_cpu_int128 }, #endif { "int64", stress_cpu_int64 }, { "int32", stress_cpu_int32 }, { "int16", stress_cpu_int16 }, { "int8", stress_cpu_int8 }, #if defined(STRESS_INT128) { "int128float", stress_cpu_int128_float }, { "int128double", stress_cpu_int128_double }, { "int128longdouble", stress_cpu_int128_longdouble }, #if defined(STRESS_FLOAT_DECIMAL) { "int128decimal32", stress_cpu_int128_decimal32 }, { "int128decimal64", stress_cpu_int128_decimal64 }, { "int128decimal128", stress_cpu_int128_decimal128 }, #endif #endif { "int64float", stress_cpu_int64_float }, { "int64double", stress_cpu_int64_double }, { "int64longdouble", stress_cpu_int64_longdouble }, { "int32float", stress_cpu_int32_float }, { "int32double", stress_cpu_int32_double }, { "int32longdouble", stress_cpu_int32_longdouble }, { "jenkin", stress_cpu_jenkin }, { "jmp", stress_cpu_jmp }, { "ln2", stress_cpu_ln2 }, { "longdouble", stress_cpu_longdouble }, { "loop", stress_cpu_loop }, { "matrixprod", stress_cpu_matrix_prod }, { "nsqrt", stress_cpu_nsqrt }, { "omega", stress_cpu_omega }, { "phi", stress_cpu_phi }, { "pi", stress_cpu_pi }, { "pjw", stress_cpu_pjw }, { "prime", stress_cpu_prime }, { "psi", stress_cpu_psi }, { "rand", stress_cpu_rand }, { "rgb", stress_cpu_rgb }, { "sdbm", stress_cpu_sdbm }, { "sieve", stress_cpu_sieve }, { "sqrt", stress_cpu_sqrt }, { "trig", stress_cpu_trig }, { "zeta", stress_cpu_zeta }, { NULL, NULL } }; /* * stress_set_cpu_method() * set the default cpu stress method */ int stress_set_cpu_method(const char *name) { stress_cpu_stressor_info_t *info = cpu_methods; for (info = cpu_methods; info->func; info++) { if (!strcmp(info->name, name)) { opt_cpu_stressor = info; return 0; } } fprintf(stderr, "cpu-method must be one of:"); for (info = cpu_methods; info->func; info++) { fprintf(stderr, " %s", info->name); } fprintf(stderr, "\n"); return -1; } /* * stress_cpu() * stress CPU by doing floating point math ops */ int stress_cpu( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { double bias; stress_cpu_func func = opt_cpu_stressor->func; (void)instance; (void)name; /* * Normal use case, 100% load, simple spinning on CPU */ if (opt_cpu_load == 100) { do { (void)func(); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } /* * It is unlikely, but somebody may request to do a zero * load stress test(!) */ if (opt_cpu_load == 0) { sleep((int)opt_timeout); return EXIT_SUCCESS; } /* * More complex percentage CPU utilisation. This is * not intended to be 100% accurate timing, it is good * enough for most purposes. */ bias = 0.0; do { int j; double t, delay; struct timeval tv1, tv2, tv3; gettimeofday(&tv1, NULL); for (j = 0; j < 64; j++) { (void)func(); if (!opt_do_run) break; (*counter)++; } gettimeofday(&tv2, NULL); t = timeval_to_double(&tv2) - timeval_to_double(&tv1); /* Must not calculate this with zero % load */ delay = t * (((100.0 / (double) opt_cpu_load)) - 1.0); delay -= bias; tv1.tv_sec = delay; tv1.tv_usec = (delay - tv1.tv_sec) * 1000000.0; select(0, NULL, NULL, NULL, &tv1); gettimeofday(&tv3, NULL); /* Bias takes account of the time to do the delay */ bias = (timeval_to_double(&tv3) - timeval_to_double(&tv2)) - delay; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-vecmath.c0000664000175000017500000000754412466243156015410 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" #if defined(STRESS_VECTOR) typedef int8_t vint8_t __attribute__ ((vector_size (16))); typedef int16_t vint16_t __attribute__ ((vector_size (16))); typedef int32_t vint32_t __attribute__ ((vector_size (16))); typedef int64_t vint64_t __attribute__ ((vector_size (16))); #define OPS(a, b, c, s) \ a += b; \ a |= b; \ a -= b; \ a &= ~b; \ a *= c; \ a = ~a; \ a *= s; \ a ^= c; \ /* * stress_vecmath() * stress GCC vector maths */ int stress_vecmath( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; vint8_t a8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; vint8_t b8 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78 }; vint8_t c8 = { 0x01, 0x02, 0x03, 0x02, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x01, 0x02, 0x03, 0x02, 0x01, 0x02 }; vint8_t s8 = { 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02 }; vint16_t a16 = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; vint16_t b16 = { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x0f1e, 0x2d3c, 0x4b5a, 0x6978 }; vint16_t c16 = { 0x0102, 0x0302, 0x0102, 0x0302, 0x0302, 0x0102, 0x0302, 0x0102 }; vint16_t s16 = { 0x0001, 0x0001, 0x0002, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002 }; vint32_t a32 = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; vint32_t b32 = { 0x01234567, 0x89abcdef, 0x0f1e2d3c, 0x4b5a6978 }; vint32_t c32 = { 0x01020302, 0x01020302, 0x03020102, 0x03020102 }; vint32_t s32 = { 0x00000001, 0x00000002, 0x00000002, 0000000001 }; vint64_t a64 = { 0x0000000000000000ULL, 0x0000000000000000ULL }; vint64_t b64 = { 0x0123456789abcdefULL, 0x0f1e2d3c4b5a6979ULL }; vint64_t c64 = { 0x0102030201020302ULL, 0x0302010203020102ULL }; vint64_t s64 = { 0x0000000000000001ULL, 0x0000000000000002ULL }; do { int i; for (i = 1000; i; i--) { /* Good mix of vector ops */ OPS(a8, b8, c8, s8); OPS(a16, b16, c16, s16); OPS(a32, b32, c32, s32); OPS(a64, b64, c64, s64); OPS(a32, b32, c32, s32); OPS(a16, b16, c16, s16); OPS(a8, b8, c8, s8); OPS(a64, b64, c64, s64); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Forces the compiler to actually compute the terms */ uint64_put(a8[0] + a8[1] + a8[2] + a8[3] + a8[4] + a8[5] + a8[6] + a8[7] + a8[8] + a8[9] + a8[10] + a8[11] + a8[12] + a8[13] + a8[14] + a8[15]); uint64_put(a16[0] + a16[1] + a16[2] + a16[3] + a16[4] + a16[5] + a16[6] + a16[7]); uint64_put(a32[0] + a32[1] + a32[2] + a32[3]); uint64_put(a64[0] + a64[1]); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-qsort.c0000664000175000017500000000731212466243156015122 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include "stress-ng.h" static uint64_t opt_qsort_size = DEFAULT_QSORT_SIZE; void stress_set_qsort_size(const void *optarg) { opt_qsort_size = get_uint64_byte(optarg); check_range("qsort-size", opt_qsort_size, MIN_QSORT_SIZE, MAX_QSORT_SIZE); } /* * stress_qsort_cmp_1() * qsort comparison - sort on int32 values */ static int stress_qsort_cmp_1(const void *p1, const void *p2) { int32_t *i1 = (int32_t *)p1; int32_t *i2 = (int32_t *)p2; if (*i1 > *i2) return 1; else if (*i1 < *i2) return -1; else return 0; } /* * stress_qsort_cmp_1() * qsort comparison - reverse sort on int32 values */ static int stress_qsort_cmp_2(const void *p1, const void *p2) { return stress_qsort_cmp_1(p2, p1); } /* * stress_qsort_cmp_1() * qsort comparison - sort on int8 values */ static int stress_qsort_cmp_3(const void *p1, const void *p2) { int8_t *i1 = (int8_t *)p1; int8_t *i2 = (int8_t *)p2; /* Force re-ordering on 8 bit value */ return *i1 - *i2; } /* * stress_qsort() * stress qsort */ int stress_qsort( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data, *ptr; const size_t n = (size_t)opt_qsort_size; size_t i; (void)instance; if ((data = malloc(sizeof(int32_t) * n)) == NULL) { pr_failed_dbg(name, "malloc"); return EXIT_FAILURE; } /* This is expensive, do it once */ for (ptr = data, i = 0; i < n; i++) *ptr++ = mwc(); do { /* Sort "random" data */ qsort(data, n, sizeof(uint32_t), stress_qsort_cmp_1); if (opt_flags & OPT_FLAGS_VERIFY) { for (ptr = data, i = 0; i < n - 1; i++, ptr++) { if (*ptr > *(ptr+1)) { pr_fail(stderr, "sort error detected, incorrect ordering found\n"); break; } } } if (!opt_do_run) break; /* Reverse sort */ qsort(data, n, sizeof(uint32_t), stress_qsort_cmp_2); if (opt_flags & OPT_FLAGS_VERIFY) { for (ptr = data, i = 0; i < n - 1; i++, ptr++) { if (*ptr < *(ptr+1)) { pr_fail(stderr, "reverse sort error detected, incorrect ordering found\n"); break; } } } if (!opt_do_run) break; /* And re-order by byte compare */ qsort(data, n * 4, sizeof(uint8_t), stress_qsort_cmp_3); /* Reverse sort this again */ qsort(data, n, sizeof(uint32_t), stress_qsort_cmp_2); if (opt_flags & OPT_FLAGS_VERIFY) { for (ptr = data, i = 0; i < n - 1; i++, ptr++) { if (*ptr < *(ptr+1)) { pr_fail(stderr, "reverse sort error detected, incorrect ordering found\n"); break; } } } if (!opt_do_run) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(data); return EXIT_SUCCESS; } stress-ng-0.03.15/net.c0000664000175000017500000000711412466243156013217 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef AF_INET6 #include #endif #ifdef AF_UNIX #include #endif #include "stress-ng.h" typedef struct { const char *name; const int domain; } domain_t; static const domain_t domains[] = { { "ipv4", AF_INET }, { "ipv6", AF_INET6 }, { "unix", AF_UNIX }, { NULL, -1 } }; /* * stress_set_net_port() * set up port number from opt */ void stress_set_net_port( const char *optname, const char *optarg, const int min_port, const int max_port, int *port) { *port = get_uint64(optarg); check_range(optname, *port, min_port, max_port - STRESS_PROCS_MAX); } /* * stress_set_net_domain() * set the domain option */ int stress_set_net_domain( const char *name, const char *domain_name, int *domain) { int i; for (i = 0; domains[i].name; i++) { if (!strcmp(domain_name, domains[i].name)) { *domain = domains[i].domain; return 0; } } fprintf(stderr, "%s: domain must be one of:", name); for (i = 0; domains[i].name; i++) fprintf(stderr, " %s", domains[i].name); fprintf(stderr, "\n"); *domain = 0; return -1; } /* * setup socket address */ void stress_set_sockaddr( const char *name, const uint32_t instance, const pid_t ppid, const int domain, const int port, struct sockaddr **sockaddr, socklen_t *len) { switch (domain) { #ifdef AF_INET case AF_INET: { static struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = domain; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port + instance); *sockaddr = (struct sockaddr *)&addr; *len = sizeof(addr); break; } #endif #ifdef AF_INET6 case AF_INET6: { static struct sockaddr_in6 addr; memset(&addr, 0, sizeof(addr)); addr.sin6_family = domain; addr.sin6_addr = in6addr_any; addr.sin6_port = htons(port + instance); *sockaddr = (struct sockaddr *)&addr; *len = sizeof(addr); break; } #endif #ifdef AF_UNIX case AF_UNIX: { static struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/stress-ng-%d-%" PRIu32, ppid, instance); *sockaddr = (struct sockaddr *)&addr; *len = sizeof(addr); break; } #endif default: pr_failed_dbg(name, "unknown domain"); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } } stress-ng-0.03.15/stress-vm-splice.c0000664000175000017500000000540212466243156015647 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" #if defined (__linux__) static size_t opt_vm_splice_bytes = DEFAULT_VM_SPLICE_BYTES; void stress_set_vm_splice_bytes(const char *optarg) { opt_vm_splice_bytes = (size_t)get_uint64_byte(optarg); check_range("vm-splice-bytes", opt_vm_splice_bytes, MIN_VM_SPLICE_BYTES, MAX_VM_SPLICE_BYTES); } /* * stress_splice * stress copying of /dev/zero to /dev/null */ int stress_vm_splice( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd, fds[2]; uint8_t *buf; const size_t page_size = stress_get_pagesize(); const size_t sz = opt_vm_splice_bytes & ~(page_size - 1); (void)instance; buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (buf == MAP_FAILED) { pr_failed_dbg(name, "mmap"); return(EXIT_FAILURE); } if (pipe(fds) < 0) { (void)munmap(buf, sz); pr_failed_err(name, "pipe"); return EXIT_FAILURE; } if ((fd = open("/dev/null", O_WRONLY)) < 0) { (void)munmap(buf, sz); (void)close(fds[0]); (void)close(fds[1]); pr_failed_err(name, "open"); return EXIT_FAILURE; } do { int ret; ssize_t bytes; struct iovec iov; iov.iov_base = buf; iov.iov_len = sz; bytes = vmsplice(fds[1], &iov, 1, 0); if (bytes < 0) break; ret = splice(fds[0], NULL, fd, NULL, opt_vm_splice_bytes, SPLICE_F_MOVE); if (ret < 0) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)munmap(buf, sz); (void)close(fd); (void)close(fds[0]); (void)close(fds[1]); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-brk.c0000664000175000017500000000677712466243156014546 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_brk() * stress brk and sbrk */ int stress_brk( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; uint32_t restarts = 0, nomems = 0; const size_t page_size = stress_get_pagesize(); again: pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; /* Parent, wait for child */ ret = waitpid(pid, &status, 0); if (ret < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n", name, errno, strerror(errno)); (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %d (instance %d)\n", name, WTERMSIG(status), instance); /* If we got killed by OOM killer, re-start */ if (WTERMSIG(status) == SIGKILL) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; goto again; } } } else if (pid == 0) { uint8_t *ptr, *start_ptr; bool touch = !(opt_flags & OPT_FLAGS_BRK_NOTOUCH); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); start_ptr = sbrk(0); if (start_ptr == (void *) -1) { pr_err(stderr, "%s: sbrk(0) failed: errno=%d (%s)\n", name, errno, strerror(errno)); exit(EXIT_FAILURE); } do { ptr = sbrk((intptr_t)page_size); if (ptr == (void *)-1) { if (errno == ENOMEM) { nomems++; if (brk(start_ptr) < 0) { pr_err(stderr, "%s: brk(%p) failed: errno=%d (%s)\n", name, start_ptr, errno, strerror(errno)); exit(EXIT_FAILURE); } } else { pr_err(stderr, "%s: sbrk(%d) failed: errno=%d (%s)\n", name, (int)page_size, errno, strerror(errno)); exit(EXIT_FAILURE); } } else { /* Touch page, force it to be resident */ if (touch) *(ptr - 1) = 0; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(ptr); } if (restarts + nomems > 0) pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 ", out of memory restarts: %" PRIu32 ".\n", name, restarts, nomems); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-urandom.c0000664000175000017500000000353112466243156015416 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" #if defined (__linux__) || defined(__gnu_hurd__) /* * stress_urandom * stress reading of /dev/urandom */ int stress_urandom( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd; (void)instance; if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { pr_failed_err(name, "open"); return EXIT_FAILURE; } do { char buffer[8192]; if (read(fd, buffer, sizeof(buffer)) < 0) { pr_failed_err(name, "read"); (void)close(fd); return EXIT_FAILURE; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-mmap.c0000664000175000017500000001732712466243156014713 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static size_t opt_mmap_bytes = DEFAULT_MMAP_BYTES; void stress_set_mmap_bytes(const char *optarg) { opt_mmap_bytes = (size_t)get_uint64_byte(optarg); check_range("mmap-bytes", opt_mmap_bytes, MIN_MMAP_BYTES, MAX_MMAP_BYTES); } /* * stress_mmap_check() * check if mmap'd data is sane */ static int stress_mmap_check(uint8_t *buf, const size_t sz) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += 4096) { if (!opt_do_run) break; for (j = 0; j < 4096; j++) if (*ptr++ != val++) return -1; val++; } return 0; } static void stress_mmap_set(uint8_t *buf, const size_t sz) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += 4096) { if (!opt_do_run) break; for (j = 0; j < 4096; j++) *ptr++ = val++; val++; } } /* * stress_mmap_mprotect() * cycle through page settings on a region of mmap'd memory */ static void stress_mmap_mprotect(void *addr, size_t len) { if (opt_flags & OPT_FLAGS_MMAP_MPROTECT) { /* Cycle through potection */ if (mprotect(addr, len, PROT_NONE) < 0) pr_fail(stderr, "mprotect set to PROT_NONE failed\n"); if (mprotect(addr, len, PROT_READ) < 0) pr_fail(stderr, "mprotect set to PROT_READ failed\n"); if (mprotect(addr, len, PROT_WRITE) < 0) pr_fail(stderr, "mprotect set to PROT_WRITE failed\n"); if (mprotect(addr, len, PROT_EXEC) < 0) pr_fail(stderr, "mprotect set to PROT_EXEC failed\n"); if (mprotect(addr, len, PROT_READ | PROT_WRITE) < 0) pr_fail(stderr, "mprotect set to PROT_READ | PROT_WRITE failed\n"); } } /* * stress_mmap() * stress mmap */ int stress_mmap( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *buf = NULL; const size_t page_size = stress_get_pagesize(); const size_t sz = opt_mmap_bytes & ~(page_size - 1); const size_t pages4k = sz / page_size; #if !defined(__gnu_hurd__) const int ms_flags = (opt_flags & OPT_FLAGS_MMAP_ASYNC) ? MS_ASYNC : MS_SYNC; #endif const pid_t pid = getpid(); int fd = -1, flags = MAP_PRIVATE | MAP_ANONYMOUS; char filename[PATH_MAX]; #ifdef MAP_POPULATE flags |= MAP_POPULATE; #endif (void)instance; /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); if (opt_flags & OPT_FLAGS_MMAP_FILE) { char ch = '\0'; if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); (void)unlink(filename); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)unlink(filename); if (lseek(fd, sz - sizeof(ch), SEEK_SET) < 0) { pr_failed_err(name, "lseek"); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } if (write(fd, &ch, sizeof(ch)) != sizeof(ch)) { pr_failed_err(name, "write"); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } flags &= ~(MAP_ANONYMOUS | MAP_PRIVATE); flags |= MAP_SHARED; } do { uint8_t mapped[pages4k]; uint8_t *mappings[pages4k]; size_t n; if (!opt_do_run) break; buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, flags, fd, 0); if (buf == MAP_FAILED) { /* Force MAP_POPULATE off, just in case */ #ifdef MAP_POPULATE flags &= ~MAP_POPULATE; #endif continue; /* Try again */ } if (opt_flags & OPT_FLAGS_MMAP_FILE) { memset(buf, 0xff, sz); #if !defined(__gnu_hurd__) (void)msync(buf, sz, ms_flags); #endif } (void)madvise_random(buf, sz); (void)mincore_touch_pages(buf, opt_mmap_bytes); stress_mmap_mprotect(buf, sz); memset(mapped, PAGE_MAPPED, sizeof(mapped)); for (n = 0; n < pages4k; n++) mappings[n] = buf + (n * page_size); /* Ensure we can write to the mapped pages */ stress_mmap_set(buf, sz); if (opt_flags & OPT_FLAGS_VERIFY) { if (stress_mmap_check(buf, sz) < 0) pr_fail(stderr, "mmap'd region of %zu bytes does " "not contain expected data\n", sz); } /* * Step #1, unmap all pages in random order */ (void)mincore_touch_pages(buf, opt_mmap_bytes); for (n = pages4k; n; ) { uint64_t j, i = mwc() % pages4k; for (j = 0; j < n; j++) { uint64_t page = (i + j) % pages4k; if (mapped[page] == PAGE_MAPPED) { mapped[page] = 0; (void)madvise_random(mappings[page], page_size); stress_mmap_mprotect(mappings[page], page_size); munmap(mappings[page], page_size); n--; break; } if (!opt_do_run) goto cleanup; } } #ifdef MAP_FIXED /* * Step #2, map them back in random order */ for (n = pages4k; n; ) { uint64_t j, i = mwc() % pages4k; for (j = 0; j < n; j++) { uint64_t page = (i + j) % pages4k; if (!mapped[page]) { off_t offset = (opt_flags & OPT_FLAGS_MMAP_FILE) ? page * page_size : 0; /* * Attempt to map them back into the original address, this * may fail (it's not the most portable operation), so keep * track of failed mappings too */ mappings[page] = mmap(mappings[page], page_size, PROT_READ | PROT_WRITE, MAP_FIXED | flags, fd, offset); if (mappings[page] == MAP_FAILED) { mapped[page] = PAGE_MAPPED_FAIL; mappings[page] = NULL; } else { (void)mincore_touch_pages(buf, page_size); (void)madvise_random(mappings[page], page_size); stress_mmap_mprotect(mappings[page], page_size); mapped[page] = PAGE_MAPPED; /* Ensure we can write to the mapped page */ stress_mmap_set(mappings[page], page_size); if (stress_mmap_check(mappings[page], page_size) < 0) pr_fail(stderr, "mmap'd region of %zu bytes does " "not contain expected data\n", page_size); if (opt_flags & OPT_FLAGS_MMAP_FILE) { memset(mappings[page], n, page_size); #if !defined(__gnu_hurd__) (void)msync(mappings[page], page_size, ms_flags); #endif } } n--; break; } if (!opt_do_run) goto cleanup; } } #endif cleanup: /* * Step #3, unmap them all */ for (n = 0; n < pages4k; n++) { if (mapped[n] & PAGE_MAPPED) { (void)madvise_random(mappings[n], page_size); stress_mmap_mprotect(mappings[n], page_size); munmap(mappings[n], page_size); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); if (opt_flags & OPT_FLAGS_MMAP_FILE) { (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); } return EXIT_SUCCESS; } stress-ng-0.03.15/stress-fault.c0000664000175000017500000000647212466243156015073 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_fault() * stress min and max page faulting */ int stress_fault( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct rusage usage; char filename[PATH_MAX]; int i = 0; const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); (void)umask(0077); do { char *ptr; int fd; fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { pr_err(stderr, "%s: open failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L if (posix_fallocate(fd, 0, 1) < 0) { (void)close(fd); pr_err(stderr, "%s: posix_fallocate failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } #else { char buffer[1]; if (write(fd, buffer, sizeof(buffer)) < 0) { (void)close(fd); pr_err(stderr, "%s: write failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } } #endif /* * Removing file here causes major fault when we touch * ptr later */ if (i & 1) (void)unlink(filename); ptr = mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); (void)close(fd); if (ptr == MAP_FAILED) { pr_err(stderr, "%s: mmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } *ptr = 0; /* Cause the page fault */ if (munmap(ptr, 1) < 0) { pr_err(stderr, "%s: munmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } /* Remove file on-non major fault case */ if (!(i & 1)) (void)unlink(filename); i++; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Clean up, most times this is redundant */ (void)unlink(filename); (void)stress_temp_dir_rm(name, pid, instance); if (!getrusage(RUSAGE_SELF, &usage)) { pr_dbg(stderr, "page faults: minor: %lu, major: %lu\n", usage.ru_minflt, usage.ru_majflt); } return EXIT_SUCCESS; } stress-ng-0.03.15/log.c0000664000175000017500000000453112466243156013212 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" uint16_t abort_fails; /* count of failures */ bool abort_msg_emitted; /* * print() * print some debug or info messages */ int print( FILE *fp, const int flag, const char *const fmt, ...) { va_list ap; int ret = 0; va_start(ap, fmt); if (opt_flags & flag) { char buf[4096]; const char *type = ""; int n; if (flag & PR_ERROR) type = "error"; if (flag & PR_DEBUG) type = "debug"; if (flag & PR_INFO) type = "info"; if (flag & PR_FAIL) { type = "fail"; } n = snprintf(buf, sizeof(buf), "%s: %s: [%i] ", app_name, type, getpid()); ret = vsnprintf(buf + n, sizeof(buf) - n, fmt, ap); fprintf(fp, "%s", buf); fflush(fp); if (flag & PR_FAIL) { abort_fails++; if (abort_fails >= ABORT_FAILURES) { if (!abort_msg_emitted) { abort_msg_emitted = true; opt_do_run = false; print(fp, PR_INFO, "%d failures reached, aborting stress process\n", ABORT_FAILURES); fflush(fp); } } } } va_end(ap); return ret; } /* * pr_failed() * print failure message with errno */ void pr_failed(const int flag, const char *name, const char *what) { print(stderr, flag, "%s: %s failed, errno=%d (%s)\n", name, what, errno, strerror(errno)); } stress-ng-0.03.15/stress-kill.c0000664000175000017500000000374212466243156014710 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" /* * stress on sched_kill() * stress system by rapid kills */ int stress_kill( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct sigaction new_action; const pid_t pid = getpid(); (void)instance; (void)name; memset(&new_action, 0, sizeof new_action); new_action.sa_handler = SIG_IGN; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGUSR1, &new_action, NULL) < 0) { pr_failed_err(name, "sigusr1"); return EXIT_FAILURE; } do { int ret; ret = kill(pid, SIGUSR1); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "kill failed: errno=%d (%s)\n", errno, strerror(errno)); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-tsearch.c0000664000175000017500000000625312466243156015406 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" static uint64_t opt_tsearch_size = DEFAULT_TSEARCH_SIZE; /* * stress_set_tsearch_size() * set tsearch size from given option string */ void stress_set_tsearch_size(const char *optarg) { opt_tsearch_size = get_uint64_byte(optarg); check_range("tsearch-size", opt_tsearch_size, MIN_TSEARCH_SIZE, MAX_TSEARCH_SIZE); } /* * cmp() * sort on int32 values */ static int cmp(const void *p1, const void *p2) { int32_t *i1 = (int32_t *)p1; int32_t *i2 = (int32_t *)p2; if (*i1 > *i2) return 1; else if (*i1 < *i2) return -1; else return 0; } /* * stress_tsearch() * stress tsearch */ int stress_tsearch( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data; const size_t n = (size_t)opt_tsearch_size; size_t i; (void)instance; if ((data = malloc(sizeof(int32_t) * n)) == NULL) { pr_failed_dbg(name, "malloc"); return EXIT_FAILURE; } do { void *root = NULL; /* Step #1, populate tree */ for (i = 0; i < n; i++) { data[i] = ((mwc() & 0xfff) << 20) ^ i; if (tsearch(&data[i], &root, cmp) == NULL) { size_t j; pr_err(stderr, "cannot allocate new tree node\n"); for (j = 0; j < i; j++) tdelete(&data[j], &root, cmp); goto abort; } } /* Step #2, find */ for (i = 0; opt_do_run && i < n; i++) { void **result; result = tfind(&data[i], &root, cmp); if (opt_flags & OPT_FLAGS_VERIFY) { if (result == NULL) pr_fail(stderr, "element %zu could not be found\n", i); else { int32_t *val; val = *result; if (*val != data[i]) pr_fail(stderr, "element %zu found %" PRIu32 ", expecting %" PRIu32 "\n", i, *val, data[i]); } } } /* Step #3, delete */ for (i = 0; i < n; i++) { void **result; result = tdelete(&data[i], &root, cmp); if ((opt_flags & OPT_FLAGS_VERIFY) && (result == NULL)) pr_fail(stderr, "element %zu could not be found\n", i); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: free(data); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-splice.c0000664000175000017500000000504412466243156015231 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" #if defined (__linux__) static size_t opt_splice_bytes = DEFAULT_SPLICE_BYTES; void stress_set_splice_bytes(const char *optarg) { opt_splice_bytes = (size_t)get_uint64_byte(optarg); check_range("splice-bytes", opt_splice_bytes, MIN_SPLICE_BYTES, MAX_SPLICE_BYTES); } /* * stress_splice * stress copying of /dev/zero to /dev/null */ int stress_splice( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd_in, fd_out, fds[2]; (void)instance; if (pipe(fds) < 0) { pr_failed_err(name, "pipe"); return EXIT_FAILURE; } if ((fd_in = open("/dev/zero", O_RDONLY)) < 0) { (void)close(fds[0]); (void)close(fds[1]); pr_failed_err(name, "open"); return EXIT_FAILURE; } if ((fd_out = open("/dev/null", O_WRONLY)) < 0) { (void)close(fd_in); (void)close(fds[0]); (void)close(fds[1]); pr_failed_err(name, "open"); return EXIT_FAILURE; } do { int ret; ssize_t bytes; bytes = splice(fd_in, NULL, fds[1], NULL, opt_splice_bytes, SPLICE_F_MOVE); if (bytes < 0) break; ret = splice(fds[0], NULL, fd_out, NULL, opt_splice_bytes, SPLICE_F_MOVE); if (ret < 0) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd_out); (void)close(fd_in); (void)close(fds[0]); (void)close(fds[1]); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-switch.c0000664000175000017500000000463012466243156015253 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_switch * stress by heavy context switching */ int stress_switch( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int pipefds[2]; (void)instance; if (pipe(pipefds) < 0) { pr_failed_dbg(name, "pipe"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { (void)close(pipefds[0]); (void)close(pipefds[1]); pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { (void)close(pipefds[1]); for (;;) { char ch; for (;;) { if (read(pipefds[0], &ch, sizeof(ch)) <= 0) { pr_failed_dbg(name, "read"); break; } if (ch == SWITCH_STOP) break; } (void)close(pipefds[0]); exit(EXIT_SUCCESS); } } else { char ch = '_'; int status; /* Parent */ (void)close(pipefds[0]); do { if (write(pipefds[1], &ch, sizeof(ch)) < 0) { pr_failed_dbg(name, "write"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); ch = SWITCH_STOP; if (write(pipefds[1], &ch, sizeof(ch)) <= 0) pr_failed_dbg(name, "termination write"); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } return EXIT_SUCCESS; } stress-ng-0.03.15/mincore.c0000664000175000017500000000402312466243156014061 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" /* * madvise_random() * apply random madvise setting to a memory region */ int mincore_touch_pages(void *buf, size_t buf_len) { #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) unsigned char *vec; char *buffer; size_t vec_len, i; const size_t page_size = stress_get_pagesize(); if (!(opt_flags & OPT_FLAGS_MMAP_MINCORE)) return 0; vec_len = buf_len / page_size; if (vec_len < 1) return -1; vec = calloc(vec_len, 1); if (!vec) return -1; if (mincore(buf, buf_len, vec) < 0) { free(vec); return -1; } /* If page is not resident in memory, touch it */ for (buffer = buf, i = 0; i < vec_len; i++, buffer += page_size) if (!(vec[i] & 1)) (*buffer)++; /* And return it back */ for (buffer = buf, i = 0; i < vec_len; i++, buffer += page_size) if (!(vec[i] & 1)) (*buffer)--; free(vec); #else (void)buf; (void)buf_len; #endif return 0; } stress-ng-0.03.15/stress-ng.h0000664000175000017500000007117012466243156014366 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #ifndef __STRESS_NG_H__ #define __STRESS_NG_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE /* GNU HURD */ #ifndef PATH_MAX #define PATH_MAX (4096) /* Some systems don't define this */ #endif #define STRESS_FD_MAX (65536) /* Max fds if we can't figure it out */ #define STRESS_PROCS_MAX (1024) /* Max number of processes per stressor */ #ifndef PIPE_BUF #define PIPE_BUF (512) /* PIPE I/O buffer size */ #endif #define SOCKET_BUF (8192) /* Socket I/O buffer size */ #define UDP_BUF (1024) /* UDP I/O buffer size */ /* Option bit masks */ #define OPT_FLAGS_AFFINITY_RAND 0x00000001 /* Change affinity randomly */ #define OPT_FLAGS_DRY_RUN 0x00000002 /* Don't actually run */ #define OPT_FLAGS_METRICS 0x00000004 /* Dump metrics at end */ #define OPT_FLAGS_VM_KEEP 0x00000008 /* Don't keep re-allocating */ #define OPT_FLAGS_RANDOM 0x00000010 /* Randomize */ #define OPT_FLAGS_SET 0x00000020 /* Set if user specifies stress procs */ #define OPT_FLAGS_KEEP_NAME 0x00000040 /* Keep stress names to stress-ng */ #define OPT_FLAGS_UTIME_FSYNC 0x00000080 /* fsync after utime modification */ #define OPT_FLAGS_METRICS_BRIEF 0x00000100 /* dump brief metrics */ #define OPT_FLAGS_VERIFY 0x00000200 /* verify mode */ #define OPT_FLAGS_MMAP_MADVISE 0x00000400 /* enable random madvise settings */ #define OPT_FLAGS_MMAP_MINCORE 0x00000800 /* mincore force pages into mem */ #define OPT_FLAGS_TIMES 0x00001000 /* user/system time summary */ #define OPT_FLAGS_CACHE_FLUSH 0x00004000 /* cache flush */ #define OPT_FLAGS_CACHE_FENCE 0x00008000 /* cache fence */ #define OPT_FLAGS_CACHE_MASK (OPT_FLAGS_CACHE_FLUSH | OPT_FLAGS_CACHE_FENCE) #define OPT_FLAGS_MMAP_FILE 0x00010000 /* mmap onto a file */ #define OPT_FLAGS_MMAP_ASYNC 0x00020000 /* mmap onto a file */ #define OPT_FLAGS_MMAP_MPROTECT 0x00040000 /* mmap mprotect enabled */ #define OPT_FLAGS_LOCKF_NONBLK 0x00080000 /* Non-blocking lockf */ #define OPT_FLAGS_MINCORE_RAND 0x00100000 /* mincore randomize */ #define OPT_FLAGS_BRK_NOTOUCH 0x00200000 /* brk, don't touch page */ #define OPT_FLAGS_HDD_SYNC 0x00400000 /* HDD O_SYNC */ #define OPT_FLAGS_HDD_DSYNC 0x00800000 /* HDD O_DYNC */ #define OPT_FLAGS_HDD_DIRECT 0x01000000 /* HDD O_DIRECT */ #define OPT_FLAGS_HDD_NOATIME 0x02000000 /* HDD O_NOATIME */ /* Stressor classes */ #define CLASS_CPU 0x00000001 /* CPU only */ #define CLASS_MEMORY 0x00000002 /* Memory thrashers */ #define CLASS_CPU_CACHE 0x00000004 /* CPU cache */ #define CLASS_IO 0x00000008 /* I/O read/writes etc */ #define CLASS_NETWORK 0x00000010 /* Network, sockets, etc */ #define CLASS_SCHEDULER 0x00000020 /* Scheduling */ #define CLASS_VM 0x00000040 /* VM stress, big memory, swapping */ #define CLASS_INTERRUPT 0x00000080 /* interrupt floods */ #define CLASS_OS 0x00000100 /* generic OS tests */ /* debug output bitmasks */ #define PR_ERROR 0x10000000 /* Print errors */ #define PR_INFO 0x20000000 /* Print info */ #define PR_DEBUG 0x40000000 /* Print debug */ #define PR_FAIL 0x80000000 /* Print test failure message */ #define PR_ALL (PR_ERROR | PR_INFO | PR_DEBUG | PR_FAIL) /* Large prime to stride around large VM regions */ #define PRIME_64 (0x8f0000000017116dULL) /* Logging helpers */ extern int print(FILE *fp, const int flag, const char *const fmt, ...) __attribute__((format(printf, 3, 4))); extern void pr_failed(const int flag, const char *name, const char *what); #define pr_dbg(fp, fmt, args...) print(fp, PR_DEBUG, fmt, ## args) #define pr_inf(fp, fmt, args...) print(fp, PR_INFO, fmt, ## args) #define pr_err(fp, fmt, args...) print(fp, PR_ERROR, fmt, ## args) #define pr_fail(fp, fmt, args...) print(fp, PR_FAIL, fmt, ## args) #define pr_tidy(fp, fmt, args...) print(fp, opt_sigint ? PR_INFO : PR_DEBUG, fmt, ## args) #define pr_failed_err(name, what) pr_failed(PR_ERROR, name, what) #define pr_failed_dbg(name, what) pr_failed(PR_DEBUG, name, what) #define ABORT_FAILURES (5) /* Memory size constants */ #define KB (1024ULL) #define MB (KB * KB) #define GB (KB * KB * KB) #define PAGE_4K_SHIFT (12) #define PAGE_4K (1 << PAGE_4K_SHIFT) #define MIN_OPS (1ULL) #define MAX_OPS (100000000ULL) /* Stressor defaults */ #define MIN_AIO_REQUESTS (1) #define MAX_AIO_REQUESTS (4096) #define DEFAULT_AIO_REQUESTS (16) #define MIN_BIGHEAP_GROWTH (4 * KB) #define MAX_BIGHEAP_GROWTH (64 * MB) #define DEFAULT_BIGHEAP_GROWTH (64 * KB) #define MIN_BSEARCH_SIZE (1 * KB) #define MAX_BSEARCH_SIZE (4 * MB) #define DEFAULT_BSEARCH_SIZE (64 * KB) #define MIN_DENTRIES (1) #define MAX_DENTRIES (100000000) #define DEFAULT_DENTRIES (2048) #define MIN_EPOLL_PORT (1024) #define MAX_EPOLL_PORT (65535) #define DEFAULT_EPOLL_PORT (6000) #define MIN_HDD_BYTES (1 * MB) #define MAX_HDD_BYTES (256 * GB) #define DEFAULT_HDD_BYTES (1 * GB) #define MIN_HDD_WRITE_SIZE (1) #define MAX_HDD_WRITE_SIZE (4 * MB) #define DEFAULT_HDD_WRITE_SIZE (64 * 1024) #define MIN_FIFO_READERS (1) #define MAX_FIFO_READERS (64) #define DEFAULT_FIFO_READERS (4) #define MIN_MQ_SIZE (1) #define MAX_MQ_SIZE (32) #define DEFAULT_MQ_SIZE (10) #define MIN_SEMAPHORE_PROCS (4) #define MAX_SEMAPHORE_PROCS (64) #define DEFAULT_SEMAPHORE_PROCS (1) #define MIN_FORKS (1) #define MAX_FORKS (16000) #define DEFAULT_FORKS (1) #define MIN_VFORKS (1) #define MAX_VFORKS (16000) #define DEFAULT_VFORKS (1) #define MIN_HSEARCH_SIZE (1 * KB) #define MAX_HSEARCH_SIZE (4 * MB) #define DEFAULT_HSEARCH_SIZE (8 * KB) #define MIN_LEASE_BREAKERS (1) #define MAX_LEASE_BREAKERS (16) #define DEFAULT_LEASE_BREAKERS (1) #define MIN_LSEARCH_SIZE (1 * KB) #define MAX_LSEARCH_SIZE (4 * MB) #define DEFAULT_LSEARCH_SIZE (8 * KB) #define MIN_MALLOC_BYTES (1 * KB) #define MAX_MALLOC_BYTES (1 * GB) #define DEFAULT_MALLOC_BYTES (64 * KB) #define MIN_MALLOC_MAX (32) #define MAX_MALLOC_MAX (256 * 1024) #define DEFAULT_MALLOC_MAX (64 * KB) #define MIN_MMAP_BYTES (4 * KB) #define MAX_MMAP_BYTES (1 * GB) #define DEFAULT_MMAP_BYTES (256 * MB) #define MIN_MREMAP_BYTES (4 * KB) #define MAX_MREMAP_BYTES (1 * GB) #define DEFAULT_MREMAP_BYTES (256 * MB) #define MIN_PTHREAD (1) #define MAX_PTHREAD (30000) #define DEFAULT_PTHREAD (16) #define MIN_QSORT_SIZE (1 * KB) #define MAX_QSORT_SIZE (64 * MB) #define DEFAULT_QSORT_SIZE (256 * KB) #define MIN_SENDFILE_SIZE (1 * KB) #define MAX_SENDFILE_SIZE (1 * GB) #define DEFAULT_SENDFILE_SIZE (4 * MB) #define MIN_SEEK_SIZE (1 * MB) #define MAX_SEEK_SIZE (256 * GB) #define DEFAULT_SEEK_SIZE (16 * MB) #define MIN_SEQUENTIAL (0) #define MAX_SEQUENTIAL (1000000) #define DEFAULT_SEQUENTIAL (0) /* Disabled */ #define MIN_SHM_SYSV_BYTES (1 * MB) #define MAX_SHM_SYSV_BYTES (1 * GB) #define DEFAULT_SHM_SYSV_BYTES (8 * MB) #define MIN_SHM_SYSV_SEGMENTS (1) #define MAX_SHM_SYSV_SEGMENTS (128) #define DEFAULT_SHM_SYSV_SEGMENTS (8) #define MIN_SOCKET_PORT (1024) #define MAX_SOCKET_PORT (65535) #define DEFAULT_SOCKET_PORT (5000) #define MIN_SPLICE_BYTES (1*KB) #define MAX_SPLICE_BYTES (64*MB) #define DEFAULT_SPLICE_BYTES (64*KB) #define MIN_TSEARCH_SIZE (1 * KB) #define MAX_TSEARCH_SIZE (4 * MB) #define DEFAULT_TSEARCH_SIZE (64 * KB) #define MIN_TIMER_FREQ (1) #define MAX_TIMER_FREQ (100000000) #define DEFAULT_TIMER_FREQ (1000000) #define MIN_UDP_PORT (1024) #define MAX_UDP_PORT (65535) #define DEFAULT_UDP_PORT (7000) #define MIN_VM_BYTES (4 * KB) #define MAX_VM_BYTES (1 * GB) #define DEFAULT_VM_BYTES (256 * MB) #define MIN_VM_HANG (0) #define MAX_VM_HANG (3600) #define DEFAULT_VM_HANG (~0ULL) #define MIN_VM_RW_BYTES (4 * KB) #define MAX_VM_RW_BYTES (1 * GB) #define DEFAULT_VM_RW_BYTES (16 * MB) #define MIN_VM_SPLICE_BYTES (4*KB) #define MAX_VM_SPLICE_BYTES (64*MB) #define DEFAULT_VM_SPLICE_BYTES (64*KB) #define DEFAULT_TIMEOUT (60 * 60 * 24) #define DEFAULT_BACKOFF (0) #define DEFAULT_LINKS (8192) #define DEFAULT_DIRS (8192) #define SWITCH_STOP 'X' #define PIPE_STOP "PIPE_STOP" #define MEM_CACHE_SIZE (65536 * 32) #define UNDEFINED (-1) #define PAGE_MAPPED (0x01) #define PAGE_MAPPED_FAIL (0x02) #define FFT_SIZE (4096) #define SIEVE_GETBIT(a, i) (a[i / 32] & (1 << (i & 31))) #define SIEVE_CLRBIT(a, i) (a[i / 32] &= ~(1 << (i & 31))) #define SIEVE_SIZE (10000000) /* MWC random number initial seed */ #define MWC_SEED_Z (362436069ULL) #define MWC_SEED_W (521288629ULL) #define MWC_SEED() mwc_seed(MWC_SEED_W, MWC_SEED_Z) #define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0])) #if defined(__x86_64__) || defined(__x86_64) || defined(__i386__) || defined(__i386) #define STRESS_X86 1 #endif #if defined(__GNUC__) && defined (__GNUC_MINOR__) && \ (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 6) #define STRESS_VECTOR 1 #endif /* NetBSD does not define MAP_ANONYMOUS */ #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif #if defined(__GNUC__) && !defined(__clang__) && defined(__SIZEOF_INT128__) #define STRESS_INT128 1 #endif /* stress process prototype */ typedef int (*stress_func)(uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name); /* Help information for options */ typedef struct { const char *opt_s; /* short option */ const char *opt_l; /* long option */ const char *description; /* description */ } help_t; /* Fast random number generator state */ typedef struct { uint64_t w; uint64_t z; } mwc_t; /* Force aligment to nearest cache line */ #ifdef __GNUC__ #define ALIGN64 __attribute__ ((aligned(64))) #else #define ALIGN64 #endif /* Per process statistics and accounting info */ typedef struct { uint64_t counter; /* number of bogo ops */ struct tms tms; /* run time stats of process */ double start; /* wall clock start time */ double finish; /* wall clock stop time */ } proc_stats_t; /* Shared memory segment */ typedef struct { uint8_t mem_cache[MEM_CACHE_SIZE] ALIGN64; /* Shared memory cache */ uint32_t futex[STRESS_PROCS_MAX] ALIGN64; /* Shared futexes */ uint64_t futex_timeout[STRESS_PROCS_MAX] ALIGN64; sem_t sem_posix ALIGN64; /* Shared semaphores */ bool sem_posix_init ALIGN64; key_t sem_sysv_key_id ALIGN64; /* System V semaphore key id */ int sem_sysv_id ALIGN64; /* System V semaphore id */ bool sem_sysv_init ALIGN64; /* System V semaphore initialized */ proc_stats_t stats[0] ALIGN64; /* Shared statistics */ } shared_t; /* Stress test classes */ typedef struct { uint32_t class; /* Class type bit mask */ const char *name; /* Name of class */ } class_t; /* Stress tests */ typedef enum { #if defined(__linux__) STRESS_AFFINITY = 0, #endif #if defined(__linux__) STRESS_AIO, #endif STRESS_BRK, STRESS_BSEARCH, STRESS_BIGHEAP, STRESS_CACHE, STRESS_CHMOD, #if _POSIX_C_SOURCE >= 199309L STRESS_CLOCK, #endif STRESS_CPU, STRESS_DENTRY, STRESS_DIR, STRESS_DUP, #if defined(__linux__) STRESS_EPOLL, #endif #if defined(__linux__) STRESS_EVENTFD, #endif #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L STRESS_FALLOCATE, #endif STRESS_FAULT, STRESS_FIFO, STRESS_FLOCK, STRESS_FORK, STRESS_FSTAT, #if defined(__linux__) STRESS_FUTEX, #endif STRESS_GET, STRESS_HDD, STRESS_HSEARCH, #if defined(__linux__) STRESS_INOTIFY, #endif STRESS_IOSYNC, STRESS_KILL, #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) STRESS_LEASE, #endif STRESS_LINK, #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) STRESS_LOCKF, #endif STRESS_LSEARCH, STRESS_MALLOC, STRESS_MEMCPY, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) STRESS_MINCORE, #endif STRESS_MMAP, #if defined(__linux__) STRESS_MREMAP, #endif #if !defined(__gnu_hurd__) STRESS_MSG, #endif #if defined(__linux__) STRESS_MQ, #endif STRESS_NICE, STRESS_NULL, STRESS_OPEN, STRESS_PIPE, STRESS_POLL, #if defined(__linux__) STRESS_PROCFS, #endif STRESS_PTHREAD, STRESS_QSORT, #if defined(STRESS_X86) STRESS_RDRAND, #endif STRESS_RENAME, STRESS_SEEK, STRESS_SEMAPHORE_POSIX, #if !defined(__gnu_hurd__) STRESS_SEMAPHORE_SYSV, #endif #if defined(__linux__) STRESS_SENDFILE, #endif STRESS_SHM_SYSV, #if defined(__linux__) STRESS_SIGFD, #endif STRESS_SIGFPE, #if _POSIX_C_SOURCE >= 199309L && !defined(__gnu_hurd__) STRESS_SIGQUEUE, #endif STRESS_SIGSEGV, STRESS_SOCKET, #if defined(__linux__) STRESS_SPLICE, #endif STRESS_STACK, STRESS_SWITCH, STRESS_SYMLINK, STRESS_SYSINFO, #if defined(__linux__) STRESS_TIMER, #endif STRESS_TSEARCH, STRESS_UDP, #if defined(__linux__) || defined(__gnu_hurd__) STRESS_URANDOM, #endif STRESS_UTIME, #if defined(STRESS_VECTOR) STRESS_VECMATH, #endif #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) STRESS_VFORK, #endif STRESS_VM, #if defined(__linux__) STRESS_VM_RW, #endif #if defined(__linux__) STRESS_VM_SPLICE, #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) STRESS_WAIT, #endif #if defined (_POSIX_PRIORITY_SCHEDULING) STRESS_YIELD, #endif STRESS_ZERO, /* STRESS_MAX must be last one */ STRESS_MAX } stress_id; /* Command line long options */ typedef enum { /* Short options */ OPT_QUERY = '?', OPT_ALL = 'a', OPT_BACKOFF = 'b', OPT_BIGHEAP = 'B', OPT_CPU = 'c', OPT_CACHE = 'C', OPT_HDD = 'd', OPT_DENTRY = 'D', OPT_FORK = 'f', #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L OPT_FALLOCATE = 'F', #endif OPT_IOSYNC = 'i', OPT_HELP = 'h', OPT_KEEP_NAME = 'k', OPT_CPU_LOAD = 'l', OPT_VM = 'm', OPT_METRICS = 'M', OPT_DRY_RUN = 'n', OPT_RENAME = 'R', OPT_OPEN = 'o', OPT_PIPE = 'p', OPT_POLL = 'P', OPT_QUIET = 'q', OPT_RANDOM = 'r', OPT_SWITCH = 's', OPT_SOCKET = 'S', OPT_TIMEOUT = 't', #if defined (__linux__) OPT_TIMER = 'T', #endif #if defined (__linux__) || defined(__gnu_hurd__) OPT_URANDOM = 'u', #endif OPT_VERBOSE = 'v', OPT_VERSION = 'V', OPT_YIELD = 'y', /* Long options only */ #if defined(__linux__) OPT_AFFINITY = 0x80, OPT_AFFINITY_OPS, OPT_AFFINITY_RAND, #endif #if defined (__linux__) OPT_AIO, OPT_AIO_OPS, OPT_AIO_REQUESTS, #endif OPT_BRK, OPT_BRK_OPS, OPT_BRK_NOTOUCH, OPT_BSEARCH, OPT_BSEARCH_OPS, OPT_BSEARCH_SIZE, OPT_BIGHEAP_OPS, OPT_BIGHEAP_GROWTH, OPT_CLASS, OPT_CACHE_OPS, OPT_CACHE_FLUSH, OPT_CACHE_FENCE, OPT_CHMOD, OPT_CHMOD_OPS, #if _POSIX_C_SOURCE >= 199309L OPT_CLOCK, OPT_CLOCK_OPS, #endif OPT_CPU_OPS, OPT_CPU_METHOD, OPT_DENTRY_OPS, OPT_DENTRIES, OPT_DENTRY_ORDER, OPT_DIR, OPT_DIR_OPS, OPT_DUP, OPT_DUP_OPS, #if defined(__linux__) OPT_EPOLL, OPT_EPOLL_OPS, OPT_EPOLL_PORT, OPT_EPOLL_DOMAIN, #endif OPT_HDD_BYTES, OPT_HDD_WRITE_SIZE, OPT_HDD_OPS, OPT_HDD_OPTS, #if defined(__linux__) OPT_EVENTFD, OPT_EVENTFD_OPS, #endif #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L OPT_FALLOCATE_OPS, #endif OPT_FAULT, OPT_FAULT_OPS, OPT_FIFO, OPT_FIFO_OPS, OPT_FIFO_READERS, OPT_FLOCK, OPT_FLOCK_OPS, OPT_FORK_OPS, OPT_FORK_MAX, OPT_FSTAT, OPT_FSTAT_OPS, OPT_FSTAT_DIR, OPT_FUTEX, OPT_FUTEX_OPS, OPT_GET, OPT_GET_OPS, OPT_HSEARCH, OPT_HSEARCH_OPS, OPT_HSEARCH_SIZE, #if defined (__linux__) OPT_INOTIFY, OPT_INOTIFY_OPS, #endif #if defined (__linux__) OPT_IONICE_CLASS, OPT_IONICE_LEVEL, #endif OPT_IOSYNC_OPS, OPT_KILL, OPT_KILL_OPS, #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) OPT_LEASE, OPT_LEASE_OPS, OPT_LEASE_BREAKERS, #endif OPT_LINK, OPT_LINK_OPS, #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) OPT_LOCKF, OPT_LOCKF_OPS, OPT_LOCKF_NONBLOCK, #endif OPT_LSEARCH, OPT_LSEARCH_OPS, OPT_LSEARCH_SIZE, OPT_MALLOC, OPT_MALLOC_OPS, OPT_MALLOC_BYTES, OPT_MALLOC_MAX, OPT_MEMCPY, OPT_MEMCPY_OPS, OPT_METRICS_BRIEF, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) OPT_MINCORE, OPT_MINCORE_OPS, OPT_MINCORE_RAND, #endif OPT_MMAP, OPT_MMAP_OPS, OPT_MMAP_BYTES, OPT_MMAP_FILE, OPT_MMAP_ASYNC, OPT_MMAP_MPROTECT, #if defined(__linux__) OPT_MREMAP, OPT_MREMAP_OPS, OPT_MREMAP_BYTES, #endif OPT_MSG, OPT_MSG_OPS, #if defined(__linux__) OPT_MQ, OPT_MQ_OPS, OPT_MQ_SIZE, #endif OPT_NICE, OPT_NICE_OPS, OPT_NO_MADVISE, OPT_NULL, OPT_NULL_OPS, OPT_OPEN_OPS, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) OPT_PAGE_IN, #endif OPT_PIPE_OPS, OPT_POLL_OPS, OPT_PROCFS, OPT_PROCFS_OPS, OPT_PTHREAD, OPT_PTHREAD_OPS, OPT_PTHREAD_MAX, OPT_QSORT, OPT_QSORT_OPS, OPT_QSORT_INTEGERS, OPT_RDRAND, OPT_RDRAND_OPS, OPT_RENAME_OPS, OPT_SCHED, OPT_SCHED_PRIO, OPT_SEEK, OPT_SEEK_OPS, OPT_SEEK_SIZE, OPT_SENDFILE, OPT_SENDFILE_OPS, OPT_SENDFILE_SIZE, OPT_SEMAPHORE_POSIX, OPT_SEMAPHORE_POSIX_OPS, OPT_SEMAPHORE_POSIX_PROCS, #if !defined(__gnu_hurd__) OPT_SEMAPHORE_SYSV, OPT_SEMAPHORE_SYSV_OPS, OPT_SEMAPHORE_SYSV_PROCS, #endif OPT_SHM_SYSV, OPT_SHM_SYSV_OPS, OPT_SHM_SYSV_BYTES, OPT_SHM_SYSV_SEGMENTS, OPT_SEQUENTIAL, OPT_SIGFD, OPT_SIGFD_OPS, OPT_SIGFPE, OPT_SIGFPE_OPS, OPT_SIGSEGV, OPT_SIGSEGV_OPS, #if _POSIX_C_SOURCE >= 199309L OPT_SIGQUEUE, OPT_SIGQUEUE_OPS, #endif OPT_SOCKET_OPS, OPT_SOCKET_PORT, OPT_SOCKET_DOMAIN, OPT_SWITCH_OPS, #if defined(__linux__) OPT_SPLICE, OPT_SPLICE_OPS, OPT_SPLICE_BYTES, #endif OPT_STACK, OPT_STACK_OPS, OPT_SYMLINK, OPT_SYMLINK_OPS, OPT_SYSINFO, OPT_SYSINFO_OPS, #if defined (__linux__) OPT_TIMER_OPS, OPT_TIMER_FREQ, #endif OPT_TSEARCH, OPT_TSEARCH_OPS, OPT_TSEARCH_SIZE, OPT_TIMES, OPT_UDP, OPT_UDP_OPS, OPT_UDP_PORT, OPT_UDP_DOMAIN, #if defined (__linux__) || defined(__gnu_hurd__) OPT_URANDOM_OPS, #endif OPT_UTIME, OPT_UTIME_OPS, OPT_UTIME_FSYNC, #if defined(STRESS_VECTOR) OPT_VECMATH, OPT_VECMATH_OPS, #endif OPT_VERIFY, #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) OPT_VFORK, OPT_VFORK_OPS, OPT_VFORK_MAX, #endif OPT_VM_BYTES, OPT_VM_HANG, OPT_VM_KEEP, #ifdef MAP_POPULATE OPT_VM_MMAP_POPULATE, #endif #ifdef MAP_LOCKED OPT_VM_MMAP_LOCKED, #endif OPT_VM_OPS, OPT_VM_METHOD, #if defined(__linux__) OPT_VM_RW, OPT_VM_RW_OPS, OPT_VM_RW_BYTES, #endif #if defined(__linux__) OPT_VM_SPLICE, OPT_VM_SPLICE_OPS, OPT_VM_SPLICE_BYTES, #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) OPT_WAIT, OPT_WAIT_OPS, #endif #if defined (_POSIX_PRIORITY_SCHEDULING) OPT_YIELD_OPS, #endif OPT_ZERO, OPT_ZERO_OPS, } stress_op; /* stress test metadata */ typedef struct { const stress_func stress_func; /* stress test function */ const stress_id id; /* stress test ID */ const short int short_getopt; /* getopt short option */ const stress_op op; /* ops option */ const char *name; /* name of stress test */ const uint32_t class; /* class of stress test */ } stress_t; typedef struct { pid_t *pids; /* process id */ int32_t started_procs; /* count of started processes */ int32_t num_procs; /* number of process per stressor */ uint64_t bogo_ops; /* number of bogo ops */ } proc_info_t; typedef struct { const char ch; /* Scaling suffix */ const uint64_t scale; /* Amount to scale by */ } scale_t; /* Various option settings and flags */ extern const char *app_name; /* Name of application */ extern shared_t *shared; /* shared memory */ extern uint64_t opt_timeout; /* timeout in seconds */ extern int32_t opt_flags; /* option flags */ extern uint64_t opt_sequential; /* Number of sequential iterations */ extern volatile bool opt_do_run; /* false to exit stressor */ extern volatile bool opt_sigint; /* true if stopped by SIGINT */ extern mwc_t __mwc; /* internal mwc random state */ /* * externs to force gcc to stash computed values and hence * to stop the optimiser optimising code away to zero. The * *_put funcs are essentially no-op functions. */ extern void double_put(const double a); extern void uint64_put(const uint64_t a); extern uint64_t uint64_zero(void); /* Filenames and directories */ extern int stress_temp_filename(char *path, const size_t len, const char *name, const pid_t pid, const uint32_t instance, const uint64_t magic); extern int stress_temp_dir(char *path, const size_t len, const char *name, const pid_t pid, const uint32_t instance); extern int stress_temp_dir_mk(const char *name, const pid_t pid, const uint32_t instance); extern int stress_temp_dir_rm(const char *name, const pid_t pid, const uint32_t instance); #if defined(STRESS_X86) static inline void clflush(volatile void *ptr) { asm volatile("clflush %0" : "+m" (*(volatile char *)ptr)); } static inline void mfence(void) { asm volatile("mfence" : : : "memory"); } #else #define clflush(ptr) /* No-op */ #define mfence() /* No-op */ #endif /* * mwc() * Multiply-with-carry random numbers * fast pseudo random number generator, see * http://www.cse.yorku.ca/~oz/marsaglia-rng.html */ static inline uint64_t mwc(void) { __mwc.z = 36969 * (__mwc.z & 65535) + (__mwc.z >> 16); __mwc.w = 18000 * (__mwc.w & 65535) + (__mwc.w >> 16); return (__mwc.z << 16) + __mwc.w; } extern void mwc_seed(const uint64_t w, const uint64_t z); extern void mwc_reseed(void); /* Time handling */ extern double timeval_to_double(const struct timeval *tv); extern double time_now(void); /* Misc settings helpers */ extern void set_oom_adjustment(const char *name, bool killable); extern void set_sched(const int sched, const int sched_priority); extern void set_iopriority(const int class, const int level); extern void set_oom_adjustment(const char *name, bool killable); extern void set_coredump(const char *name); extern void set_proc_name(const char *name); /* Argument parsing and range checking */ extern int get_opt_sched(const char *const str); extern int get_opt_ionice_class(const char *const str); extern int get_int(const char *const str); extern uint64_t get_uint64(const char *const str); extern uint64_t get_uint64_scale(const char *const str, const scale_t scales[], const char *const msg); extern uint64_t get_uint64_byte(const char *const str); extern uint64_t get_uint64_time(const char *const str); extern long int opt_long(const char *opt, const char *str); extern void check_value(const char *const msg, const int val); extern void check_range(const char *const opt, const uint64_t val, const uint64_t lo, const uint64_t hi); /* Misc helper funcs */ extern char *munge_underscore(char *str); extern size_t stress_get_pagesize(void); extern long stress_get_processors_online(void); extern long stress_get_ticks_per_second(void); extern void set_max_limits(void); /* Memory tweaking */ extern int madvise_random(void *addr, size_t length); extern int mincore_touch_pages(void *buf, size_t buf_len); /* Mounts */ extern int mount_add(char *mnts[], const int max, int *n, const char *name); extern void mount_free(char *mnts[], const int n); extern int mount_get(char *mnts[], const int max); /* Network helpers */ void stress_set_net_port(const char *optname, const char *optarg, const int min_port, const int max_port, int *port); int stress_set_net_domain(const char *name, const char *domain_name, int *domain); void stress_set_sockaddr(const char *name, const uint32_t instance, const pid_t ppid, const int domain, const int port, struct sockaddr **sockaddr, socklen_t *len); extern void stress_semaphore_posix_init(void); extern void stress_semaphore_posix_destroy(void); extern void stress_semaphore_sysv_init(void); extern void stress_semaphore_sysv_destroy(void); /* Used to set options for specific stressors */ extern void stress_adjust_ptread_max(uint64_t max); extern void stress_set_aio_requests(const char *optarg); extern void stress_set_bigheap_growth(const char *optarg); extern void stress_set_bsearch_size(const char *optarg); extern void stress_set_cpu_load(const char *optarg); extern int stress_set_cpu_method(const char *name); extern void stress_set_dentries(const char *optarg); extern int stress_set_dentry_order(const char *optarg); extern void stress_set_epoll_port(const char *optarg); extern int stress_set_epoll_domain(const char *optarg); extern void stress_set_fifo_readers(const char *optarg); extern void stress_set_fork_max(const char *optarg); extern void stress_set_fstat_dir(const char *optarg); extern void stress_set_hdd_bytes(const char *optarg); extern int stress_hdd_opts(char *opts); extern void stress_set_hdd_write_size(const char *optarg); extern void stress_set_hsearch_size(const char *optarg); extern void stress_set_lease_breakers(const char *optarg); extern void stress_set_lsearch_size(const char *optarg); extern void stress_set_malloc_bytes(const char *optarg); extern void stress_set_malloc_max(const char *optarg); extern void stress_set_mmap_bytes(const char *optarg); extern void stress_set_mremap_bytes(const char *optarg); extern void stress_set_mq_size(const char *optarg); extern void stress_set_pthread_max(const char *optarg); extern void stress_set_qsort_size(const void *optarg); extern void stress_set_seek_size(const char *optarg); extern void stress_set_sendfile_size(const char *optarg); extern void stress_set_semaphore_posix_procs(const char *optarg); extern void stress_set_semaphore_sysv_procs(const char *optarg); extern void stress_set_shm_sysv_bytes(const char *optarg); extern void stress_set_shm_sysv_segments(const char *optarg); extern int stress_set_socket_domain(const char *name); extern void stress_set_socket_port(const char *optarg); extern void stress_set_splice_bytes(const char *optarg); extern void stress_set_timer_freq(const char *optarg); extern void stress_set_tsearch_size(const char *optarg); extern int stress_set_udp_domain(const char *name); extern void stress_set_udp_port(const char *optarg); extern void stress_set_vfork_max(const char *optarg); extern void stress_set_vm_bytes(const char *optarg); extern void stress_set_vm_flags(const int flag); extern void stress_set_vm_hang(const char *optarg); extern int stress_set_vm_method(const char *name); extern void stress_set_vm_rw_bytes(const char *optarg); extern void stress_set_vm_splice_bytes(const char *optarg); #define STRESS(name) \ extern int name(uint64_t *const counter, const uint32_t instance, \ const uint64_t max_ops, const char *name) /* Stressors */ STRESS(stress_affinity); STRESS(stress_aio); STRESS(stress_bigheap); STRESS(stress_brk); STRESS(stress_bsearch); STRESS(stress_cache); STRESS(stress_chmod); STRESS(stress_clock); STRESS(stress_cpu); STRESS(stress_dentry); STRESS(stress_dir); STRESS(stress_dup); STRESS(stress_epoll); STRESS(stress_eventfd); STRESS(stress_hdd); STRESS(stress_hsearch); STRESS(stress_fallocate); STRESS(stress_fault); STRESS(stress_fifo); STRESS(stress_flock); STRESS(stress_fork); STRESS(stress_fstat); STRESS(stress_futex); STRESS(stress_get); STRESS(stress_inotify); STRESS(stress_iosync); STRESS(stress_kill); STRESS(stress_lease); STRESS(stress_link); STRESS(stress_lockf); STRESS(stress_lsearch); STRESS(stress_malloc); STRESS(stress_memcpy); STRESS(stress_mincore); STRESS(stress_mmap); STRESS(stress_mremap); STRESS(stress_msg); STRESS(stress_mq); STRESS(stress_nice); STRESS(stress_noop); STRESS(stress_null); STRESS(stress_open); STRESS(stress_pipe); STRESS(stress_poll); STRESS(stress_procfs); STRESS(stress_pthread); STRESS(stress_qsort); STRESS(stress_rdrand); STRESS(stress_rename); STRESS(stress_seek); STRESS(stress_sem_posix); STRESS(stress_sem_sysv); STRESS(stress_shm_sysv); STRESS(stress_sendfile); STRESS(stress_sigfd); STRESS(stress_sigfpe); STRESS(stress_sigsegv); STRESS(stress_sigq); STRESS(stress_socket); STRESS(stress_splice); STRESS(stress_stack); STRESS(stress_switch); STRESS(stress_symlink); STRESS(stress_sysinfo); STRESS(stress_timer); STRESS(stress_tsearch); STRESS(stress_udp); STRESS(stress_urandom); STRESS(stress_utime); STRESS(stress_vecmath); STRESS(stress_vfork); STRESS(stress_vm); STRESS(stress_vm_rw); STRESS(stress_vm_splice); STRESS(stress_wait); STRESS(stress_yield); STRESS(stress_zero); #endif stress-ng-0.03.15/stress-sigfd.c0000664000175000017500000000530712466243156015050 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_sigfd * stress signalfd reads */ int stress_sigfd( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid, ppid = getpid(); int sfd; sigset_t mask; (void)instance; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { pr_failed_dbg(name, "sigprocmask"); _exit(EXIT_FAILURE); } sfd = signalfd(-1, &mask, 0); if (sfd < 0) { pr_failed_dbg(name, "signalfd"); _exit(EXIT_FAILURE); } pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { for (;;) { union sigval s; int ret; memset(&s, 0, sizeof(s)); s.sival_int = 0; ret = sigqueue(ppid, SIGUSR1, s); if (ret < 0) break; } (void)close(sfd); _exit(0); } else { /* Parent */ int status; do { int ret; struct signalfd_siginfo fdsi; ret = read(sfd, &fdsi, sizeof(fdsi)); if (ret == 0) break; if (ret != sizeof(fdsi)) { pr_failed_dbg(name, "signalfd read"); (void)close(sfd); _exit(EXIT_FAILURE); } if (opt_flags & OPT_FLAGS_VERIFY) { if (fdsi.ssi_signo != SIGUSR1) { pr_fail(stderr, "%s: unexpected signal %d", name, fdsi.ssi_signo); break; } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* terminal child */ (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-iosync.c0000664000175000017500000000273412466243156015261 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" /* * stress on sync() * stress system by IO sync calls */ int stress_iosync( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; do { sync(); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-mq.c0000664000175000017500000001043012466243156014362 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined(__linux__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" typedef struct { uint64_t value; bool stop; } msg_t; static int opt_mq_size = DEFAULT_MQ_SIZE; void stress_set_mq_size(const char *optarg) { uint64_t sz; sz = get_uint64_byte(optarg); check_range("mq-size", opt_mq_size, MIN_MQ_SIZE, MAX_MQ_SIZE); opt_mq_size = (int)sz; } /* * stress_mq * stress POSIX message queues */ int stress_mq( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid = getpid(); mqd_t mq = -1; int sz = opt_mq_size, max_sz; FILE *fp; struct mq_attr attr; char mq_name[64]; (void)instance; snprintf(mq_name, sizeof(mq_name), "/%s-%i-%" PRIu32, name, pid, instance); if ((fp = fopen("/proc/sys/fs/mqueue/msg_default", "r")) != NULL) { if (fscanf(fp, "%20d", &max_sz) != 1) max_sz = MAX_MQ_SIZE; (void)fclose(fp); if (max_sz < MIN_MQ_SIZE) max_sz = MIN_MQ_SIZE; if (max_sz > MAX_MQ_SIZE) max_sz = MAX_MQ_SIZE; } else { max_sz = MAX_MQ_SIZE; } if (sz > max_sz) sz = max_sz; /* * Determine a workable MQ size if we can't determine it from /proc */ while (sz > 0) { attr.mq_flags = 0; attr.mq_maxmsg = sz; attr.mq_msgsize = sizeof(msg_t); attr.mq_curmsgs = 0; mq = mq_open(mq_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr); if (mq >= 0) break; sz--; } if (mq < 0) { pr_failed_dbg(name, "mq_open"); return EXIT_FAILURE; } if (sz < opt_mq_size) { pr_inf(stdout, "POSIX message queue requested size %d messages, maximum of %d allowed\n", opt_mq_size, sz); } pr_dbg(stderr, "POSIX message queue %s with %lu messages\n", mq_name, (unsigned long)attr.mq_maxmsg); pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { for (;;) { uint64_t i; for (i = 0; ; i++) { msg_t msg; if (mq_receive(mq, (char *)&msg, sizeof(msg), NULL) < 0) { pr_failed_dbg(name, "mq_receive"); break; } if (msg.stop) break; if (opt_flags & OPT_FLAGS_VERIFY) { if (msg.value != i) { pr_fail(stderr, "mq_receive: expected message " "containing 0x%" PRIx64 " but received 0x%" PRIx64 " instead\n", i, msg.value); } } } exit(EXIT_SUCCESS); } } else { int status; msg_t msg; /* Parent */ do { memset(&msg, 0, sizeof(msg)); msg.value = (*counter); msg.stop = false; if (mq_send(mq, (char *)&msg, sizeof(msg), 1) < 0) { if (errno != EINTR) pr_failed_dbg(name, "msgsnd"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); msg.value = (*counter); msg.stop = true; if (mq_send(mq, (char *)&msg, sizeof(msg), 1) < 0) { pr_failed_dbg(name, "termination msgsnd"); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); if (mq_close(mq) < 0) pr_failed_dbg(name, "mq_close"); if (mq_unlink(mq_name) < 0) pr_failed_dbg(name, "mq_unlink"); } return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-hsearch.c0000664000175000017500000000611012466243156015362 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" static uint64_t opt_hsearch_size = DEFAULT_HSEARCH_SIZE; /* * stress_set_hsearch_size() * set hsearch size from given option string */ void stress_set_hsearch_size(const char *optarg) { opt_hsearch_size = get_uint64_byte(optarg); check_range("hsearch-size", opt_hsearch_size, MIN_TSEARCH_SIZE, MAX_TSEARCH_SIZE); } /* * stress_hsearch() * stress hsearch */ int stress_hsearch( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t max = (size_t)opt_hsearch_size; size_t i; int ret = EXIT_FAILURE; char **keys; (void)instance; /* Make hash table with 25% slack */ if (!hcreate(max + (max / 4))) { pr_failed_err(name, "hcreate"); return EXIT_FAILURE; } if ((keys = calloc(max, sizeof(char *))) == NULL) { pr_err(stderr, "%s: cannot allocate keys\n", name); goto free_hash; } /* Populate hash, make it 100% full for worst performance */ for (i = 0; i < max; i++) { char buffer[32]; ENTRY e; snprintf(buffer, sizeof(buffer), "%zu", i); keys[i] = strdup(buffer); if (!keys[i]) { pr_err(stderr, "%s: cannot allocate key\n", name); goto free_all; } e.key = keys[i]; e.data = (void *)i; if (hsearch(e, ENTER) == NULL) { pr_err(stderr, "%s: cannot allocate new hash item\n", name); goto free_all; } } do { for (i = 0; opt_do_run && i < max; i++) { ENTRY e, *ep; e.key = keys[i]; e.data = NULL; /* Keep Coverity quiet */ ep = hsearch(e, FIND); if (opt_flags & OPT_FLAGS_VERIFY) { if (ep == NULL) { pr_fail(stderr, "cannot find key %s\n", keys[i]); } else { if (i != (size_t)ep->data) { pr_fail(stderr, "hash returned incorrect data %zd\n", i); } } } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); ret = EXIT_SUCCESS; free_all: for (i = 0; i < max; i++) free(keys[i]); free(keys); free_hash: hdestroy(); return ret; } stress-ng-0.03.15/madvise.c0000664000175000017500000000450612466243156014063 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" #if _BSD_SOURCE static const int madvise_options[] = { #ifdef MADV_NORMAL MADV_NORMAL, #endif #ifdef MADV_RANDOM MADV_RANDOM, #endif #ifdef MADV_SEQUENTIAL MADV_SEQUENTIAL, #endif #ifdef MADV_WILLNEDD MADV_WILLNEED, #endif /* * Don't use DONTNEED as this can zero fill * pages that don't have backing store which * trips checksum errors when we check that * the pages are sane. * #ifdef MADV_DONTNEED MADV_DONTNEED, #endif */ #ifdef MADV_DONTFORK MADV_DONTFORK, #endif #ifdef MADV_DOFORK MADV_DOFORK, #endif #ifdef MADV_MERGEABLE MADV_MERGEABLE, #endif #ifdef MADV_UNMERGEABLE MADV_UNMERGEABLE, #endif #ifdef MADV_HUGEPAGE MADV_HUGEPAGE, #endif #ifdef MADV_NOHUGEPAGE MADV_NOHUGEPAGE, #endif #ifdef MADV_DONTDUMP MADV_DONTDUMP, #endif #ifdef MADV_DODUMP MADV_DODUMP #endif }; #endif /* * madvise_random() * apply random madvise setting to a memory region */ int madvise_random(void *addr, size_t length) { #if _BSD_SOURCE if (opt_flags & OPT_FLAGS_MMAP_MADVISE) { int i = (mwc() >> 7) % SIZEOF_ARRAY(madvise_options); return madvise(addr, length, madvise_options[i]); } #else (void)addr; (void)length; #endif return 0; } stress-ng-0.03.15/stress-null.c0000664000175000017500000000347412466243156014731 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_null * stress reading of /dev/null */ int stress_null( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd; char buffer[4096]; (void)instance; if ((fd = open("/dev/null", O_WRONLY)) < 0) { pr_failed_err(name, "open"); return EXIT_FAILURE; } memset(buffer, 0xff, sizeof(buffer)); do { if (write(fd, buffer, sizeof(buffer)) < 0) { pr_failed_err(name, "write"); (void)close(fd); return EXIT_FAILURE; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-stack.c0000664000175000017500000001064412466243156015061 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include #include #include "stress-ng.h" static sigjmp_buf jmp_env; /* * stress_segvhandler() * SEGV handler */ static void stress_segvhandler(int dummy) { (void)dummy; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } /* * stress_stack * stress by forcing stack overflows */ int stress_stack( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; (void)instance; uint8_t stack[SIGSTKSZ]; stack_t ss; /* * We need to create an alternative signal * stack so when a segfault occurs we use * this already allocated signal stack rather * than try to push onto an already overflowed * stack */ memset(stack, 0, sizeof(stack)); ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_failed_err(name, "sigaltstack"); return EXIT_FAILURE; } again: pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; /* Parent, wait for child */ ret = waitpid(pid, &status, 0); if (ret < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n", name, errno, strerror(errno)); (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %d (instance %d)\n", name, WTERMSIG(status), instance); /* If we got killed by OOM killer, re-start */ if (WTERMSIG(status) == SIGKILL) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); goto again; } } } else if (pid == 0) { char *start_ptr = sbrk(0); if (start_ptr == (void *) -1) { pr_err(stderr, "%s: sbrk(0) failed: errno=%d (%s)\n", name, errno, strerror(errno)); exit(EXIT_FAILURE); } /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); for (;;) { struct sigaction new_action; int ret; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; memset(&new_action, 0, sizeof new_action); new_action.sa_handler = stress_segvhandler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = SA_ONSTACK; if (sigaction(SIGSEGV, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } if (sigaction(SIGBUS, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); /* * We return here if we segfault, so * first check if we need to terminate */ if (!opt_do_run || (max_ops && *counter >= max_ops)) break; if (ret) { /* We end up here after handling the fault */ (*counter)++; } else { /* Expand the stack and cause a fault */ char *last_ptr = 0; do { char *ptr = alloca(256 * KB); /* need this else gcc optimises out the alloca */ *ptr = 0; /* Force gcc to actually do the alloca */ uint64_put((uint64_t)(last_ptr - ptr)); last_ptr = ptr; } while (opt_do_run); } } } return EXIT_SUCCESS; } stress-ng-0.03.15/stress-nice.c0000664000175000017500000000465612466243156014700 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress on sched_nice() * stress system by sched_nice */ int stress_nice( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int max_prio, min_prio; (void)instance; (void)name; #ifdef RLIMIT_NICE { struct rlimit rlim; if (getrlimit(RLIMIT_NICE, &rlim) < 0) { /* Make an assumption, bah */ max_prio = 20; min_prio = -20; } else { max_prio = 20 - (int)rlim.rlim_cur; min_prio = -max_prio; } } #else /* Make an assumption, bah */ max_prio = 20; min_prio = -20; #endif do { pid_t pid; pid = fork(); if (pid == 0) { int i; /* Child */ pid = getpid(); for (i = min_prio; i <= max_prio; i++) { errno = 0; setpriority(PRIO_PROCESS, pid, i); if (!errno) { double start = time_now(); while (time_now() - start < 0.1) ; (*counter)++; } } _exit(0); } if (pid > 0) { int status; /* Parent, wait for child */ if (waitpid(pid, &status, 0) < 0) { (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); } } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-pthread.c0000664000175000017500000001244112466243156015400 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static uint64_t opt_pthread_max = DEFAULT_PTHREAD; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static bool thread_terminate; static uint64_t pthread_count; static sigset_t set; void stress_set_pthread_max(const char *optarg) { opt_pthread_max = get_uint64_byte(optarg); check_range("pthread-max", opt_pthread_max, MIN_PTHREAD, MAX_PTHREAD); } void stress_adjust_ptread_max(uint64_t max) { if (opt_pthread_max > max) { opt_pthread_max = max; pr_inf(stdout, "re-adjusting maximum threads to " "soft limit of %" PRIu64 "\n", opt_pthread_max); } } /* * stress_pthread_func() * pthread that exits immediately */ void *stress_pthread_func(void *ctxt) { uint8_t stack[SIGSTKSZ]; stack_t ss; static void *nowt = NULL; (void)ctxt; /* * Block all signals, let controlling thread * handle these */ sigprocmask(SIG_BLOCK, &set, NULL); /* * According to POSIX.1 a thread should have * a distinct alternative signal stack. * However, we block signals in this thread * so this is probably just totall unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_failed_err("pthread", "sigaltstack"); goto die; } /* * Bump count of running threads */ if (pthread_mutex_lock(&mutex)) { pr_failed_err("pthread", "mutex lock"); goto die; } pthread_count++; if (pthread_mutex_unlock(&mutex)) { pr_failed_err("pthread", "mutex unlock"); goto die; } /* * Wait for controlling thread to * indicate it is time to die */ if (pthread_mutex_lock(&mutex)) { pr_failed_err("pthread", "mutex unlock"); goto die; } while (!thread_terminate) { if (pthread_cond_wait(&cond, &mutex)) { pr_failed_err("pthread", "pthread condition wait"); break; } } if (pthread_mutex_unlock(&mutex)) { pr_failed_err("pthread", "mutex unlock"); } die: return &nowt; } /* * stress_pthread() * stress by creating pthreads */ int stress_pthread( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pthread_t pthreads[MAX_PTHREAD]; bool ok = true; uint64_t limited = 0, attempted = 0; (void)instance; sigfillset(&set); do { uint64_t i, j; thread_terminate = false; pthread_count = 0; for (i = 0; (i < opt_pthread_max) && (!max_ops || *counter < max_ops); i++) { if (pthread_create(&pthreads[i], NULL, stress_pthread_func, NULL)) { /* Out of resources, don't try any more */ if (errno == EAGAIN) { limited++; break; } /* Something really unexpected */ pr_failed_err(name, "pthread create"); ok = false; break; } (*counter)++; if (!opt_do_run) break; } attempted++; /* * Wait until they are all started or * we get bored waiting.. */ for (j = 0; j < 1000; j++) { bool all_running = false; if (pthread_mutex_lock(&mutex)) { pr_failed_err(name, "mutex lock"); ok = false; goto reap; } all_running = (pthread_count == i); if (pthread_mutex_unlock(&mutex)) { pr_failed_err(name, "mutex unlock"); ok = false; goto reap; } if (all_running) break; } if (pthread_mutex_lock(&mutex)) { pr_failed_err(name, "mutex lock"); ok = false; goto reap; } thread_terminate = true; if (pthread_cond_broadcast(&cond)) { pr_failed_err(name, "pthread condition broadcast"); ok = false; /* fall through and unlock */ } if (pthread_mutex_unlock(&mutex)) { pr_failed_err(name, "mutex unlock"); ok = false; } reap: for (j = 0; j < i; j++) { if (pthread_join(pthreads[j], NULL)) { pr_failed_err(name, "pthread join"); ok = false; } } } while (ok && opt_do_run && (!max_ops || *counter < max_ops)); if (limited) { pr_inf(stdout, "%.2f%% of iterations could not reach " "requested %" PRIu64 " threads (instance %" PRIu32 ")\n", 100.0 * (double)limited / (double)attempted, opt_pthread_max, instance); } (void)pthread_cond_destroy(&cond); (void)pthread_mutex_destroy(&mutex); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-fallocate.c0000664000175000017500000000562712466243156015713 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L /* * stress_fallocate * stress I/O via fallocate and ftruncate */ int stress_fallocate( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); int fd; char filename[PATH_MAX]; uint64_t ftrunc_errs = 0; if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)unlink(filename); do { (void)posix_fallocate(fd, (off_t)0, 4096 * 4096); if (!opt_do_run) break; fsync(fd); if (opt_flags & OPT_FLAGS_VERIFY) { struct stat buf; if (fstat(fd, &buf) < 0) pr_fail(stderr, "fstat on file failed"); else if (buf.st_size != (off_t)4096 * 4096) pr_fail(stderr, "file size does not match size the expected file size\n"); } if (ftruncate(fd, 0) < 0) ftrunc_errs++; if (!opt_do_run) break; fsync(fd); if (opt_flags & OPT_FLAGS_VERIFY) { struct stat buf; if (fstat(fd, &buf) < 0) pr_fail(stderr, "fstat on file failed"); else if (buf.st_size != (off_t)0) pr_fail(stderr, "file size does not match size the expected file size\n"); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); if (ftrunc_errs) pr_dbg(stderr, "%s: %" PRIu64 " ftruncate errors occurred.\n", name, ftrunc_errs); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-vm.c0000664000175000017500000012073212466243156014376 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" #define VM_BOGO_SHIFT (12) /* * the VM stress test has diffent methods of vm stressor */ typedef size_t (*stress_vm_func)(uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops); typedef struct { const char *name; const stress_vm_func func; } stress_vm_stressor_info_t; static uint64_t opt_vm_hang = DEFAULT_VM_HANG; static size_t opt_vm_bytes = DEFAULT_VM_BYTES; static int opt_vm_flags = 0; /* VM mmap flags */ static stress_vm_stressor_info_t *opt_vm_stressor; static stress_vm_stressor_info_t vm_methods[]; void stress_set_vm_hang(const char *optarg) { opt_vm_hang = get_uint64_byte(optarg); check_range("vm-hang", opt_vm_hang, MIN_VM_HANG, MAX_VM_HANG); } void stress_set_vm_bytes(const char *optarg) { opt_vm_bytes = (size_t)get_uint64_byte(optarg); check_range("vm-bytes", opt_vm_bytes, MIN_VM_BYTES, MAX_VM_BYTES); } void stress_set_vm_flags(const int flag) { opt_vm_flags |= flag; } /* * For testing, set this to 1 to simulate random memory errors */ #define INJECT_BIT_ERRORS (0) #define SET_AND_TEST(ptr, val, bit_errors) \ { \ *ptr = val; \ bit_errors += (*ptr != val); \ } /* * This compiles down to a load, ror, store in x86 */ #define ROR64(val) \ { \ uint64_t tmp = val; \ uint64_t bit0 = (tmp & 1) << 63; \ tmp >>= 1; \ tmp |= bit0; \ val = tmp; \ } #define ROR8(val) \ { \ uint8_t tmp = val; \ uint8_t bit0 = (tmp & 1) << 7; \ tmp >>= 1; \ tmp |= bit0; \ val = tmp; \ } #define INC_LO_NYBBLE(val) \ { \ uint8_t lo = (val); \ lo += 1; \ lo &= 0xf; \ (val) = ((val) & 0xf0) | lo; \ } #define INC_HI_NYBBLE(val) \ { \ uint8_t hi = (val); \ hi += 0xf0; \ hi &= 0xf0; \ (val) = ((val) & 0x0f) | hi; \ } #define UNSIGNED_ABS(a, b) \ ((a) > (b)) ? (a) - (b) : (b) - (a) #if INJECT_BIT_ERRORS /* * inject_random_bit_errors() * for testing purposes, we can insert various faults */ static void inject_random_bit_errors(uint8_t *buf, const size_t sz) { int i; for (i = 0; i < 8; i++) { /* 1 bit errors */ buf[random() % sz] ^= (1 << i); buf[random() % sz] |= (1 << i); buf[random() % sz] &= ~(1 << i); } for (i = 0; i < 7; i++) { /* 2 bit errors */ buf[random() % sz] ^= (3 << i); buf[random() % sz] |= (3 << i); buf[random() % sz] &= ~(3 << i); } for (i = 0; i < 6; i++) { /* 3 bit errors */ buf[random() % sz] ^= (7 << i); buf[random() % sz] |= (7 << i); buf[random() % sz] &= ~(7 << i); } } #else /* No-op */ static inline void inject_random_bit_errors(uint8_t *buf, const size_t sz) { (void)buf; (void)sz; } #endif /* * stress_vm_check() * report back on bit errors found */ static void stress_vm_check(const char *name, const size_t bit_errors) { if (bit_errors && (opt_flags & OPT_FLAGS_VERIFY)) #if INJECT_BIT_ERRORS pr_dbg(stderr, "%s: detected %zu memory error%s\n", name, bit_errors, bit_errors == 1 ? "" : "s"); #else pr_fail(stderr, "%s: detected %zu memory error%s\n", name, bit_errors, bit_errors == 1 ? "" : "s"); #endif } /* * stress_vm_count_bits() * count number of bits set (K and R) */ static inline size_t stress_vm_count_bits(uint64_t v) { size_t n; for (n = 0; v; n++) v &= v - 1; return n; } /* * stress_vm_moving_inversion() * work sequentially through memory setting 8 bytes at at a time * with a random value, then check if it is correct, invert it and * then check if that is correct. */ static size_t stress_vm_moving_inversion( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { uint64_t w, z, *buf_end, c = *counter; volatile uint64_t *ptr; size_t bit_errors; buf_end = (uint64_t *)(buf + sz); mwc_reseed(); w = mwc(); z = mwc(); mwc_seed(w, z); for (ptr = (uint64_t *)buf; ptr < buf_end; ) { *(ptr++) = mwc(); } mwc_seed(w, z); for (bit_errors = 0, ptr = (uint64_t *)buf; ptr < buf_end; ) { uint64_t val = mwc(); if (*ptr != val) bit_errors++; *(ptr++) = ~val; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); mwc_seed(w, z); for (bit_errors = 0, ptr = (uint64_t *)buf; ptr < buf_end; ) { uint64_t val = mwc(); if (*(ptr++) != ~val) bit_errors++; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } mwc_seed(w, z); for (ptr = (uint64_t *)buf_end; ptr > (uint64_t *)buf; ) { *--ptr = mwc(); c++; if (max_ops && c >= max_ops) goto abort; } inject_random_bit_errors(buf, sz); (void)mincore_touch_pages(buf, sz); mwc_seed(w, z); for (ptr = (uint64_t *)buf_end; ptr > (uint64_t *)buf; ) { uint64_t val = mwc(); if (*--ptr != val) bit_errors++; *ptr = ~val; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } mwc_seed(w, z); for (ptr = (uint64_t *)buf_end; ptr > (uint64_t *)buf; ) { uint64_t val = mwc(); if (*--ptr != ~val) bit_errors++; if (!opt_do_run) goto abort; } abort: stress_vm_check("moving inversion", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_modulo_x() * set every 23rd byte to a random pattern and then set * all the other bytes to the complement of this. Check * that the random patterns are still set. */ static size_t stress_vm_modulo_x( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { uint32_t i, j; const uint32_t stride = 23; /* Small prime to hit cache */ uint8_t pattern, compliment; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; size_t bit_errors = 0; uint64_t c = *counter; mwc_reseed(); pattern = mwc(); compliment = ~pattern; for (i = 0; i < stride; i++) { for (ptr = buf + i; ptr < buf_end; ptr += stride) { *ptr = pattern; if (!opt_do_run) goto abort; } for (ptr = buf; ptr < buf_end; ptr += stride) { for (j = 0; j < i && ptr < buf_end; j++) { *ptr++ = compliment; c++; if (max_ops && c >= max_ops) goto abort; } if (!opt_do_run) goto abort; ptr++; for (j = i + 1; j < stride && ptr < buf_end; j++) { *ptr++ = compliment; c++; if (max_ops && c >= max_ops) goto abort; } if (!opt_do_run) goto abort; } inject_random_bit_errors(buf, sz); for (ptr = buf + i; ptr < buf_end; ptr += stride) { if (*ptr != pattern) bit_errors++; if (!opt_do_run) return bit_errors; } } abort: stress_vm_check("modulo X", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_walking_one_data() * for each byte, walk through each data line setting them to high * setting each bit to see if none of the lines are stuck */ static size_t stress_vm_walking_one_data( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t bit_errors = 0; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint64_t c = *counter; for (ptr = buf; ptr < buf_end; ptr++) { SET_AND_TEST(ptr, 0x01, bit_errors); SET_AND_TEST(ptr, 0x02, bit_errors); SET_AND_TEST(ptr, 0x04, bit_errors); SET_AND_TEST(ptr, 0x08, bit_errors); SET_AND_TEST(ptr, 0x10, bit_errors); SET_AND_TEST(ptr, 0x20, bit_errors); SET_AND_TEST(ptr, 0x40, bit_errors); SET_AND_TEST(ptr, 0x80, bit_errors); c++; if (max_ops && c >= max_ops) break; if (!opt_do_run) break; } stress_vm_check("walking one (data)", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_walking_zero_data() * for each byte, walk through each data line setting them to low * setting each bit to see if none of the lines are stuck */ static size_t stress_vm_walking_zero_data( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t bit_errors = 0; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint64_t c = *counter; for (ptr = buf; ptr < buf_end; ptr++) { SET_AND_TEST(ptr, 0xfe, bit_errors); SET_AND_TEST(ptr, 0xfd, bit_errors); SET_AND_TEST(ptr, 0xfb, bit_errors); SET_AND_TEST(ptr, 0xf7, bit_errors); SET_AND_TEST(ptr, 0xef, bit_errors); SET_AND_TEST(ptr, 0xdf, bit_errors); SET_AND_TEST(ptr, 0xbf, bit_errors); SET_AND_TEST(ptr, 0x7f, bit_errors); c++; if (max_ops && c >= max_ops) break; if (!opt_do_run) break; } stress_vm_check("walking zero (data)", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_walking_one_addr() * work through a range of addresses setting each address bit in * the given memory mapped range to high to see if any address bits * are stuck. */ static size_t stress_vm_walking_one_addr( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint8_t d1 = 0, d2 = ~d1; size_t bit_errors = 0; size_t tests = 0; uint64_t c = *counter; memset(buf, d1, sz); for (ptr = buf; ptr < buf_end; ptr += 256) { uint16_t i; uint64_t mask; *ptr = d1; for (mask = 1, i = 1; i < 64; i++) { uintptr_t uintptr = ((uintptr_t)ptr) ^ mask; uint8_t *addr = (uint8_t *)uintptr; if (addr == ptr) continue; if (addr < buf || addr >= buf_end || addr == ptr) continue; *addr = d2; tests++; if (*ptr != d1) bit_errors++; mask <<= 1; } c++; if (max_ops && c >= max_ops) break; if (!opt_do_run) break; } stress_vm_check("walking one (address)", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_walking_zero_addr() * work through a range of addresses setting each address bit in * the given memory mapped range to low to see if any address bits * are stuck. */ static size_t stress_vm_walking_zero_addr( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint8_t d1 = 0, d2 = ~d1; size_t bit_errors = 0; size_t tests = 0; uint64_t sz_mask; uint64_t c = *counter; for (sz_mask = 1; sz_mask < sz; sz_mask <<= 1) ; sz_mask--; memset(buf, d1, sz); for (ptr = buf; ptr < buf_end; ptr += 256) { uint16_t i; uint64_t mask; *ptr = d1; for (mask = 1, i = 1; i < 64; i++) { uintptr_t uintptr = ((uintptr_t)ptr) ^ (~mask & sz_mask); uint8_t *addr = (uint8_t *)uintptr; if (addr < buf || addr >= buf_end || addr == ptr) continue; *addr = d2; tests++; if (*ptr != d1) bit_errors++; mask <<= 1; } c++; if (max_ops && c >= max_ops) break; if (!opt_do_run) break; } stress_vm_check("walking zero (address)", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_gray() * fill all of memory with a gray code and check that * all the bits are set correctly. gray codes just change * one bit at a time. */ static size_t stress_vm_gray( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static uint8_t val; uint8_t v, *buf_end = buf + sz; volatile uint8_t *ptr; size_t bit_errors = 0; uint64_t c = *counter; for (v = val, ptr = buf; ptr < buf_end; ptr++, v++) { if (!opt_do_run) return 0; *ptr = (v >> 1) ^ v; c++; if (max_ops && c >= max_ops) break; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (v = val, ptr = buf; ptr < buf_end; ptr++, v++) { if (!opt_do_run) break; if (*ptr != ((v >> 1) ^ v)) bit_errors++; } val++; stress_vm_check("gray code", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_incdec() * work through memory incrementing it and then decrementing * it by a value that changes on each test iteration. * Check that the memory has not changed by the inc + dec * operations. */ static size_t stress_vm_incdec( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static uint8_t val = 0; uint8_t *buf_end = buf + sz; volatile uint8_t *ptr; size_t bit_errors = 0; uint64_t c = *counter; val++; memset(buf, 0x00, sz); for (ptr = buf; ptr < buf_end; ptr++) { *ptr += val; c++; if (max_ops && c >= max_ops) break; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (ptr = buf; ptr < buf_end; ptr++) { *ptr -= val; c++; if (max_ops && c >= max_ops) break; } for (ptr = buf; ptr < buf_end; ptr++) { if (*ptr != 0) bit_errors++; } stress_vm_check("incdec code", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_prime_incdec() * walk through memory in large prime steps incrementing * bytes and then re-walk again decrementing; then sanity * check. */ static size_t stress_vm_prime_incdec( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static uint8_t val = 0; uint8_t *buf_end = buf + sz; volatile uint8_t *ptr = buf; size_t bit_errors = 0, i; const uint64_t prime = PRIME_64; uint64_t j, c = *counter; #if SIZE_MAX > UINT32_MAX /* Unlikely.. */ if (sz > (1ULL << 63)) return 0; #endif memset(buf, 0x00, sz); for (i = 0; i < sz; i++) { ptr[i] += val; c++; if (max_ops && c >= max_ops) break; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ for (i = 0, j = prime; i < sz; i++, j += prime) { ptr[j % sz] -= val; c++; if (max_ops && c >= max_ops) break; } for (ptr = buf; ptr < buf_end; ptr++) { if (*ptr != 0) bit_errors++; } stress_vm_check("prime-incdec", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_swap() * forward swap and then reverse swap chunks of memory * and see that nothing got corrupted. */ static size_t stress_vm_swap( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { const size_t chunk_sz = 64, chunks = sz / chunk_sz; uint64_t w1, z1, c = *counter; uint8_t *buf_end = buf + sz; volatile uint8_t *ptr; size_t bit_errors = 0, i; size_t *swaps; mwc_reseed(); z1 = mwc(); w1 = mwc(); if ((swaps = calloc(chunks, sizeof(size_t))) == NULL) { pr_failed_dbg("stress-vm", "calloc"); return 0; } for (i = 0; i < chunks; i++) { swaps[i] = (mwc() % chunks) * chunk_sz; } mwc_seed(w1, z1); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc(); memset((void *)ptr, val, chunk_sz); } /* Forward swaps */ for (i = 0, ptr = buf; ptr < buf_end; ptr += chunk_sz, i++) { size_t offset = swaps[i]; volatile uint8_t *dst = buf + offset, *src = ptr, *src_end = src + chunk_sz; while (src < src_end) { uint8_t tmp = *src; *src++ = *dst; *dst++ = tmp; } c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } /* Reverse swaps */ for (i = chunks - 1, ptr = buf_end - chunk_sz; ptr >= buf; ptr -= chunk_sz, i--) { size_t offset = swaps[i]; volatile uint8_t *dst = buf + offset, *src = ptr, *src_end = src + chunk_sz; while (src < src_end) { uint8_t tmp = *src; *src++ = *dst; *dst++ = tmp; } c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); mwc_seed(w1, z1); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { volatile uint8_t *p = ptr, *p_end = ptr + chunk_sz; uint8_t val = mwc(); while (p < p_end) { if (*p != val) bit_errors++; p++; } if (!opt_do_run) break; } abort: free(swaps); stress_vm_check("swap bytes", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_rand_set() * fill 64 bit chunks of memory with a random pattern and * and then sanity check they are all set correctly. */ static size_t stress_vm_rand_set( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { const size_t chunk_sz = sizeof(uint8_t) * 8; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint64_t w, z, c = *counter; size_t bit_errors = 0; mwc_reseed(); w = mwc(); z = mwc(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc(); *(ptr + 0) = val; *(ptr + 1) = val; *(ptr + 2) = val; *(ptr + 3) = val; *(ptr + 4) = val; *(ptr + 5) = val; *(ptr + 6) = val; *(ptr + 7) = val; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc(); bit_errors += (*(ptr + 0) != val); bit_errors += (*(ptr + 1) != val); bit_errors += (*(ptr + 2) != val); bit_errors += (*(ptr + 3) != val); bit_errors += (*(ptr + 4) != val); bit_errors += (*(ptr + 5) != val); bit_errors += (*(ptr + 6) != val); bit_errors += (*(ptr + 7) != val); if (!opt_do_run) break; } abort: stress_vm_check("rand-set", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_ror() * fill memory with a random pattern and then rotate * right all the bits in an 8 byte (64 bit) chunk * and then sanity check they are all shifted at the * end. */ static size_t stress_vm_ror( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { const size_t chunk_sz = sizeof(uint8_t) * 8; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; uint64_t w, z, c = *counter; size_t bit_errors = 0; mwc_reseed(); w = mwc(); z = mwc(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = (uint8_t)mwc(); *(ptr + 0) = val; *(ptr + 1) = val; *(ptr + 2) = val; *(ptr + 3) = val; *(ptr + 4) = val; *(ptr + 5) = val; *(ptr + 6) = val; *(ptr + 7) = val; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { ROR64(*(ptr + 0)); ROR64(*(ptr + 1)); ROR64(*(ptr + 2)); ROR64(*(ptr + 3)); ROR64(*(ptr + 4)); ROR64(*(ptr + 5)); ROR64(*(ptr + 6)); ROR64(*(ptr + 7)); c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = (uint8_t)mwc(); ROR64(val); bit_errors += (*(ptr + 0) != val); bit_errors += (*(ptr + 1) != val); bit_errors += (*(ptr + 2) != val); bit_errors += (*(ptr + 3) != val); bit_errors += (*(ptr + 4) != val); bit_errors += (*(ptr + 5) != val); bit_errors += (*(ptr + 6) != val); bit_errors += (*(ptr + 7) != val); if (!opt_do_run) break; } abort: stress_vm_check("ror", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_flip() * set all memory to random pattern, then work through * memory 8 times flipping bits 0..7 on by one to eventually * invert all the bits. Check if the final bits are all * correctly inverted. */ static size_t stress_vm_flip( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { const size_t chunk_sz = sizeof(uint8_t) * 8; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz, bit = 0b00000011; uint64_t w, z, c = *counter; size_t bit_errors = 0, i; mwc_reseed(); w = mwc(); z = mwc(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = (uint8_t)mwc(); *(ptr + 0) = val; ROR8(val); *(ptr + 1) = val; ROR8(val); *(ptr + 2) = val; ROR8(val); *(ptr + 3) = val; ROR8(val); *(ptr + 4) = val; ROR8(val); *(ptr + 5) = val; ROR8(val); *(ptr + 6) = val; ROR8(val); *(ptr + 7) = val; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); for (i = 0; i < 8; i++) { ROR8(bit); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { *(ptr + 0) ^= bit; *(ptr + 1) ^= bit; *(ptr + 2) ^= bit; *(ptr + 3) ^= bit; *(ptr + 4) ^= bit; *(ptr + 5) ^= bit; *(ptr + 6) ^= bit; *(ptr + 7) ^= bit; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); } inject_random_bit_errors(buf, sz); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = (uint8_t)mwc(); bit_errors += (*(ptr + 0) != val); ROR8(val); bit_errors += (*(ptr + 1) != val); ROR8(val); bit_errors += (*(ptr + 2) != val); ROR8(val); bit_errors += (*(ptr + 3) != val); ROR8(val); bit_errors += (*(ptr + 4) != val); ROR8(val); bit_errors += (*(ptr + 5) != val); ROR8(val); bit_errors += (*(ptr + 6) != val); ROR8(val); bit_errors += (*(ptr + 7) != val); if (!opt_do_run) break; } abort: stress_vm_check("flip", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_zero_one() * set all memory to zero and see if any bits are stuck at one and * set all memory to one and see if any bits are stuck at zero */ static size_t stress_vm_zero_one( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint64_t *ptr; uint64_t *buf_end = (uint64_t *)(buf + sz); uint64_t c = *counter; size_t bit_errors = 0; (void)max_ops; memset(buf, 0x00, sz); (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); c += sz / 8; for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += 8) { bit_errors += stress_vm_count_bits(*(ptr + 0)); bit_errors += stress_vm_count_bits(*(ptr + 1)); bit_errors += stress_vm_count_bits(*(ptr + 2)); bit_errors += stress_vm_count_bits(*(ptr + 3)); bit_errors += stress_vm_count_bits(*(ptr + 4)); bit_errors += stress_vm_count_bits(*(ptr + 5)); bit_errors += stress_vm_count_bits(*(ptr + 6)); bit_errors += stress_vm_count_bits(*(ptr + 7)); if (!opt_do_run) goto abort; } memset(buf, 0xff, sz); (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); c += sz / 8; for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += 8) { bit_errors += stress_vm_count_bits(~*(ptr + 0)); bit_errors += stress_vm_count_bits(~*(ptr + 1)); bit_errors += stress_vm_count_bits(~*(ptr + 2)); bit_errors += stress_vm_count_bits(~*(ptr + 3)); bit_errors += stress_vm_count_bits(~*(ptr + 4)); bit_errors += stress_vm_count_bits(~*(ptr + 5)); bit_errors += stress_vm_count_bits(~*(ptr + 6)); bit_errors += stress_vm_count_bits(~*(ptr + 7)); if (!opt_do_run) break; } abort: stress_vm_check("zero-one", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_galpat_one() * galloping pattern. Set all bits to zero and flip a few * random bits to one. Check if this one is pulled down * or pulls its neighbours up. */ static size_t stress_vm_galpat_zero( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint64_t *ptr; uint64_t *buf_end = (uint64_t *)(buf + sz); size_t i, bit_errors = 0, bits_set = 0; size_t bits_bad = sz / 4096; uint64_t c = *counter; memset(buf, 0x00, sz); mwc_reseed(); for (i = 0; i < bits_bad; i++) { for (;;) { size_t offset = mwc() % sz; uint8_t bit = mwc() & 3; if (!buf[offset]) { buf[offset] |= (1 << bit); break; } } c++; if (max_ops && c >= max_ops) break; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += 8) { bits_set += stress_vm_count_bits(*(ptr + 0)); bits_set += stress_vm_count_bits(*(ptr + 1)); bits_set += stress_vm_count_bits(*(ptr + 2)); bits_set += stress_vm_count_bits(*(ptr + 3)); bits_set += stress_vm_count_bits(*(ptr + 4)); bits_set += stress_vm_count_bits(*(ptr + 5)); bits_set += stress_vm_count_bits(*(ptr + 6)); bits_set += stress_vm_count_bits(*(ptr + 7)); if (!opt_do_run) break; } if (bits_set != bits_bad) bit_errors += UNSIGNED_ABS(bits_set, bits_bad); stress_vm_check("galpat-zero", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_galpat_one() * galloping pattern. Set all bits to one and flip a few * random bits to zero. Check if this zero is pulled up * or pulls its neighbours down. */ static size_t stress_vm_galpat_one( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint64_t *ptr; uint64_t *buf_end = (uint64_t *)(buf + sz); size_t i, bit_errors = 0, bits_set = 0; size_t bits_bad = sz / 4096; uint64_t c = *counter; memset(buf, 0xff, sz); mwc_reseed(); for (i = 0; i < bits_bad; i++) { for (;;) { size_t offset = mwc() % sz; uint8_t bit = mwc() & 3; if (buf[offset] == 0xff) { buf[offset] &= ~(1 << bit); break; } } c++; if (max_ops && c >= max_ops) break; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += 8) { bits_set += stress_vm_count_bits(~(*(ptr + 0))); bits_set += stress_vm_count_bits(~(*(ptr + 1))); bits_set += stress_vm_count_bits(~(*(ptr + 2))); bits_set += stress_vm_count_bits(~(*(ptr + 3))); bits_set += stress_vm_count_bits(~(*(ptr + 4))); bits_set += stress_vm_count_bits(~(*(ptr + 5))); bits_set += stress_vm_count_bits(~(*(ptr + 6))); bits_set += stress_vm_count_bits(~(*(ptr + 7))); if (!opt_do_run) break; } if (bits_set != bits_bad) bit_errors += UNSIGNED_ABS(bits_set, bits_bad); stress_vm_check("galpat-one", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_inc_nybble() * work through memort and bump increment lower nybbles by * 1 and upper nybbles by 0xf and sanity check byte. */ static size_t stress_vm_inc_nybble( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static uint8_t val = 0; volatile uint8_t *ptr; uint8_t *buf_end = buf + sz; size_t bit_errors = 0; uint64_t c = *counter; memset(buf, val, sz); INC_LO_NYBBLE(val); INC_HI_NYBBLE(val); mwc_reseed(); for (ptr = buf; ptr < buf_end; ptr += 8) { INC_LO_NYBBLE(*(ptr + 0)); INC_LO_NYBBLE(*(ptr + 1)); INC_LO_NYBBLE(*(ptr + 2)); INC_LO_NYBBLE(*(ptr + 3)); INC_LO_NYBBLE(*(ptr + 4)); INC_LO_NYBBLE(*(ptr + 5)); INC_LO_NYBBLE(*(ptr + 6)); INC_LO_NYBBLE(*(ptr + 7)); c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } for (ptr = buf; ptr < buf_end; ptr += 8) { INC_HI_NYBBLE(*(ptr + 0)); INC_HI_NYBBLE(*(ptr + 1)); INC_HI_NYBBLE(*(ptr + 2)); INC_HI_NYBBLE(*(ptr + 3)); INC_HI_NYBBLE(*(ptr + 4)); INC_HI_NYBBLE(*(ptr + 5)); INC_HI_NYBBLE(*(ptr + 6)); INC_HI_NYBBLE(*(ptr + 7)); c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (ptr = buf; ptr < buf_end; ptr += 8) { bit_errors += (*(ptr + 0) != val); bit_errors += (*(ptr + 1) != val); bit_errors += (*(ptr + 2) != val); bit_errors += (*(ptr + 3) != val); bit_errors += (*(ptr + 4) != val); bit_errors += (*(ptr + 5) != val); bit_errors += (*(ptr + 6) != val); bit_errors += (*(ptr + 7) != val); if (!opt_do_run) break; } abort: stress_vm_check("inc-nybble", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_rand_sum() * sequentially set all memory to random values and then * check if they are still set correctly. */ static size_t stress_vm_rand_sum( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { const size_t chunk_sz = sizeof(uint8_t) * 8; volatile uint64_t *ptr; uint64_t *buf_end = (uint64_t *)(buf + sz); uint64_t w, z, c = *counter; size_t bit_errors = 0; mwc_reseed(); w = mwc(); z = mwc(); mwc_seed(w, z); for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += chunk_sz) { *(ptr + 0) = mwc(); *(ptr + 1) = mwc(); *(ptr + 2) = mwc(); *(ptr + 3) = mwc(); *(ptr + 4) = mwc(); *(ptr + 5) = mwc(); *(ptr + 6) = mwc(); *(ptr + 7) = mwc(); c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); mwc_seed(w, z); for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += chunk_sz) { bit_errors += stress_vm_count_bits(*(ptr + 0) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 1) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 2) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 3) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 4) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 5) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 6) ^ mwc()); bit_errors += stress_vm_count_bits(*(ptr + 7) ^ mwc()); if (!opt_do_run) break; } abort: stress_vm_check("rand-sum", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_prime_zero() * step through memory in non-contiguous large steps * and clearing each bit to one (one bit per complete memory cycle) * and check if they are clear. */ static size_t stress_vm_prime_zero( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t i; volatile uint8_t *ptr = buf; uint8_t j; size_t bit_errors = 0; const uint64_t prime = PRIME_64; uint64_t k, c = *counter; #if SIZE_MAX > UINT32_MAX /* Unlikely.. */ if (sz > (1ULL << 63)) return 0; #endif memset(buf, 0xff, sz); for (j = 0; j < 8; j++) { uint8_t mask = ~(1 << j); /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ for (i = 0, k = prime; i < sz; i++, k += prime) { ptr[k % sz] &= mask; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (i = 0; i < sz; i++) { bit_errors += stress_vm_count_bits(buf[i]); } abort: stress_vm_check("prime-zero", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_prime_one() * step through memory in non-contiguous large steps * and set each bit to one (one bit per complete memory cycle) * and check if they are set. */ static size_t stress_vm_prime_one( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t i; volatile uint8_t *ptr = buf; uint8_t j; size_t bit_errors = 0; const uint64_t prime = PRIME_64; uint64_t k, c = *counter; #if SIZE_MAX > UINT32_MAX /* Unlikely.. */ if (sz > (1ULL << 63)) return 0; #endif memset(buf, 0x00, sz); for (j = 0; j < 8; j++) { uint8_t mask = 1 << j; /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ for (i = 0, k = prime; i < sz; i++, k += prime) { ptr[k % sz] |= mask; c++; if (max_ops && c >= max_ops) goto abort; if (!opt_do_run) goto abort; } } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (i = 0; i < sz; i++) { bit_errors += 8 - stress_vm_count_bits(buf[i]); if (!opt_do_run) break; } abort: stress_vm_check("prime-one", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_prime_gray_zero() * step through memory in non-contiguous large steps * and first clear just one bit (based on gray code) and then * clear all the other bits and finally check if thay are all clear */ static size_t stress_vm_prime_gray_zero( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t i; volatile uint8_t *ptr = buf; size_t bit_errors = 0; const uint64_t prime = PRIME_64; uint64_t j, c = *counter; #if SIZE_MAX > UINT32_MAX /* Unlikely.. */ if (sz > (1ULL << 63)) return 0; #endif memset(buf, 0xff, sz); for (i = 0, j = prime; i < sz; i++, j += prime) { /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ ptr[j % sz] &= ((i >> 1) ^ i); if (!opt_do_run) goto abort; c++; if (max_ops && c >= max_ops) goto abort; } for (i = 0, j = prime; i < sz; i++, j += prime) { /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ ptr[j % sz] &= ~((i >> 1) ^ i); if (!opt_do_run) goto abort; c++; if (max_ops && c >= max_ops) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (i = 0; i < sz; i++) { bit_errors += stress_vm_count_bits(buf[i]); if (!opt_do_run) break; } abort: stress_vm_check("prime-gray-zero", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_prime_one() * step through memory in non-contiguous large steps * and first set just one bit (based on gray code) and then * set all the other bits and finally check if thay are all set */ static size_t stress_vm_prime_gray_one( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t i; volatile uint8_t *ptr = buf; size_t bit_errors = 0; const uint64_t prime = PRIME_64; uint64_t j, c = *counter; #if SIZE_MAX > UINT32_MAX /* Unlikely.. */ if (sz > (1ULL << 63)) return 0; #endif memset(buf, 0x00, sz); for (i = 0, j = prime; i < sz; i++, j += prime) { /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ ptr[j % sz] |= ((i >> 1) ^ i); if (!opt_do_run) goto abort; c++; if (max_ops && c >= max_ops) goto abort; } (void)mincore_touch_pages(buf, sz); for (i = 0, j = prime; i < sz; i++, j += prime) { /* * Step through memory in prime sized steps * in a totally sub-optimal way to exercise * memory and cache stalls */ ptr[j % sz] |= ~((i >> 1) ^ i); if (!opt_do_run) goto abort; c++; if (max_ops && c >= max_ops) goto abort; } (void)mincore_touch_pages(buf, sz); inject_random_bit_errors(buf, sz); for (i = 0; i < sz; i++) { bit_errors += 8 - stress_vm_count_bits(buf[i]); if (!opt_do_run) break; } abort: stress_vm_check("prime-gray-one", bit_errors); *counter = c; return bit_errors; } /* * stress_vm_write_64() * simple 64 bit write, no read check */ static size_t stress_vm_write64( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static uint64_t val; uint64_t *ptr = (uint64_t *)buf; register uint64_t v = val; register size_t i = 0, n = sz / (sizeof(uint64_t) * 32); while (i < n) { *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; *ptr++ = v; i++; if (!opt_do_run || (max_ops && i >= max_ops)) break; } *counter += i; val++; return 0; } /* * stress_vm_read_64() * simple 64 bit read */ static size_t stress_vm_read64( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { volatile uint64_t *ptr = (uint64_t *)buf; register size_t i = 0, n = sz / (sizeof(uint64_t) * 32); while (i < n) { (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); (void)*(ptr++); i++; if (!opt_do_run || (max_ops && i >= max_ops)) break; } *counter += i; return 0; } /* * stress_vm_all() * work through all vm stressors sequentially */ static size_t stress_vm_all( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { static int i = 1; size_t bit_errors = 0; bit_errors = vm_methods[i].func(buf, sz, counter, max_ops); i++; if (vm_methods[i].func == NULL) i = 1; return bit_errors; } static stress_vm_stressor_info_t vm_methods[] = { { "all", stress_vm_all }, { "flip", stress_vm_flip }, { "galpat-0", stress_vm_galpat_zero }, { "galpat-1", stress_vm_galpat_one }, { "gray", stress_vm_gray }, { "incdec", stress_vm_incdec }, { "inc-nybble", stress_vm_inc_nybble }, { "rand-set", stress_vm_rand_set }, { "rand-sum", stress_vm_rand_sum }, { "read64", stress_vm_read64 }, { "ror", stress_vm_ror }, { "swap", stress_vm_swap }, { "move-inv", stress_vm_moving_inversion }, { "modulo-x", stress_vm_modulo_x }, { "prime-0", stress_vm_prime_zero }, { "prime-1", stress_vm_prime_one }, { "prime-gray-0",stress_vm_prime_gray_zero }, { "prime-gray-1",stress_vm_prime_gray_one }, { "prime-incdec",stress_vm_prime_incdec }, { "walk-0d", stress_vm_walking_zero_data }, { "walk-1d", stress_vm_walking_one_data }, { "walk-0a", stress_vm_walking_zero_addr }, { "walk-1a", stress_vm_walking_one_addr }, { "write64", stress_vm_write64 }, { "zero-one", stress_vm_zero_one }, { NULL, NULL } }; /* * stress_set_vm_method() * set default vm stress method */ int stress_set_vm_method(const char *name) { stress_vm_stressor_info_t *info; for (info = vm_methods; info->func; info++) { if (!strcmp(info->name, name)) { opt_vm_stressor = info; return 0; } } fprintf(stderr, "vm-method must be one of:"); for (info = vm_methods; info->func; info++) { fprintf(stderr, " %s", info->name); } fprintf(stderr, "\n"); return -1; } /* * stress_vm() * stress virtual memory */ int stress_vm( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint32_t restarts = 0, nomems = 0; uint8_t *buf = NULL; pid_t pid; const bool keep = (opt_flags & OPT_FLAGS_VM_KEEP); const stress_vm_func func = opt_vm_stressor->func; const size_t page_size = stress_get_pagesize(); const size_t buf_sz = opt_vm_bytes & ~(page_size - 1); (void)instance; again: if (!opt_do_run) return EXIT_SUCCESS; pid = fork(); if (pid < 0) { pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; /* Parent, wait for child */ ret = waitpid(pid, &status, 0); if (ret < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n", name, errno, strerror(errno)); (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %d (instance %d)\n", name, WTERMSIG(status), instance); /* If we got killed by OOM killer, re-start */ if (WTERMSIG(status) == SIGKILL) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; goto again; } } } else if (pid == 0) { /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { if (!keep || (keep && buf == NULL)) { if (!opt_do_run) return EXIT_SUCCESS; buf = mmap(NULL, buf_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | opt_vm_flags, -1, 0); if (buf == MAP_FAILED) continue; /* Try again */ (void)madvise_random(buf, buf_sz); } (void)mincore_touch_pages(buf, buf_sz); (void)func(buf, buf_sz, counter, max_ops << VM_BOGO_SHIFT); if (opt_vm_hang == 0) { for (;;) { (void)sleep(3600); } } else if (opt_vm_hang != DEFAULT_VM_HANG) { (void)sleep((int)opt_vm_hang); } if (!keep) { (void)madvise_random(buf, buf_sz); (void)munmap(buf, buf_sz); } } while (opt_do_run && (!max_ops || *counter < max_ops)); if (keep && buf != NULL) (void)munmap(buf, buf_sz); } *counter >>= VM_BOGO_SHIFT; if (restarts + nomems > 0) pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 ", out of memory restarts: %" PRIu32 ".\n", name, restarts, nomems); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-udp.c0000664000175000017500000001167712466243156014553 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef AF_INET6 #include #endif #ifdef AF_UNIX #include #endif #include "stress-ng.h" static int opt_udp_domain = AF_INET; static int opt_udp_port = DEFAULT_SOCKET_PORT; void stress_set_udp_port(const char *optarg) { stress_set_net_port("udp-port", optarg, MIN_UDP_PORT, MAX_UDP_PORT - STRESS_PROCS_MAX, &opt_udp_port); } /* * stress_set_udp_domain() * set the udp domain option */ int stress_set_udp_domain(const char *name) { return stress_set_net_domain("udp-domain", name, &opt_udp_domain); } /* * handle_udp_sigalrm() * catch SIGALRM */ static void handle_udp_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_udp * stress by heavy udp ops */ int stress_udp( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid, ppid = getppid(); int rc = EXIT_SUCCESS; pr_dbg(stderr, "%s: process [%d] using udp port %d\n", name, getpid(), opt_udp_port + instance); pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { /* Child, client */ struct sockaddr *addr; do { char buf[UDP_BUF]; socklen_t len; int fd; int j = 0; if ((fd = socket(opt_udp_domain, SOCK_DGRAM, 0)) < 0) { pr_failed_dbg(name, "socket"); /* failed, kick parent to finish */ (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } stress_set_sockaddr(name, instance, ppid, opt_udp_domain, opt_udp_port, &addr, &len); do { size_t i; for (i = 16; i < sizeof(buf); i += 16, j++) { memset(buf, 'A' + (j % 26), sizeof(buf)); ssize_t ret = sendto(fd, buf, i, 0, addr, len); if (ret < 0) { if (errno != EINTR) pr_failed_dbg(name, "sendto"); break; } } } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); #ifdef AF_UNIX if (opt_udp_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif /* Inform parent we're all done */ (void)kill(getppid(), SIGALRM); exit(EXIT_SUCCESS); } else { /* Parent, server */ char buf[UDP_BUF]; int fd, status; int so_reuseaddr = 1; socklen_t addr_len = 0; struct sigaction new_action; struct sockaddr *addr; new_action.sa_handler = handle_udp_sigalrm; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_udp_domain, SOCK_DGRAM, 0)) < 0) { pr_failed_dbg(name, "socket"); rc = EXIT_FAILURE; goto die; } stress_set_sockaddr(name, instance, ppid, opt_udp_domain, opt_udp_port, &addr, &addr_len); if (bind(fd, addr, addr_len) < 0) { pr_failed_dbg(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_failed_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } do { socklen_t len = addr_len; ssize_t n = recvfrom(fd, buf, sizeof(buf), 0, addr, &len); if (n == 0) break; if (n < 0) { if (errno != EINTR) pr_failed_dbg(name, "recvfrom"); break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: (void)close(fd); die: #ifdef AF_UNIX if (opt_udp_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif if (pid) { (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } } return rc; } stress-ng-0.03.15/stress-dup.c0000664000175000017500000000443112466243156014541 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "stress-ng.h" /* * stress_dup() * stress system by rapid dup/close calls */ int stress_dup( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fds[STRESS_FD_MAX]; struct rlimit rlim; rlim_t i, opened = 0; (void)instance; (void)name; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) rlim.rlim_cur = STRESS_FD_MAX; /* Guess */ /* Determine max number of free file descriptors we have */ for (i = 0; i < rlim.rlim_cur; i++) { if (fcntl((int)i, F_GETFL) > -1) opened++; } rlim.rlim_cur -= opened; fds[0] = open("/dev/zero", O_RDONLY); if (fds[0] < 0) { pr_failed_dbg(name, "open on /dev/zero"); return EXIT_FAILURE; } do { for (i = 1; i < rlim.rlim_cur; i++) { fds[i] = dup(fds[0]); if (fds[i] < 0) break; if (!opt_do_run) break; (*counter)++; } for (i = 1; i < rlim.rlim_cur; i++) { if (fds[i] < 0) break; if (!opt_do_run) break; (void)close(fds[i]); } } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fds[0]); return EXIT_SUCCESS; } stress-ng-0.03.15/COPYING0000664000175000017500000004325412466243156013325 0ustar kingking GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. stress-ng-0.03.15/stress-dentry.c0000664000175000017500000001063412466243156015260 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "stress-ng.h" typedef enum { ORDER_FORWARD, ORDER_REVERSE, ORDER_STRIDE, ORDER_NONE, } dentry_order_t; typedef struct { const char *name; const dentry_order_t order; } dentry_removal_t; static dentry_removal_t dentry_removals[] = { { "forward", ORDER_FORWARD }, { "reverse", ORDER_REVERSE }, { "stride", ORDER_STRIDE }, { NULL, ORDER_NONE }, }; static dentry_order_t order = ORDER_REVERSE; static uint64_t opt_dentries = DEFAULT_DENTRIES; void stress_set_dentries(const char *optarg) { opt_dentries = get_uint64(optarg); check_range("dentries", opt_dentries, MIN_DENTRIES, MAX_DENTRIES); } /* * stress_set_dentry_order() * set dentry ordering from give option */ int stress_set_dentry_order(const char *optarg) { dentry_removal_t *dr; for (dr = dentry_removals; dr->name; dr++) { if (!strcmp(dr->name, optarg)) { order = dr->order; return 0; } } fprintf(stderr, "dentry-order must be one of:"); for (dr = dentry_removals; dr->name; dr++) { fprintf(stderr, " %s", dr->name); } fprintf(stderr, "\n"); return -1; } /* * stress_dentry_unlink() * remove all dentries */ static void stress_dentry_unlink( const char *name, const uint32_t instance, const uint64_t n) { uint64_t i, j; const pid_t pid = getpid(); const uint64_t prime = PRIME_64; switch (order) { case ORDER_REVERSE: for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t j = (n - 1) - i, gray_code = (j >> 1) ^ j; stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); (void)unlink(path); } break; case ORDER_STRIDE: for (i = 0, j = prime; i < n; i++, j += prime) { char path[PATH_MAX]; uint64_t k = j % n; uint64_t gray_code = (k >> 1) ^ k; stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); (void)unlink(path); } break; case ORDER_FORWARD: default: for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t gray_code = (i >> 1) ^ i; stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); (void)unlink(path); } break; } sync(); } /* * stress_dentry * stress dentries */ int stress_dentry( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; do { uint64_t i, n = opt_dentries; for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t gray_code = (i >> 1) ^ i; int fd; stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); if ((fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); n = i; break; } (void)close(fd); if (!opt_do_run || (max_ops && *counter >= max_ops)) goto abort; (*counter)++; } stress_dentry_unlink(name, instance, n); if (!opt_do_run) break; sync(); } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: /* force unlink of all files */ pr_tidy(stderr, "%s: removing %" PRIu64 " entries\n", name, opt_dentries); stress_dentry_unlink(name, instance, opt_dentries); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } stress-ng-0.03.15/stress-yield.c0000664000175000017500000000330612466243156015057 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #if defined(_POSIX_PRIORITY_SCHEDULING) #include #include "stress-ng.h" /* * stress on sched_yield() * stress system by sched_yield */ int stress_yield( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; do { int ret; ret = sched_yield(); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "sched_yield failed: errno=%d (%s)\n", errno, strerror(errno)); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-sendfile.c0000664000175000017500000000544212466243156015545 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #if defined (__linux__) #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static int64_t opt_sendfile_size = DEFAULT_SENDFILE_SIZE; void stress_set_sendfile_size(const char *optarg) { opt_sendfile_size = get_uint64_byte(optarg); check_range("sendfile-size", opt_sendfile_size, MIN_SENDFILE_SIZE, MAX_SENDFILE_SIZE); } /* * stress_sendfile * stress reading of a temp file and writing to /dev/null via sendfile */ int stress_sendfile( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char filename[PATH_MAX]; int fdin, fdout, ret = EXIT_SUCCESS; size_t sz = (size_t)opt_sendfile_size; const pid_t pid = getpid(); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)umask(0077); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc()); if ((fdin = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { pr_failed_err(name, "open"); ret = EXIT_FAILURE; goto dir_out; } (void)posix_fallocate(fdin, (off_t)0, (off_t)sz); if ((fdout = open("/dev/null", O_WRONLY)) < 0) { pr_failed_err(name, "open"); ret = EXIT_FAILURE; goto close_in; } do { off_t offset = 0; if (sendfile(fdout, fdin, &offset, sz) < 0) { pr_failed_err(name, "sendfile"); ret = EXIT_FAILURE; goto close_out; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); close_out: (void)close(fdout); close_in: (void)close(fdin); (void)unlink(filename); dir_out: (void)stress_temp_dir_rm(name, pid, instance); return ret; } #endif stress-ng-0.03.15/stress-ng.c0000664000175000017500000016673712466243156014377 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stress-ng.h" static proc_info_t procs[STRESS_MAX]; /* Per stressor process information */ /* Various option settings and flags */ uint64_t opt_sequential = DEFAULT_SEQUENTIAL; /* Number of sequential iterations */ static int64_t opt_backoff = DEFAULT_BACKOFF; /* child delay */ static uint32_t opt_class = 0; /* Which kind of class is specified */ uint64_t opt_timeout = 0; /* timeout in seconds */ int32_t opt_flags = PR_ERROR | PR_INFO | OPT_FLAGS_MMAP_MADVISE; volatile bool opt_do_run = true; /* false to exit stressor */ volatile bool opt_sigint = false; /* true if stopped by SIGINT */ /* Scheduler options */ static int opt_sched = UNDEFINED; /* sched policy */ static int opt_sched_priority = UNDEFINED; /* sched priority */ static int opt_ionice_class = UNDEFINED; /* ionice class */ static int opt_ionice_level = UNDEFINED; /* ionice level */ const char *app_name = "stress-ng"; /* Name of application */ shared_t *shared; /* shared memory */ /* * Attempt to catch a range of signals so * we can clean up rather than leave * cruft everywhere. */ static const int signals[] = { /* POSIX.1-1990 */ #ifdef SIGHUP SIGHUP, #endif #ifdef SIGINT SIGINT, #endif #ifdef SIGQUIT SIGQUIT, #endif #ifdef SIGABRT SIGABRT, #endif #ifdef SIGFPE SIGFPE, #endif #ifdef SIGTERM SIGTERM, #endif #ifdef SIGUSR1 SIGUSR1, #endif #ifdef SIGUSR2 SIGUSR2, /* POSIX.1-2001 */ #endif #ifdef SIGXCPU SIGXCPU, #endif #ifdef SIGXFSZ SIGXFSZ, #endif /* Linux various */ #ifdef SIGIOT SIGIOT, #endif #ifdef SIGSTKFLT SIGSTKFLT, #endif #ifdef SIGPWR SIGPWR, #endif #ifdef SIGINFO SIGINFO, #endif #ifdef SIGVTALRM SIGVTALRM, #endif -1, }; #define STRESSOR(lower_name, upper_name, class) \ { \ stress_ ## lower_name, \ STRESS_ ## upper_name, \ OPT_ ## upper_name, \ OPT_ ## upper_name ## _OPS, \ # lower_name, \ class \ } /* Human readable stress test names */ static const stress_t stressors[] = { #if defined(__linux__) STRESSOR(affinity, AFFINITY, CLASS_SCHEDULER), #endif #if defined(__linux__) STRESSOR(aio, AIO, CLASS_IO | CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(bigheap, BIGHEAP, CLASS_OS | CLASS_VM), STRESSOR(brk, BRK, CLASS_MEMORY | CLASS_OS), STRESSOR(bsearch, BSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(cache, CACHE, CLASS_CPU_CACHE), STRESSOR(chmod, CHMOD, CLASS_IO | CLASS_OS), #if _POSIX_C_SOURCE >= 199309L STRESSOR(clock, CLOCK, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(cpu, CPU, CLASS_CPU), STRESSOR(dentry, DENTRY, CLASS_IO | CLASS_OS), STRESSOR(dir, DIR, CLASS_IO | CLASS_OS), STRESSOR(dup, DUP, CLASS_IO | CLASS_OS), #if defined(__linux__) STRESSOR(epoll, EPOLL, CLASS_NETWORK | CLASS_OS), #endif #if defined(__linux__) STRESSOR(eventfd, EVENTFD, CLASS_IO | CLASS_SCHEDULER | CLASS_OS), #endif #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L STRESSOR(fallocate, FALLOCATE, CLASS_IO | CLASS_OS), #endif STRESSOR(fault, FAULT, CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS), STRESSOR(fifo, FIFO, CLASS_IO | CLASS_OS | CLASS_SCHEDULER), STRESSOR(flock, FLOCK, CLASS_IO | CLASS_OS), STRESSOR(fork, FORK, CLASS_SCHEDULER | CLASS_OS), STRESSOR(fstat, FSTAT, CLASS_IO | CLASS_OS), #if defined(__linux__) STRESSOR(futex, FUTEX, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(get, GET, CLASS_OS), STRESSOR(hdd, HDD, CLASS_IO | CLASS_OS), STRESSOR(hsearch, HSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(iosync, IOSYNC, CLASS_IO | CLASS_OS), #if defined(__linux__) STRESSOR(inotify, INOTIFY, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(kill, KILL, CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS), #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) STRESSOR(lease, LEASE, CLASS_IO | CLASS_OS), #endif STRESSOR(link, LINK, CLASS_IO | CLASS_OS), #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) STRESSOR(lockf, LOCKF, CLASS_IO | CLASS_OS), #endif STRESSOR(lsearch, LSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(malloc, MALLOC, CLASS_CPU_CACHE | CLASS_MEMORY | CLASS_OS), STRESSOR(memcpy, MEMCPY, CLASS_CPU_CACHE | CLASS_MEMORY), #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) STRESSOR(mincore, MINCORE, CLASS_OS | CLASS_MEMORY), #endif STRESSOR(mmap, MMAP, CLASS_VM | CLASS_IO | CLASS_OS), #if defined(__linux__) STRESSOR(mremap, MREMAP, CLASS_VM | CLASS_OS), #endif #if !defined(__gnu_hurd__) STRESSOR(msg, MSG, CLASS_SCHEDULER | CLASS_OS), #endif #if defined(__linux__) STRESSOR(mq, MQ, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(nice, NICE, CLASS_SCHEDULER | CLASS_OS), STRESSOR(null, NULL, CLASS_IO | CLASS_MEMORY | CLASS_OS), STRESSOR(open, OPEN, CLASS_IO | CLASS_OS), STRESSOR(pipe, PIPE, CLASS_IO | CLASS_MEMORY | CLASS_OS), STRESSOR(poll, POLL, CLASS_SCHEDULER | CLASS_OS), #if defined (__linux__) STRESSOR(procfs, PROCFS, CLASS_IO | CLASS_OS), #endif STRESSOR(pthread, PTHREAD, CLASS_SCHEDULER | CLASS_OS), STRESSOR(qsort, QSORT, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), #if defined(STRESS_X86) STRESSOR(rdrand, RDRAND, CLASS_CPU), #endif STRESSOR(rename, RENAME, CLASS_IO | CLASS_OS), STRESSOR(seek, SEEK, CLASS_IO | CLASS_OS), STRESSOR(sem_posix, SEMAPHORE_POSIX, CLASS_OS | CLASS_SCHEDULER), #if !defined(__gnu_hurd__) STRESSOR(sem_sysv, SEMAPHORE_SYSV, CLASS_OS | CLASS_SCHEDULER), #endif STRESSOR(shm_sysv, SHM_SYSV, CLASS_VM | CLASS_OS), #if defined(__linux__) STRESSOR(sendfile, SENDFILE, CLASS_IO | CLASS_OS), #endif #if defined(__linux__) STRESSOR(sigfd, SIGFD, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(sigfpe, SIGFPE, CLASS_OS), #if _POSIX_C_SOURCE >= 199309L && !defined(__gnu_hurd__) STRESSOR(sigq, SIGQUEUE, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(sigsegv, SIGSEGV, CLASS_OS), STRESSOR(socket, SOCKET, CLASS_NETWORK | CLASS_OS), #if defined(__linux__) STRESSOR(splice, SPLICE, CLASS_IO | CLASS_OS), #endif STRESSOR(stack, STACK, CLASS_CPU | CLASS_MEMORY), STRESSOR(switch, SWITCH, CLASS_SCHEDULER | CLASS_OS), STRESSOR(symlink, SYMLINK, CLASS_IO | CLASS_OS), STRESSOR(sysinfo, SYSINFO, CLASS_OS), #if defined(__linux__) STRESSOR(timer, TIMER, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(tsearch, TSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(udp, UDP, CLASS_IO | CLASS_OS), #if defined(__linux__) || defined(__gnu_hurd__) STRESSOR(urandom, URANDOM, CLASS_IO | CLASS_OS), #endif STRESSOR(utime, UTIME, CLASS_NETWORK | CLASS_OS), #if defined(STRESS_VECTOR) STRESSOR(vecmath, VECMATH, CLASS_CPU), #endif #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) STRESSOR(vfork, VFORK, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(vm, VM, CLASS_IO | CLASS_VM | CLASS_MEMORY | CLASS_OS), #if defined (__linux__) STRESSOR(vm_rw, VM_RW, CLASS_VM | CLASS_MEMORY | CLASS_OS), #endif #if defined(__linux__) STRESSOR(vm_splice, VM_SPLICE, CLASS_VM | CLASS_IO | CLASS_OS), #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) STRESSOR(wait, WAIT, CLASS_SCHEDULER | CLASS_OS), #endif #if defined (_POSIX_PRIORITY_SCHEDULING) STRESSOR(yield, YIELD, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(zero, ZERO, CLASS_IO | CLASS_MEMORY | CLASS_OS), /* Add new stress tests here */ { stress_noop, STRESS_MAX, 0, 0, NULL, 0 } }; /* Different stress classes */ static const class_t classes[] = { { CLASS_CPU, "cpu" }, { CLASS_CPU_CACHE, "cpu-cache" }, { CLASS_IO, "io" }, { CLASS_INTERRUPT, "interrupt" }, { CLASS_MEMORY, "memory" }, { CLASS_NETWORK, "network" }, { CLASS_OS, "os" }, { CLASS_SCHEDULER, "scheduler" }, { CLASS_VM, "vm" }, { 0, NULL } }; static const struct option long_options[] = { #if defined(__linux__) { "affinity", 1, 0, OPT_AFFINITY }, { "affinity-ops",1, 0, OPT_AFFINITY_OPS }, { "affinity-rand",0, 0, OPT_AFFINITY_RAND }, #endif #if defined(__linux__) { "aio", 1, 0, OPT_AIO }, { "aio-ops", 1, 0, OPT_AIO_OPS }, { "aio-requests",1, 0, OPT_AIO_REQUESTS }, #endif { "all", 1, 0, OPT_ALL }, { "backoff", 1, 0, OPT_BACKOFF }, { "bigheap", 1, 0, OPT_BIGHEAP }, { "bigheap-ops",1, 0, OPT_BIGHEAP_OPS }, { "bigheap-growth",1, 0, OPT_BIGHEAP_GROWTH }, { "brk", 1, 0, OPT_BRK }, { "brk-ops", 1, 0, OPT_BRK_OPS }, { "brk-notouch",0, 0, OPT_BRK_NOTOUCH }, { "bsearch", 1, 0, OPT_BSEARCH }, { "bsearch-ops",1, 0, OPT_BSEARCH_OPS }, { "bsearch-size",1, 0, OPT_BSEARCH_SIZE }, { "cache", 1, 0, OPT_CACHE }, { "cache-ops", 1, 0, OPT_CACHE_OPS }, { "chmod", 1, 0, OPT_CHMOD }, { "chmod-ops", 1, 0, OPT_CHMOD_OPS }, { "cache-flush",0, 0, OPT_CACHE_FLUSH }, { "cache-fence",0, 0, OPT_CACHE_FENCE }, { "class", 1, 0, OPT_CLASS }, #if _POSIX_C_SOURCE >= 199309L { "clock", 1, 0, OPT_CLOCK }, { "clock-ops", 1, 0, OPT_CLOCK_OPS }, #endif { "cpu", 1, 0, OPT_CPU }, { "cpu-ops", 1, 0, OPT_CPU_OPS }, { "cpu-load", 1, 0, OPT_CPU_LOAD }, { "cpu-method", 1, 0, OPT_CPU_METHOD }, { "dentry", 1, 0, OPT_DENTRY }, { "dentry-ops", 1, 0, OPT_DENTRY_OPS }, { "dentries", 1, 0, OPT_DENTRIES }, { "dentry-order",1, 0, OPT_DENTRY_ORDER }, { "dir", 1, 0, OPT_DIR }, { "dir-ops", 1, 0, OPT_DIR_OPS }, { "dry-run", 0, 0, OPT_DRY_RUN }, { "dup", 1, 0, OPT_DUP }, { "dup-ops", 1, 0, OPT_DUP_OPS }, #if defined (__linux__) { "epoll", 1, 0, OPT_EPOLL }, { "epoll-ops", 1, 0, OPT_EPOLL_OPS }, { "epoll-port", 1, 0, OPT_EPOLL_PORT }, { "epoll-domain",1, 0, OPT_EPOLL_DOMAIN }, #endif #if defined (__linux__) { "eventfd", 1, 0, OPT_EVENTFD }, { "eventfd-ops",1, 0, OPT_EVENTFD_OPS }, #endif #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L { "fallocate", 1, 0, OPT_FALLOCATE }, { "fallocate-ops",1, 0, OPT_FALLOCATE_OPS }, #endif { "fault", 1, 0, OPT_FAULT }, { "fault-ops", 1, 0, OPT_FAULT_OPS }, { "fifo", 1, 0, OPT_FIFO }, { "fifo-ops", 1, 0, OPT_FIFO_OPS }, { "fifo-readers",1, 0, OPT_FIFO_READERS }, { "flock", 1, 0, OPT_FLOCK }, { "flock-ops", 1, 0, OPT_FLOCK_OPS }, { "fork", 1, 0, OPT_FORK }, { "fork-ops", 1, 0, OPT_FORK_OPS }, { "fork-max", 1, 0, OPT_FORK_MAX }, { "fstat", 1, 0, OPT_FSTAT }, { "fstat-ops", 1, 0, OPT_FSTAT_OPS }, { "fstat-dir", 1, 0, OPT_FSTAT_DIR }, #if defined(__linux__) { "futex", 1, 0, OPT_FUTEX }, { "futex-ops", 1, 0, OPT_FUTEX_OPS }, #endif { "get", 1, 0, OPT_GET }, { "get-ops", 1, 0, OPT_GET_OPS }, { "hdd", 1, 0, OPT_HDD }, { "hdd-ops", 1, 0, OPT_HDD_OPS }, { "hdd-bytes", 1, 0, OPT_HDD_BYTES }, { "hdd-write-size", 1, 0, OPT_HDD_WRITE_SIZE }, { "hdd-opts", 1, 0, OPT_HDD_OPTS }, { "help", 0, 0, OPT_HELP }, { "hsearch", 1, 0, OPT_HSEARCH }, { "hsearch-ops",1, 0, OPT_HSEARCH_OPS }, { "hsearch-size",1, 0, OPT_HSEARCH_SIZE }, #if defined (__linux__) { "inotify", 1, 0, OPT_INOTIFY }, { "inotify-ops",1, 0, OPT_INOTIFY_OPS }, #endif { "io", 1, 0, OPT_IOSYNC }, { "io-ops", 1, 0, OPT_IOSYNC_OPS }, #if defined (__linux__) { "ionice-class",1, 0, OPT_IONICE_CLASS }, { "ionice-level",1, 0, OPT_IONICE_LEVEL }, #endif { "keep-name", 0, 0, OPT_KEEP_NAME }, { "kill", 1, 0, OPT_KILL }, { "kill-ops", 1, 0, OPT_KILL_OPS }, #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) { "lease", 1, 0, OPT_LEASE }, { "lease-ops", 1, 0, OPT_LEASE_OPS }, { "lease-breakers",1, 0, OPT_LEASE_BREAKERS }, #endif { "link", 1, 0, OPT_LINK }, { "link-ops", 1, 0, OPT_LINK_OPS }, #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) { "lockf", 1, 0, OPT_LOCKF }, { "lockf-ops", 1, 0, OPT_LOCKF_OPS }, { "lockf-nonblock", 0, 0, OPT_LOCKF_NONBLOCK }, #endif { "lsearch", 1, 0, OPT_LSEARCH }, { "lsearch-ops",1, 0, OPT_LSEARCH_OPS }, { "lsearch-size",1, 0, OPT_LSEARCH_SIZE }, { "malloc", 1, 0, OPT_MALLOC }, { "malloc-bytes",1, 0, OPT_MALLOC_BYTES }, { "malloc-max", 1, 0, OPT_MALLOC_MAX }, { "malloc-ops", 1, 0, OPT_MALLOC_OPS }, { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy-ops", 1, 0, OPT_MEMCPY_OPS }, { "metrics", 0, 0, OPT_METRICS }, { "metrics-brief",0, 0, OPT_METRICS_BRIEF }, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) { "mincore", 1, 0, OPT_MINCORE }, { "mincore-ops",1, 0, OPT_MINCORE_OPS }, { "mincore-random",0, 0, OPT_MINCORE_RAND }, #endif { "mmap", 1, 0, OPT_MMAP }, { "mmap-ops", 1, 0, OPT_MMAP_OPS }, { "mmap-async", 0, 0, OPT_MMAP_ASYNC }, { "mmap-bytes", 1, 0, OPT_MMAP_BYTES }, { "mmap-file", 0, 0, OPT_MMAP_FILE }, { "mmap-mprotect",0, 0, OPT_MMAP_MPROTECT }, #if defined(__linux__) { "mremap", 1, 0, OPT_MREMAP }, { "mremap-ops", 1, 0, OPT_MREMAP_OPS }, { "mremap-bytes",1, 0, OPT_MREMAP_BYTES }, #endif #if !defined(__gnu_hurd__) { "msg", 1, 0, OPT_MSG }, { "msg-ops", 1, 0, OPT_MSG_OPS }, #endif #if defined(__linux__) { "mq", 1, 0, OPT_MQ }, { "mq-ops", 1, 0, OPT_MQ_OPS }, { "mq-size", 1, 0, OPT_MQ_SIZE }, #endif { "nice", 1, 0, OPT_NICE }, { "nice-ops", 1, 0, OPT_NICE_OPS }, { "no-madvise", 0, 0, OPT_NO_MADVISE }, { "null", 1, 0, OPT_NULL }, { "null-ops", 1, 0, OPT_NULL_OPS }, { "open", 1, 0, OPT_OPEN }, { "open-ops", 1, 0, OPT_OPEN_OPS }, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) { "page-in", 0, 0, OPT_PAGE_IN }, #endif { "pipe", 1, 0, OPT_PIPE }, { "pipe-ops", 1, 0, OPT_PIPE_OPS }, { "poll", 1, 0, OPT_POLL }, { "poll-ops", 1, 0, OPT_POLL_OPS }, #if defined (__linux__) { "procfs", 1, 0, OPT_PROCFS }, { "procfs-ops", 1, 0, OPT_PROCFS_OPS }, #endif { "pthread", 1, 0, OPT_PTHREAD }, { "pthread-ops",1, 0, OPT_PTHREAD_OPS }, { "pthread-max",1, 0, OPT_PTHREAD_MAX }, { "qsort", 1, 0, OPT_QSORT }, { "qsort-ops", 1, 0, OPT_QSORT_OPS }, { "qsort-size", 1, 0, OPT_QSORT_INTEGERS }, { "quiet", 0, 0, OPT_QUIET }, { "random", 1, 0, OPT_RANDOM }, #if defined(STRESS_X86) { "rdrand", 1, 0, OPT_RDRAND }, { "rdrand-ops", 1, 0, OPT_RDRAND_OPS }, #endif { "rename", 1, 0, OPT_RENAME }, { "rename-ops", 1, 0, OPT_RENAME_OPS }, { "sched", 1, 0, OPT_SCHED }, { "sched-prio", 1, 0, OPT_SCHED_PRIO }, { "seek", 1, 0, OPT_SEEK }, { "seek-ops", 1, 0, OPT_SEEK_OPS }, { "seek-size", 1, 0, OPT_SEEK_SIZE }, { "sem", 1, 0, OPT_SEMAPHORE_POSIX }, { "sem-ops", 1, 0, OPT_SEMAPHORE_POSIX_OPS }, { "sem-procs", 1, 0, OPT_SEMAPHORE_POSIX_PROCS }, #if !defined(__gnu_hurd__) { "sem-sysv", 1, 0, OPT_SEMAPHORE_SYSV }, { "sem-sysv-ops",1, 0, OPT_SEMAPHORE_SYSV_OPS }, { "sem-sysv-procs",1, 0, OPT_SEMAPHORE_SYSV_PROCS }, #endif #if defined(__linux__) { "sendfile", 1, 0, OPT_SENDFILE }, { "sendfile-ops",1, 0, OPT_SENDFILE_OPS }, { "sendfile-size",1, 0, OPT_SENDFILE_SIZE }, #endif { "sequential", 1, 0, OPT_SEQUENTIAL }, { "shm-sysv", 1, 0, OPT_SHM_SYSV }, { "shm-sysv-ops",1, 0, OPT_SHM_SYSV_OPS }, { "shm-sysv-bytes",1, 0, OPT_SHM_SYSV_BYTES }, { "shm-sysv-segs",1, 0, OPT_SHM_SYSV_SEGMENTS }, #if defined(__linux__) { "sigfd", 1, 0, OPT_SIGFD }, { "sigfd-ops", 1, 0, OPT_SIGFD_OPS }, #endif { "sigfpe", 1, 0, OPT_SIGFPE }, { "sigfpe-ops", 1, 0, OPT_SIGFPE_OPS }, { "sigsegv", 1, 0, OPT_SIGSEGV }, { "sigsegv-ops",1, 0, OPT_SIGSEGV_OPS }, #if _POSIX_C_SOURCE >= 199309L && !defined(__gnu_hurd__) { "sigq", 1, 0, OPT_SIGQUEUE }, { "sigq-ops", 1, 0, OPT_SIGQUEUE_OPS }, #endif { "sock", 1, 0, OPT_SOCKET }, { "sock-domain",1, 0, OPT_SOCKET_DOMAIN }, { "sock-ops", 1, 0, OPT_SOCKET_OPS }, { "sock-port", 1, 0, OPT_SOCKET_PORT }, #if defined (__linux__) { "splice", 1, 0, OPT_SPLICE }, { "splice-bytes",1, 0, OPT_SPLICE_BYTES }, { "splice-ops", 1, 0, OPT_SPLICE_OPS }, #endif { "stack", 1, 0, OPT_STACK}, { "stack-ops", 1, 0, OPT_STACK_OPS }, { "switch", 1, 0, OPT_SWITCH }, { "switch-ops", 1, 0, OPT_SWITCH_OPS }, { "symlink", 1, 0, OPT_SYMLINK }, { "symlink-ops",1, 0, OPT_SYMLINK_OPS }, { "sysinfo", 1, 0, OPT_SYSINFO }, { "sysinfo-ops",1, 0, OPT_SYSINFO_OPS }, { "timeout", 1, 0, OPT_TIMEOUT }, #if defined (__linux__) { "timer", 1, 0, OPT_TIMER }, { "timer-ops", 1, 0, OPT_TIMER_OPS }, { "timer-freq", 1, 0, OPT_TIMER_FREQ }, #endif { "tsearch", 1, 0, OPT_TSEARCH }, { "tsearch-ops",1, 0, OPT_TSEARCH_OPS }, { "tsearch-size",1, 0, OPT_TSEARCH_SIZE }, { "times", 0, 0, OPT_TIMES }, { "udp", 1, 0, OPT_UDP }, { "udp-domain",1, 0, OPT_UDP_DOMAIN }, { "udp-ops", 1, 0, OPT_UDP_OPS }, { "udp-port", 1, 0, OPT_UDP_PORT }, { "utime", 1, 0, OPT_UTIME }, { "utime-ops", 1, 0, OPT_UTIME_OPS }, { "utime-fsync",0, 0, OPT_UTIME_FSYNC }, #if defined (__linux__) || defined(__gnu_hurd__) { "urandom", 1, 0, OPT_URANDOM }, { "urandom-ops",1, 0, OPT_URANDOM_OPS }, #endif #if defined(STRESS_VECTOR) { "vecmath", 1, 0, OPT_VECMATH }, { "vecmath-ops",1, 0, OPT_VECMATH_OPS }, #endif { "verbose", 0, 0, OPT_VERBOSE }, { "verify", 0, 0, OPT_VERIFY }, { "version", 0, 0, OPT_VERSION }, #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) { "vfork", 1, 0, OPT_VFORK }, { "vfork-ops", 1, 0, OPT_VFORK_OPS }, { "vfork-max", 1, 0, OPT_VFORK_MAX }, #endif { "vm", 1, 0, OPT_VM }, { "vm-bytes", 1, 0, OPT_VM_BYTES }, { "vm-hang", 1, 0, OPT_VM_HANG }, { "vm-keep", 0, 0, OPT_VM_KEEP }, #ifdef MAP_POPULATE { "vm-populate",0, 0, OPT_VM_MMAP_POPULATE }, #endif #ifdef MAP_LOCKED { "vm-locked", 0, 0, OPT_VM_MMAP_LOCKED }, #endif { "vm-ops", 1, 0, OPT_VM_OPS }, { "vm-method", 1, 0, OPT_VM_METHOD }, #if defined (__linux__) { "vm-rw", 1, 0, OPT_VM_RW }, { "vm-rw-bytes",1, 0, OPT_VM_RW_BYTES }, { "vm-rw-ops", 1, 0, OPT_VM_RW_OPS }, #endif #if defined (__linux__) { "vm-splice", 1, 0, OPT_VM_SPLICE }, { "vm-splice-bytes",1, 0, OPT_VM_SPLICE_BYTES }, { "vm-splice-ops",1, 0, OPT_VM_SPLICE_OPS }, #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) { "wait", 1, 0, OPT_WAIT }, { "wait-ops", 1, 0, OPT_WAIT_OPS }, #endif #if defined (_POSIX_PRIORITY_SCHEDULING) { "yield", 1, 0, OPT_YIELD }, { "yield-ops", 1, 0, OPT_YIELD_OPS }, #endif { "zero", 1, 0, OPT_ZERO }, { "zero-ops", 1, 0, OPT_ZERO_OPS }, { NULL, 0, 0, 0 } }; static const help_t help[] = { { "-h", "help", "show help" }, #if defined (__linux__) { NULL, "affinity N", "start N workers that rapidly change CPU affinity" }, { NULL, "affinity-ops N", "stop when N affinity bogo operations completed" }, { NULL, "affinity-rand", "change affinity randomly rather than sequentially" }, #endif #if defined (__linux__) { NULL, "aio N", "start N workers that issue async I/O requests" }, { NULL, "aio-ops N", "stop when N bogo async I/O requests completed" }, { NULL, "aio-requests N", "number of async I/O requests per worker" }, #endif { "a N", "all N", "start N workers of each stress test" }, { "b N", "backoff N", "wait of N microseconds before work starts" }, { "B N", "bigheap N", "start N workers that grow the heap using calloc()" }, { NULL, "bigheap-ops N", "stop when N bogo bigheap operations completed" }, { NULL, "bigheap-growth N", "grow heap by N bytes per iteration" }, { NULL, "brk N", "start N workers performing rapid brk calls" }, { NULL, "brk-ops N", "stop when N brk bogo operations completed" }, { NULL, "brk-notouch", "don't touch (page in) new data segment page" }, { NULL, "bsearch", "start N workers that exercise a binary search" }, { NULL, "bsearch-ops", "stop when N binary search bogo operations completed" }, { NULL, "bsearch-size", "number of 32 bit integers to bsearch" }, { "C N", "cache N", "start N CPU cache thrashing workers" }, { NULL, "cache-ops N", "stop when N cache bogo operations completed (x86 only)" }, { NULL, "cache-flush", "flush cache after every memory write (x86 only)" }, { NULL, "cache-fence", "serialize stores" }, { NULL, "class name", "specify a class of stressors, use with --sequential" }, { NULL, "chmod N", "start N workers thrashing chmod file mode bits " }, { NULL, "chmod-ops N", "stop chmod workers after N bogo operations" }, #if _POSIX_C_SOURCE >= 199309L { NULL, "clock N", "start N workers thrashing clocks and POSIX timers" }, { NULL, "clock-ops N", "stop clock workers after N bogo operations" }, #endif { "c N", "cpu N", "start N workers spinning on sqrt(rand())" }, { NULL, "cpu-ops N", "stop when N cpu bogo operations completed" }, { "l P", "cpu-load P", "load CPU by P %%, 0=sleep, 100=full load (see -c)" }, { NULL, "cpu-method m", "specify stress cpu method m, default is all" }, { "D N", "dentry N", "start N dentry thrashing stressors" }, { NULL, "dentry-ops N", "stop when N dentry bogo operations completed" }, { NULL, "dentry-order O", "specify dentry unlink order (reverse, forward, stride)" }, { NULL, "dentries N", "create N dentries per iteration" }, { NULL, "dir N", "start N directory thrashing stressors" }, { NULL, "dir-ops N", "stop when N directory bogo operations completed" }, { "n", "dry-run", "do not run" }, { NULL, "dup N", "start N workers exercising dup/close" }, { NULL, "dup-ops N", "stop when N dup/close bogo operations completed" }, #if defined (__linux__) { NULL, "epoll N", "start N workers doing epoll handled socket activity" }, { NULL, "epoll-ops N", "stop when N epoll bogo operations completed" }, { NULL, "epoll-port P", "use socket ports P upwards" }, { NULL, "epoll-domain D", "specify socket domain, default is unix" }, #endif #if defined (__linux__) { NULL, "eventfd N", "start N workers stressing eventfd read/writes" }, { NULL, "eventfd-ops N", "stop eventfd workers after N bogo operations" }, #endif #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L { NULL, "fallocate N", "start N workers fallocating 16MB files" }, { NULL, "fallocate-ops N", "stop when N fallocate bogo operations completed" }, #endif { NULL, "fault N", "start N workers producing page faults" }, { NULL, "fault-ops N", "stop when N page fault bogo operations completed" }, { NULL, "fifo N", "start N workers exercising fifo I/O" }, { NULL, "fifo-ops N", "stop when N fifo bogo operations completed" }, { NULL, "fifo-readers N", "number of fifo reader stessors to start" }, { NULL, "flock N", "start N workers locking a single file" }, { NULL, "flock-ops N", "stop when N flock bogo operations completed" }, { "f N", "fork N", "start N workers spinning on fork() and exit()" }, { NULL, "fork-ops N", "stop when N fork bogo operations completed" }, { NULL, "fork-max P", "create P processes per iteration, default is 1" }, { NULL, "fstat N", "start N workers exercising fstat on files" }, { NULL, "fstat-ops N", "stop when N fstat bogo operations completed" }, { NULL, "fstat-dir path", "fstat files in the specified directory" }, #if defined (__linux__) { NULL, "futex N", "start N workers exercising a fast mutex" }, { NULL, "futex-ops N", "stop when N fast mutex bogo operations completed" }, #endif { NULL, "get N", "start N workers exercising the get*() system calls" }, { NULL, "get-ops N", "stop when N get bogo operations completed" }, { "d N", "hdd N", "start N workers spinning on write()/unlink()" }, { NULL, "hdd-ops N", "stop when N hdd bogo operations completed" }, { NULL, "hdd-bytes N", "write N bytes per hdd worker (default is 1GB)" }, { NULL, "hdd-opts list", "specify list of various stressor options" }, { NULL, "hdd-write-size N", "set the default write size to N bytes" }, { NULL, "hsearch", "start N workers that exercise a hash table search" }, { NULL, "hsearch-ops", "stop when N hash search bogo operations completed" }, { NULL, "hsearch-size", "number of integers to insert into hash table" }, #if defined (__linux__) { NULL, "inotify N", "start N workers exercising inotify events" }, { NULL, "inotify-ops N", "stop inotify workers after N bogo operations" }, #endif { "i N", "io N", "start N workers spinning on sync()" }, { NULL, "io-ops N", "stop when N io bogo operations completed" }, #if defined (__linux__) { NULL, "ionice-class C", "specify ionice class (idle, besteffort, realtime)" }, { NULL, "ionice-level L", "specify ionice level (0 max, 7 min)" }, #endif { "k", "keep-name", "keep stress process names to be 'stress-ng'" }, { NULL, "kill N", "start N workers killing with SIGUSR1" }, { NULL, "kill-ops N", "stop when N kill bogo operations completed" }, #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) { NULL, "lease N", "start N workers holding and breaking a lease" }, { NULL, "lease-ops N", "stop when N lease bogo operations completed" }, { NULL, "lease-breakers N", "number of lease breaking processes to start" }, #endif { NULL, "link N", "start N workers creating hard links" }, { NULL, "link-ops N", "stop when N link bogo operations completed" }, #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) { NULL, "lockf N", "start N workers locking a single file via lockf" }, { NULL, "lockf-ops N", "stop when N lockf bogo operations completed" }, { NULL, "lockf-nonblock", "don't block if lock cannot be obtained, re-try" }, #endif { NULL, "lsearch", "start N workers that exercise a linear search" }, { NULL, "lsearch-ops", "stop when N linear search bogo operations completed" }, { NULL, "lsearch-size", "number of 32 bit integers to lsearch" }, { NULL, "malloc N", "start N workers exercising malloc/realloc/free" }, { NULL, "malloc-bytes N", "allocate up to N bytes per allocation" }, { NULL, "malloc-max N", "keep up to N allocations at a time" }, { NULL, "malloc-ops N", "stop when N malloc bogo operations completed" }, { "M", "metrics", "print pseudo metrics of activity" }, { NULL, "metrics-brief", "enable metrics and only show non-zero results" }, { NULL, "memcpy N", "start N workers performing memory copies" }, { NULL, "memcpy-ops N", "stop when N memcpy bogo operations completed" }, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) { NULL, "mincore N", "start N workers exercising mincore" }, { NULL, "mincore-ops N", "stop when N mimcore bogo operations completed" }, { NULL, "mincore-random", "randomly select pages rather than linear scan" }, #endif { NULL, "mmap N", "start N workers stressing mmap and munmap" }, { NULL, "mmap-ops N", "stop when N mmap bogo operations completed" }, { NULL, "mmap-async", "using asynchronous msyncs for file based mmap" }, { NULL, "mmap-bytes N", "mmap and munmap N bytes for each stress iteration" }, { NULL, "mmap-file", "mmap onto a file using synchronous msyncs" }, { NULL, "mmap-mprotect", "enable mmap mprotect stressing" }, #if defined(__linux__) { NULL, "mremap N", "start N workers stressing mremap" }, { NULL, "mremap-ops N", "stop when N mremap bogo operations completed" }, { NULL, "mremap-bytes N", "mremap N bytes maximum for each stress iteration" }, #endif { NULL, "msg N", "start N workers passing messages using System V messages" }, { NULL, "msg-ops N", "stop msg workers after N bogo messages completed" }, #if defined(__linux__) { NULL, "mq N", "start N workers passing messages using POSIX messages" }, { NULL, "mq-ops N", "stop mq workers after N bogo messages completed" }, { NULL, "mq-size N", "specify the size of the POSIX message queue" }, #endif { NULL, "nice N", "start N workers that randomly re-adjust nice levels" }, { NULL, "nice-ops N", "stop when N nice bogo operations completed" }, { NULL, "no-madvise", "don't use random madvise options for each mmap" }, { NULL, "null N", "start N workers writing to /dev/null" }, { NULL, "null-ops N", "stop when N /dev/null bogo write operations completed" }, { "o", "open N", "start N workers exercising open/close" }, { NULL, "open-ops N", "stop when N open/close bogo operations completed" }, #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) { NULL, "page-in", "touch allocated pages that are not in core" }, #endif { "p N", "pipe N", "start N workers exercising pipe I/O" }, { NULL, "pipe-ops N", "stop when N pipe I/O bogo operations completed" }, { "P N", "poll N", "start N workers exercising zero timeout polling" }, { NULL, "poll-ops N", "stop when N poll bogo operations completed" }, #if defined (__linux__) { NULL, "procfs N", "start N workers reading portions of /proc" }, { NULL, "procfs-ops N", "stop procfs workers after N bogo read operations" }, #endif { NULL, "pthread N", "start N workers that create multiple threads" }, { NULL, "pthread-ops N", "stop pthread workers after N bogo threads created" }, { NULL, "pthread-max P", "create P threads at a time by each worker" }, { "Q", "qsort N", "start N workers exercising qsort on 32 bit random integers" }, { NULL, "qsort-ops N", "stop when N qsort bogo operations completed" }, { NULL, "qsort-size N", "number of 32 bit integers to sort" }, { "q", "quiet", "quiet output" }, { "r", "random N", "start N random workers" }, #if defined(STRESS_X86) { NULL, "rdrand N", "start N workers exercising rdrand instruction (x86 only)" }, { NULL, "rdrand-ops N", "stop when N rdrand bogo operations completed" }, #endif { "R", "rename N", "start N workers exercising file renames" }, { NULL, "rename-ops N", "stop when N rename bogo operations completed" }, { NULL, "sched type", "set scheduler type" }, { NULL, "sched-prio N", "set scheduler priority level N" }, { NULL, "seek N", "start N workers performing random seek r/w IO" }, { NULL, "seek-ops N", "stop when N seek bogo operations completed" }, { NULL, "seek-size N", "length of file to do random I/O upon" }, { NULL, "sem N", "start N workers doing semaphore operations" }, { NULL, "sem-ops N", "stop when N semaphore bogo operations completed" }, { NULL, "sem-procs N", "number of processes to start per worker" }, #if !defined(__gnu_hurd__) { NULL, "sem-sysv N", "start N workers doing System V semaphore operations" }, { NULL, "sem-sysv-ops N", "stop when N System V semaphore bogo operations completed" }, { NULL, "sem-sysv-procs N", "number of processes to start per worker" }, #endif #if defined (__linux__) { NULL, "sendfile N", "start N workers exercising sendfile" }, { NULL, "sendfile-ops N", "stop after N bogo sendfile operations" }, { NULL, "sendfile-size N", "size of data to be sent with sendfile" }, #endif { NULL, "sequential N", "run all stressors one by one, invoking N of them" }, { NULL, "shm-sysv N", "start N workers that exercise System V shared memory" }, { NULL, "shm-sysv-ops N", "stop after N shared memory bogo operations" }, { NULL, "shm-sysv-bytes N", "allocate and free N bytes of shared memory per iteration" }, { NULL, "shm-sysv-segs N", "allocate N shared memory segments per iteration" }, #if defined (__linux__) { NULL, "sigfd N", "start N workers reading signals via signalfd reads " }, { NULL, "sigfd-ops N", "stop when N bogo signalfd reads completed" }, #endif { NULL, "sigfpe N", "start N workers generating floating point math faults" }, { NULL, "sigfpe-ops N", "stop when N bogo floating point math faults completed" }, #if _POSIX_C_SOURCE >= 199309L { NULL, "sigq N", "start N workers sending sigqueue signals" }, { NULL, "sigq-ops N", "stop when N siqqueue bogo operations completed" }, #endif { NULL, "sigsegv N", "start N workers generating segmentation faults" }, { NULL, "sigsegv-ops N", "stop when N bogo segmentation faults completed" }, { "S N", "sock N", "start N workers doing socket activity" }, { NULL, "sock-ops N", "stop when N socket bogo operations completed" }, { NULL, "sock-port P", "use socket ports P to P + number of workers - 1" }, { NULL, "sock-domain D", "specify socket domain, default is ipv4" }, #if defined (__linux__) { NULL, "splice N", "start N workers reading/writing using splice" }, { NULL, "splice-ops N", "stop when N bogo splice operations completed" }, { NULL, "splice-bytes N", "number of bytes to transfer per splice call" }, #endif { NULL, "stack N", "start N workers generating stack overflows" }, { NULL, "stack-ops N", "stop when N bogo stack overflows completed" }, { "s N", "switch N", "start N workers doing rapid context switches" }, { NULL, "switch-ops N", "stop when N context switch bogo operations completed" }, { NULL, "symlink N", "start N workers creating symbolic links" }, { NULL, "symlink-ops N", "stop when N symbolic link bogo operations completed" }, { NULL, "sysinfo N", "start N workers reading system information" }, { NULL, "sysinfo-ops N", "stop when sysinfo bogo operations completed" }, { "t N", "timeout N", "timeout after N seconds" }, #if defined (__linux__) { "T N", "timer N", "start N workers producing timer events" }, { NULL, "timer-ops N", "stop when N timer bogo events completed" }, { NULL, "timer-freq F", "run timer(s) at F Hz, range 1000 to 1000000000" }, #endif { NULL, "tsearch", "start N workers that exercise a tree search" }, { NULL, "tsearch-ops", "stop when N tree search bogo operations completed" }, { NULL, "tsearch-size", "number of 32 bit integers to tsearch" }, { NULL, "times", "show run time summary at end of the run" }, { NULL, "udp N", "start N workers performing UDP send/receives " }, { NULL, "udp-ops N", "stop when N udp bogo operations completed" }, { NULL, "udp-port P", "use ports P to P + number of workers - 1" }, { NULL, "udo-domain D", "specify domain, default is ipv4" }, #if defined(__linux__) || defined(__gnu_hurd__) { "u N", "urandom N", "start N workers reading /dev/urandom" }, { NULL, "urandom-ops N", "stop when N urandom bogo read operations completed" }, #endif { NULL, "utime N", "start N workers updating file timestamps" }, { NULL, "utime-ops N", "stop after N utime bogo operations completed" }, { NULL, "utime-fsync", "force utime meta data sync to the file system" }, #if defined(STRESS_VECTOR) { NULL, "vecmath N", "start N workers performing vector math ops" }, { NULL, "vecmath-ops N", "stop after N vector math bogo operations completed" }, #endif { "v", "verbose", "verbose output" }, { NULL, "verify", "verify results (not available on all tests)" }, { "V", "version", "show version" }, #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) { NULL, "vfork N", "start N workers spinning on vfork() and exit()" }, { NULL, "vfork-ops N", "stop when N vfork bogo operations completed" }, { NULL, "vfork-max P", "create P processes per iteration, default is 1" }, #endif { "m N", "vm N", "start N workers spinning on anonymous mmap" }, { NULL, "vm-bytes N", "allocate N bytes per vm worker (default 256MB)" }, { NULL, "vm-hang N", "sleep N seconds before freeing memory" }, { NULL, "vm-keep", "redirty memory instead of reallocating" }, { NULL, "vm-ops N", "stop when N vm bogo operations completed" }, #ifdef MAP_LOCKED { NULL, "vm-locked", "lock the pages of the mapped region into memory" }, #endif { NULL, "vm-method m", "specify stress vm method m, default is all" }, #ifdef MAP_POPULATE { NULL, "vm-populate", "populate (prefault) page tables for a mapping" }, #endif #if defined (__linux__) { NULL, "vm-rw N", "start N vm read/write process_vm* copy workers" }, { NULL, "vm-rw-bytes N", "transfer N bytes of memory per bogo operation" }, { NULL, "vm-rw-ops N", "stop after N vm process_vm* copy bogo operations" }, #endif #if defined (__linux__) { NULL, "vm-splice N", "start N workers reading/writing using vmsplice" }, { NULL, "vm-splice-ops N", "stop when N bogo splice operations completed" }, { NULL, "vm-splice-bytes N", "number of bytes to transfer per vmsplice call" }, #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) { NULL, "wait N", "start N workers waiting on child being stop/resumed" }, { NULL, "wait-ops N", "stop when N bogo wait operations completed" }, #endif #if defined(_POSIX_PRIORITY_SCHEDULING) { "y N", "yield N", "start N workers doing sched_yield() calls" }, { NULL, "yield-ops N", "stop when N bogo yield operations completed" }, #endif { NULL, "zero N", "start N workers reading /dev/zero" }, { NULL, "zero-ops N", "stop when N /dev/zero bogo read operations completed" }, { NULL, NULL, NULL } }; /* * stressor_id_find() * Find index into stressors by id */ static inline int stressor_id_find(const stress_id id) { int i; for (i = 0; stressors[i].name; i++) if (stressors[i].id == id) break; return i; /* End of array is a special "NULL" entry */ } static uint32_t get_class(const char *str) { int i; for (i = 0; classes[i].class; i++) if (!strcmp(classes[i].name, str)) return classes[i].class; return 0; } /* * Catch signals and set flag to break out of stress loops */ static void stress_sigint_handler(int dummy) { (void)dummy; opt_sigint = true; opt_do_run = false; } static void stress_sigalrm_handler(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_sethandler() * set signal handler to catch SIGINT and SIGALRM */ static int stress_sethandler(const char *stress) { struct sigaction new_action; new_action.sa_handler = stress_sigint_handler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGINT, &new_action, NULL) < 0) { pr_failed_err(stress, "sigaction"); return -1; } new_action.sa_handler = stress_sigalrm_handler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_failed_err(stress, "sigaction"); return -1; } return 0; } /* * version() * print program version info */ static void version(void) { printf("%s, version " VERSION "\n", app_name); } /* * usage() * print some help */ static void usage(void) { int i; version(); printf( "\nUsage: %s [OPTION [ARG]]\n", app_name); for (i = 0; help[i].description; i++) { char opt_s[10] = ""; if (help[i].opt_s) snprintf(opt_s, sizeof(opt_s), "-%s,", help[i].opt_s); printf(" %-6s--%-17s%s\n", opt_s, help[i].opt_l, help[i].description); } printf("\nExample: %s --cpu 8 --io 4 --vm 2 --vm-bytes 128M --fork 4 --timeout 10s\n\n" "Note: Sizes can be suffixed with B,K,M,G and times with s,m,h,d,y\n", app_name); exit(EXIT_SUCCESS); } /* * opt_name() * find name associated with an option value */ static const char *opt_name(int opt_val) { int i; for (i = 0; long_options[i].name; i++) if (long_options[i].val == opt_val) return long_options[i].name; return ""; } /* * proc_finished() * mark a process as complete */ static inline void proc_finished(pid_t *pid) { *pid = 0; } /* * kill_procs() * kill tasks using signal */ static void kill_procs(int sig) { static int count = 0; int i; /* multiple calls will always fallback to SIGKILL */ count++; if (count > 5) sig = SIGKILL; for (i = 0; i < STRESS_MAX; i++) { int j; for (j = 0; j < procs[i].started_procs; j++) { if (procs[i].pids[j]) (void)kill(procs[i].pids[j], sig); } } } /* * wait_procs() * wait for procs */ static void wait_procs(bool *success) { int i; for (i = 0; i < STRESS_MAX; i++) { int j; for (j = 0; j < procs[i].started_procs; j++) { pid_t pid; redo: pid = procs[i].pids[j]; if (pid) { int status, ret; ret = waitpid(pid, &status, 0); if (ret > 0) { if (WEXITSTATUS(status)) { pr_err(stderr, "Process %d terminated with an error, exit status=%d\n", ret, WEXITSTATUS(status)); *success = false; } proc_finished(&procs[i].pids[j]); pr_dbg(stderr, "process [%d] terminated\n", ret); } else if (ret == -1) { /* Somebody interrupted the wait */ if (errno == EINTR) goto redo; /* This child did not exist, mark it done anyhow */ if (errno == ECHILD) proc_finished(&procs[i].pids[j]); } } } } } /* * handle_sigint() * catch SIGINT */ static void handle_sigint(int dummy) { (void)dummy; opt_do_run = false; kill_procs(SIGALRM); } /* * opt_long() * parse long int option, check for invalid values */ long int opt_long(const char *opt, const char *str) { long int val; char c; bool found = false; for (c = '0'; c <= '9'; c++) { if (strchr(str, c)) { found = true; break; } } if (!found) { fprintf(stderr, "Given value %s is not a valid decimal for the %s option\n", str, opt); exit(EXIT_FAILURE); } errno = 0; val = strtol(str, NULL, 10); if (errno) { fprintf(stderr, "Invalid value for the %s option\n", opt); exit(EXIT_FAILURE); } return val; } /* * free_procs() * free proc info in procs table */ static void free_procs(void) { int32_t i; for (i = 0; i < STRESS_MAX; i++) free(procs[i].pids); } /* * stress_run () * kick off and run stressors */ void stress_run( const int total_procs, const int32_t max_procs, proc_stats_t stats[], double *duration, bool *success ) { double time_start, time_finish; int32_t n_procs, i, j, n; time_start = time_now(); pr_dbg(stderr, "starting stressors\n"); for (n_procs = 0; n_procs < total_procs; n_procs++) { for (i = 0; i < STRESS_MAX; i++) { if (time_now() - time_start > opt_timeout) goto abort; j = procs[i].started_procs; if (j < procs[i].num_procs) { int rc = EXIT_SUCCESS; int pid = fork(); char name[64]; switch (pid) { case -1: pr_err(stderr, "Cannot fork: errno=%d (%s)\n", errno, strerror(errno)); kill_procs(SIGALRM); goto wait_for_procs; case 0: /* Child */ free_procs(); if (stress_sethandler(name) < 0) exit(EXIT_FAILURE); (void)alarm(opt_timeout); mwc_reseed(); set_oom_adjustment(name, false); set_coredump(name); set_max_limits(); snprintf(name, sizeof(name), "%s-%s", app_name, munge_underscore((char *)stressors[i].name)); set_iopriority(opt_ionice_class, opt_ionice_level); set_proc_name(name); pr_dbg(stderr, "%s: started [%d] (instance %" PRIu32 ")\n", name, getpid(), j); n = (i * max_procs) + j; stats[n].start = stats[n].finish = time_now(); (void)usleep(opt_backoff * n_procs); if (opt_do_run && !(opt_flags & OPT_FLAGS_DRY_RUN)) rc = stressors[i].stress_func(&stats[n].counter, j, procs[i].bogo_ops, name); stats[n].finish = time_now(); if (times(&stats[n].tms) == (clock_t)-1) { pr_dbg(stderr, "times failed: errno=%d (%s)\n", errno, strerror(errno)); } pr_dbg(stderr, "%s: exited [%d] (instance %" PRIu32 ")\n", name, getpid(), j); exit(rc); default: procs[i].pids[j] = pid; procs[i].started_procs++; /* Forced early abort during startup? */ if (!opt_do_run) { pr_dbg(stderr, "abort signal during startup, cleaning up\n"); kill_procs(SIGALRM); goto wait_for_procs; } break; } } } } abort: pr_dbg(stderr, "%d stressors running\n", n_procs); wait_for_procs: wait_procs(success); time_finish = time_now(); *duration += time_finish - time_start; } int main(int argc, char **argv) { double duration = 0.0; int32_t val, opt_random = 0, i, j; int32_t total_procs = 0, max_procs = 0; size_t len; bool success = true, previous = false; struct sigaction new_action; long int ticks_per_sec; struct rlimit limit; int id; memset(procs, 0, sizeof(procs)); mwc_reseed(); (void)stress_get_pagesize(); (void)stress_set_cpu_method("all"); (void)stress_set_vm_method("all"); if (stress_get_processors_online() < 0) { pr_err(stderr, "sysconf failed, number of cpus online unknown: errno=%d: (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } ticks_per_sec = stress_get_ticks_per_second(); if (ticks_per_sec < 0) { pr_err(stderr, "sysconf failed, clock ticks per second unknown: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } for (;;) { int c, option_index; stress_id id; next_opt: if ((c = getopt_long(argc, argv, "?hMVvqnt:b:c:i:m:d:f:s:l:p:P:C:S:a:y:F:D:T:u:o:r:B:R:k", long_options, &option_index)) == -1) break; for (id = 0; stressors[id].id != STRESS_MAX; id++) { if (stressors[id].short_getopt == c) { const char *name = opt_name(c); opt_flags |= OPT_FLAGS_SET; procs[id].num_procs = opt_long(name, optarg); if (procs[id].num_procs <= 0) procs[id].num_procs = stress_get_processors_online(); check_value(name, procs[id].num_procs); goto next_opt; } if (stressors[id].op == (stress_op)c) { procs[id].bogo_ops = get_uint64(optarg); check_range(opt_name(c), procs[id].bogo_ops, MIN_OPS, MAX_OPS); goto next_opt; } } switch (c) { #if defined(__linux__) case OPT_AIO_REQUESTS: stress_set_aio_requests(optarg); break; #endif case OPT_ALL: opt_flags |= OPT_FLAGS_SET; val = opt_long("-a", optarg); if (val <= 0) val = stress_get_processors_online(); check_value("all", val); for (i = 0; i < STRESS_MAX; i++) procs[i].num_procs = val; break; #if defined(__linux__) case OPT_AFFINITY_RAND: opt_flags |= OPT_FLAGS_AFFINITY_RAND; break; #endif case OPT_BACKOFF: opt_backoff = opt_long("backoff", optarg); break; case OPT_BIGHEAP_GROWTH: stress_set_bigheap_growth(optarg); break; case OPT_BRK_NOTOUCH: opt_flags |= OPT_FLAGS_BRK_NOTOUCH; break; case OPT_BSEARCH_SIZE: stress_set_bsearch_size(optarg); break; case OPT_CACHE_FLUSH: opt_flags |= OPT_FLAGS_CACHE_FLUSH; break; case OPT_CACHE_FENCE: opt_flags |= OPT_FLAGS_CACHE_FENCE; break; case OPT_CLASS: opt_class = get_class(optarg); if (!opt_class) { int i; fprintf(stderr, "Unknown class: '%s', available classes:", optarg); for (i = 0; classes[i].class; i++) fprintf(stderr, " %s", classes[i].name); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } break; case OPT_CPU_LOAD: stress_set_cpu_load(optarg); break; case OPT_CPU_METHOD: if (stress_set_cpu_method(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_DRY_RUN: opt_flags |= OPT_FLAGS_DRY_RUN; break; case OPT_DENTRIES: stress_set_dentries(optarg); break; case OPT_DENTRY_ORDER: if (stress_set_dentry_order(optarg) < 0) exit(EXIT_FAILURE); break; #if defined (__linux__) case OPT_EPOLL_DOMAIN: if (stress_set_epoll_domain(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_EPOLL_PORT: stress_set_epoll_port(optarg); break; #endif case OPT_FIFO_READERS: stress_set_fifo_readers(optarg); break; case OPT_FORK_MAX: stress_set_fork_max(optarg); break; case OPT_FSTAT_DIR: stress_set_fstat_dir(optarg); break; case OPT_HELP: usage(); break; case OPT_HDD_BYTES: stress_set_hdd_bytes(optarg); break; case OPT_HDD_OPTS: if (stress_hdd_opts(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_HDD_WRITE_SIZE: stress_set_hdd_write_size(optarg); break; case OPT_HSEARCH_SIZE: stress_set_hsearch_size(optarg); break; #if defined (__linux__) case OPT_IONICE_CLASS: opt_ionice_class = get_opt_ionice_class(optarg); break; case OPT_IONICE_LEVEL: opt_ionice_level = get_int(optarg); break; #endif case OPT_KEEP_NAME: opt_flags |= OPT_FLAGS_KEEP_NAME; break; #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) case OPT_LEASE_BREAKERS: stress_set_lease_breakers(optarg); break; #endif #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) case OPT_LOCKF_NONBLOCK: opt_flags |= OPT_FLAGS_LOCKF_NONBLK; break; #endif case OPT_LSEARCH_SIZE: stress_set_lsearch_size(optarg); break; case OPT_MALLOC_BYTES: stress_set_malloc_bytes(optarg); break; case OPT_MALLOC_MAX: stress_set_malloc_max(optarg); break; case OPT_METRICS: opt_flags |= OPT_FLAGS_METRICS; break; case OPT_METRICS_BRIEF: opt_flags |= (OPT_FLAGS_METRICS_BRIEF | OPT_FLAGS_METRICS); break; #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) case OPT_MINCORE_RAND: opt_flags |= OPT_FLAGS_MINCORE_RAND; break; #endif case OPT_MMAP_ASYNC: opt_flags |= (OPT_FLAGS_MMAP_FILE | OPT_FLAGS_MMAP_ASYNC); break; case OPT_MMAP_BYTES: stress_set_mmap_bytes(optarg); break; case OPT_MMAP_FILE: opt_flags |= OPT_FLAGS_MMAP_FILE; break; case OPT_MMAP_MPROTECT: opt_flags |= OPT_FLAGS_MMAP_MPROTECT; break; #if defined(__linux__) case OPT_MREMAP_BYTES: stress_set_mremap_bytes(optarg); break; #endif #if defined(__linux__) case OPT_MQ_SIZE: stress_set_mq_size(optarg); break; #endif case OPT_NO_MADVISE: opt_flags &= ~OPT_FLAGS_MMAP_MADVISE; break; #if (_BSD_SOURCE || _SVID_SOURCE) && !defined(__gnu_hurd__) case OPT_PAGE_IN: opt_flags |= OPT_FLAGS_MMAP_MINCORE; break; #endif case OPT_PTHREAD_MAX: stress_set_pthread_max(optarg); break; case OPT_QSORT_INTEGERS: stress_set_qsort_size(optarg); break; case OPT_QUERY: printf("Try '%s --help' for more information.\n", app_name); exit(EXIT_FAILURE); break; case OPT_QUIET: opt_flags &= ~(PR_ALL); break; case OPT_RANDOM: opt_flags |= OPT_FLAGS_RANDOM; opt_random = opt_long("-r", optarg); check_value("random", opt_random); break; case OPT_SCHED: opt_sched = get_opt_sched(optarg); break; case OPT_SCHED_PRIO: opt_sched_priority = get_int(optarg); break; case OPT_SEEK_SIZE: stress_set_seek_size(optarg); break; case OPT_SEMAPHORE_POSIX_PROCS: stress_set_semaphore_posix_procs(optarg); break; #if !defined(__gnu_hurd__) case OPT_SEMAPHORE_SYSV_PROCS: stress_set_semaphore_sysv_procs(optarg); break; #endif #if defined (__linux__) case OPT_SENDFILE_SIZE: stress_set_sendfile_size(optarg); break; #endif case OPT_SEQUENTIAL: opt_sequential = get_uint64_byte(optarg); if (opt_sequential <= 0) opt_sequential = stress_get_processors_online(); check_range("sequential", opt_sequential, MIN_SEQUENTIAL, MAX_SEQUENTIAL); break; case OPT_SHM_SYSV_BYTES: stress_set_shm_sysv_bytes(optarg); break; case OPT_SHM_SYSV_SEGMENTS: stress_set_shm_sysv_segments(optarg); break; case OPT_SOCKET_DOMAIN: if (stress_set_socket_domain(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_SOCKET_PORT: stress_set_socket_port(optarg); break; #if defined (__linux__) case OPT_SPLICE_BYTES: stress_set_splice_bytes(optarg); break; #endif case OPT_TIMEOUT: opt_timeout = get_uint64_time(optarg); break; #if defined (__linux__) case OPT_TIMER_FREQ: stress_set_timer_freq(optarg); break; #endif case OPT_TIMES: opt_flags |= OPT_FLAGS_TIMES; break; case OPT_TSEARCH_SIZE: stress_set_tsearch_size(optarg); break; case OPT_UDP_DOMAIN: if (stress_set_udp_domain(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_UDP_PORT: stress_set_udp_port(optarg); break; case OPT_UTIME_FSYNC: opt_flags |= OPT_FLAGS_UTIME_FSYNC; break; case OPT_VERBOSE: opt_flags |= PR_ALL; break; #if _BSD_SOURCE || \ (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \ !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) case OPT_VFORK_MAX: stress_set_vfork_max(optarg); break; #endif case OPT_VERIFY: opt_flags |= (OPT_FLAGS_VERIFY | PR_FAIL); break; case OPT_VERSION: version(); exit(EXIT_SUCCESS); case OPT_VM_BYTES: stress_set_vm_bytes(optarg); break; case OPT_VM_HANG: stress_set_vm_hang(optarg); break; case OPT_VM_KEEP: stress_set_vm_flags(OPT_FLAGS_VM_KEEP); break; case OPT_VM_METHOD: if (stress_set_vm_method(optarg) < 0) exit(EXIT_FAILURE); break; #ifdef MAP_LOCKED case OPT_VM_MMAP_LOCKED: stress_set_vm_flags(MAP_LOCKED); break; #endif #ifdef MAP_POPULATE case OPT_VM_MMAP_POPULATE: stress_set_vm_flags(MAP_POPULATE); break; #endif #if defined (__linux__) case OPT_VM_RW_BYTES: stress_set_vm_rw_bytes(optarg); break; #endif #if defined (__linux__) case OPT_VM_SPLICE_BYTES: stress_set_vm_splice_bytes(optarg); break; #endif default: printf("Unknown option\n"); exit(EXIT_FAILURE); } } if (opt_class && !opt_sequential) { fprintf(stderr, "class option is only used with sequential option\n"); exit(EXIT_FAILURE); } pr_dbg(stderr, "%ld processors online\n", stress_get_processors_online()); if (opt_flags & OPT_FLAGS_RANDOM) { int32_t n = opt_random; if (opt_flags & OPT_FLAGS_SET) { pr_err(stderr, "Cannot specify random option with " "other stress processes selected\n"); exit(EXIT_FAILURE); } /* create n randomly chosen stressors */ while (n > 0) { int32_t rnd = mwc() % ((opt_random >> 5) + 2); if (rnd > n) rnd = n; n -= rnd; procs[mwc() % STRESS_MAX].num_procs += rnd; } } set_oom_adjustment("main", false); set_coredump("main"); set_sched(opt_sched, opt_sched_priority); set_iopriority(opt_ionice_class, opt_ionice_level); for (i = 0; signals[i] != -1; i++) { new_action.sa_handler = handle_sigint; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(signals[i], &new_action, NULL) < 0) { pr_err(stderr, "stress_ng: sigaction failed: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } for (i = 0; i < STRESS_MAX; i++) total_procs += procs[i].num_procs; if (opt_sequential) { if (total_procs) { pr_err(stderr, "sequential option cannot be specified with other stressors enabled\n"); free_procs(); exit(EXIT_FAILURE); } if (opt_timeout == 0) { opt_timeout = 60; pr_inf(stdout, "defaulting to a %" PRIu64 " second run per stressor\n", opt_timeout); } /* Sequential mode has no bogo ops threshold */ for (i = 0; i < STRESS_MAX; i++) { procs[i].bogo_ops = 0; procs[i].pids = calloc(opt_sequential, sizeof(pid_t)); if (!procs[i].pids) { pr_err(stderr, "cannot allocate pid list\n"); free_procs(); exit(EXIT_FAILURE); } } max_procs = opt_sequential; } else { if (!total_procs) { pr_err(stderr, "No stress workers specified\n"); free_procs(); exit(EXIT_FAILURE); } if (opt_timeout == 0) { opt_timeout = DEFAULT_TIMEOUT; pr_inf(stdout, "defaulting to a %" PRIu64 " second run per stressor\n", opt_timeout); } /* Share bogo ops between processes equally */ for (i = 0; i < STRESS_MAX; i++) { procs[i].bogo_ops = procs[i].num_procs ? procs[i].bogo_ops / procs[i].num_procs : 0; procs[i].pids = NULL; if (max_procs < procs[i].num_procs) max_procs = procs[i].num_procs; if (procs[i].num_procs) { procs[i].pids = calloc(procs[i].num_procs, sizeof(pid_t)); if (!procs[i].pids) { pr_err(stderr, "cannot allocate pid list\n"); free_procs(); exit(EXIT_FAILURE); } } } } id = stressor_id_find(STRESS_PTHREAD); if (procs[id].num_procs && (getrlimit(RLIMIT_NPROC, &limit) == 0)) { uint64_t max = (uint64_t)limit.rlim_cur / procs[id].num_procs; stress_adjust_ptread_max(max); } pr_inf(stdout, "dispatching hogs:"); for (i = 0; i < STRESS_MAX; i++) { if (procs[i].num_procs) { fprintf(stdout, "%s %" PRId32 " %s", previous ? "," : "", procs[i].num_procs, stressors[i].name); previous = true; } } fprintf(stdout, "\n"); fflush(stdout); len = sizeof(shared_t) + (sizeof(proc_stats_t) * STRESS_MAX * max_procs); shared = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); if (shared == MAP_FAILED) { pr_err(stderr, "Cannot mmap to shared memory region: errno=%d (%s)\n", errno, strerror(errno)); free_procs(); exit(EXIT_FAILURE); } memset(shared, 0, len); id = stressor_id_find(STRESS_SEMAPHORE_POSIX); if (procs[id].num_procs || opt_sequential) stress_semaphore_posix_init(); #if !defined(__gnu_hurd__) id = stressor_id_find(STRESS_SEMAPHORE_SYSV); if (procs[id].num_procs || opt_sequential) stress_semaphore_sysv_init(); #endif if (opt_sequential) { /* * Step through each stressor one by one */ for (i = 0; opt_do_run && i < STRESS_MAX; i++) { int32_t j; for (j = 0; opt_do_run && j < STRESS_MAX; j++) procs[i].num_procs = 0; procs[i].num_procs = opt_class ? (stressors[i].class & opt_class ? opt_sequential : 0) : opt_sequential; if (procs[i].num_procs) stress_run(opt_sequential, opt_sequential, shared->stats, &duration, &success); } } else { /* * Run all stressors in parallel */ stress_run(total_procs, max_procs, shared->stats, &duration, &success); } pr_inf(stdout, "%s run completed in %.2fs\n", success ? "successful" : "unsuccessful", duration); if (opt_flags & OPT_FLAGS_METRICS) { pr_inf(stdout, "%-12s %9.9s %9.9s %9.9s %9.9s %12s %12s\n", "stressor", "bogo ops", "real time", "usr time", "sys time", "bogo ops/s", "bogo ops/s"); pr_inf(stdout, "%-12s %9.9s %9.9s %9.9s %9.9s %12s %12s\n", "", "", "(secs) ", "(secs) ", "(secs) ", "(real time)", "(usr+sys time)"); for (i = 0; i < STRESS_MAX; i++) { uint64_t c_total = 0, u_total = 0, s_total = 0, us_total; double r_total = 0.0; int32_t n = (i * max_procs); for (j = 0; j < procs[i].started_procs; j++, n++) { c_total += shared->stats[n].counter; u_total += shared->stats[n].tms.tms_utime + shared->stats[n].tms.tms_cutime; s_total += shared->stats[n].tms.tms_stime + shared->stats[n].tms.tms_cstime; r_total += shared->stats[n].finish - shared->stats[n].start; } /* Total usr + sys time of all procs */ us_total = u_total + s_total; /* Real time in terms of average wall clock time of all procs */ r_total = procs[i].started_procs ? r_total / (double)procs[i].started_procs : 0.0; if ((opt_flags & OPT_FLAGS_METRICS_BRIEF) && (c_total == 0)) continue; pr_inf(stdout, "%-12s %9" PRIu64 " %9.2f %9.2f %9.2f %12.2f %12.2f\n", munge_underscore((char *)stressors[i].name), c_total, /* op count */ r_total, /* average real (wall) clock time */ (double)u_total / (double)ticks_per_sec, /* actual user time */ (double)s_total / (double)ticks_per_sec, /* actual system time */ r_total > 0.0 ? (double)c_total / r_total : 0.0, us_total > 0 ? (double)c_total / ((double)us_total / (double)ticks_per_sec) : 0.0); } } free_procs(); stress_semaphore_posix_destroy(); #if !defined(__gnu_hurd__) stress_semaphore_sysv_destroy(); #endif (void)munmap(shared, len); if (opt_flags & OPT_FLAGS_TIMES) { struct tms buf; double total_cpu_time = stress_get_processors_online() * duration; if (times(&buf) == (clock_t)-1) { pr_err(stderr, "cannot get run time information: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } pr_inf(stdout, "for a %.2fs run time:\n", duration); pr_inf(stdout, " %8.2fs available CPU time\n", total_cpu_time); pr_inf(stdout, " %8.2fs user time (%6.2f%%)\n", (float)buf.tms_cutime / (float)ticks_per_sec, 100.0 * ((float)buf.tms_cutime / (float)ticks_per_sec) / total_cpu_time); pr_inf(stdout, " %8.2fs system time (%6.2f%%)\n", (float)buf.tms_cstime / (float)ticks_per_sec, 100.0 * ((float)buf.tms_cstime / (float)ticks_per_sec) / total_cpu_time); pr_inf(stdout, " %8.2fs total time (%6.2f%%)\n", ((float)buf.tms_cutime + (float)buf.tms_cstime) / (float)ticks_per_sec, 100.0 * (((float)buf.tms_cutime + (float)buf.tms_cstime) / (float)ticks_per_sec) / total_cpu_time); } exit(EXIT_SUCCESS); } stress-ng-0.03.15/stress-rdrand.c0000664000175000017500000000650012466243156015222 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "stress-ng.h" #if defined(STRESS_X86) && !defined(__OpenBSD__) #include /* * rdrand64() * read 64 bit random value */ static inline uint64_t rdrand64(void) { uint64_t ret; asm volatile("1:;\n\ rdrand %0;\n\ jnc 1b;\n":"=r"(ret)); return ret; } /* * Unrolled 32 times */ #define RDRAND64() \ { \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ rdrand64(); \ } /* * stress_rdrand() * stress Intel rdrand instruction */ int stress_rdrand( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint32_t eax, ebx, ecx, edx; (void)instance; /* Intel CPU? */ __cpuid(0, eax, ebx, ecx, edx); if (!((memcmp(&ebx, "Genu", 4) == 0) && (memcmp(&edx, "ineI", 4) == 0) && (memcmp(&ecx, "ntel", 4) == 0))) { pr_err(stderr, "%s: rdrand test aborted, not a recognised Intel CPU.\n", name); return EXIT_FAILURE; } /* ..and supports rdrand? */ __cpuid(1, eax, ebx, ecx, edx); if (!(ecx & 0x40000000)) { pr_err(stderr, "%s: rdrand test aborted, CPU does not support rdrand instruction.\n", name); return EXIT_FAILURE; } do { RDRAND64(); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_dbg(stderr, "%s: %" PRIu64 " random bits read\n", name, (*counter) * 64 * 32); return EXIT_SUCCESS; } #else /* * stress_rdrand() * no-op for non-intel */ int stress_rdrand( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)counter; (void)instance; (void)max_ops; pr_dbg(stderr, "%s: rdrand instruction not supported on this architecture\n", name); return EXIT_SUCCESS; } #endif stress-ng-0.03.15/stress-lease.c0000664000175000017500000001122012466243156015034 0ustar kingking/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * This code is a complete clean re-write of the stress tool by * Colin Ian King and attempts to be * backwardly compatible with the stress tool by Amos Waterland * but has more stress tests and more * functionality. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #if defined(_POSIX_PRIORITY_SCHEDULING) #include #endif #include "stress-ng.h" #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) static uint64_t lease_sigio; static uint64_t opt_lease_breakers = DEFAULT_LEASE_BREAKERS; void stress_set_lease_breakers(const char *optarg) { opt_lease_breakers = get_uint64(optarg); check_range("lease-breakers", opt_lease_breakers, MIN_LEASE_BREAKERS, MAX_LEASE_BREAKERS); } /* * stress_lease_handler() * lease signal handler */ static void stress_lease_handler(int dummy) { (void)dummy; lease_sigio++; } /* * stress_lease_spawn() * spawn a process */ static int stress_lease_spawn( const char *filename, const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; pid = fork(); if (pid < 0) { return -1; } if (pid == 0) { do { int fd; errno = 0; fd = open(filename, O_NONBLOCK | O_WRONLY, S_IRUSR | S_IWUSR); if (fd < 0) { if (errno != EWOULDBLOCK && errno != EACCES) { pr_dbg(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } continue; } (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); exit(EXIT_SUCCESS); } return pid; } /* * stress_lease * stress by fcntl lease activity */ int stress_lease( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char filename[PATH_MAX]; struct sigaction new_action; int fd, status; pid_t l_pids[opt_lease_breakers]; pid_t pid = getpid(); uint64_t i; memset(l_pids, 0, sizeof(l_pids)); memset(&new_action, 0, sizeof new_action); new_action.sa_handler = stress_lease_handler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGIO, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; (void)stress_temp_filename(filename, PATH_MAX, name, pid, instance, mwc()); fd = creat(filename, S_IRUSR | S_IWUSR); if (fd < 0) { pr_err(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)close(fd); for (i = 0; i < opt_lease_breakers; i++) { l_pids[i] = stress_lease_spawn(filename, name, max_ops, counter); if (l_pids[i] < 0) { pr_err(stderr, "%s: failed to start all the lease breaker processes\n", name); goto reap; } } do { fd = open(filename, O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR); if (fd < 0) { pr_err(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); goto reap; } while (fcntl(fd, F_SETLEASE, F_WRLCK) < 0) { if (!opt_do_run) { (void)close(fd); goto reap; } } (*counter)++; #if defined(_POSIX_PRIORITY_SCHEDULING) (void)sched_yield(); #endif if (fcntl(fd, F_SETLEASE, F_UNLCK) < 0) { pr_err(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)close(fd); break; } (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); reap: for (i = 0; i < opt_lease_breakers; i++) { if (l_pids[i]) { kill(l_pids[i], SIGKILL); waitpid(l_pids[i], &status, 0); } } (void)unlink(filename); (void)stress_temp_dir_rm(name, pid, instance); pr_dbg(stderr, "%s: %" PRIu64 " lease sigio interrupts caught\n", name, lease_sigio); return EXIT_SUCCESS; } #endif