stress-ng-0.05.23/0000775000175000017500000000000012702231607012252 5ustar kingkingstress-ng-0.05.23/stress-numa.c0000664000175000017500000002106012702231255014675 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_NUMA) #include #include #include #include #include #include #include #include #include #include #include #include #define NUMA_LONG_BITS (sizeof(unsigned long) * 8) #define MPOL_DEFAULT (0) #define MPOL_PREFERRED (1) #define MPOL_BIND (2) #define MPOL_INTERLEAVE (3) #define MPOL_F_NODE (1 << 0) #define MPOL_F_ADDR (1 << 1) #define MPOL_F_MEMS_ALLOWED (1 << 2) #define MPOL_MF_STRICT (1 << 0) #define MPOL_MF_MOVE (1 << 1) #define MPOL_MF_MOVE_ALL (1 << 2) #define SYS_NODE_PATH "/sys/devices/system/node" #define MMAP_SZ (4 * MB) typedef struct node { uint32_t node_id; struct node *next; } node_t; /* * Rather than have all the libnuma overhead, just * perform NUMA operations via the system call * interfaces. */ static int sys_get_mempolicy( int *mode, unsigned long *nodemask, unsigned long maxnode, unsigned long addr, unsigned long flags) { #if defined(__NR_get_mempolicy) return syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); #else errno = ENOSYS; return -1; #endif } static int sys_set_mempolicy( int mode, unsigned long *nodemask, unsigned long maxnode) { #if defined(__NR_set_mempolicy) return syscall(__NR_set_mempolicy, mode, nodemask, maxnode); #else errno = ENOSYS; return -1; #endif } static long sys_mbind( void *addr, unsigned long len, int mode, const unsigned long *nodemask, unsigned long maxnode, unsigned flags) { #if defined(__NR_mbind) return syscall(__NR_mbind, addr, len, mode, nodemask, maxnode, flags); #else errno = ENOSYS; return -1; #endif } static long sys_migrate_pages( int pid, unsigned long maxnode, const unsigned long *old_nodes, const unsigned long *new_nodes) { #if defined(__NR_migrate_pages) return syscall(__NR_migrate_pages, pid, maxnode, old_nodes, new_nodes); #else errno = ENOSYS; return -1; #endif } static long sys_move_pages( int pid, unsigned long count, void **pages, const int *nodes, int *status, int flags) { #if defined(__NR_move_pages) return syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); #else errno = ENOSYS; return -1; #endif } /* Added to kernel 2.6.19 for x86_64 and i386 */ static long sys_getcpu( unsigned *cpu, unsigned *node, void *tcache) { #if defined(__NR_getcpu) return syscall(__NR_getcpu, cpu, node, tcache); #else errno = ENOSYS; return -1; #endif } /* * stress_numa_free_nodes() * free circular list of node info */ static void stress_numa_free_nodes(node_t *nodes) { node_t *n = nodes; while (n) { node_t *next = n->next; free(n); n = next; if (n == nodes) break; } } /* * stress_numa_get_nodes(void) * collect number of nodes, add them to a * circular linked list */ static int stress_numa_get_nodes(node_t **node_ptr) { DIR *dir; struct dirent *entry; unsigned long n = 0; node_t *tail = NULL; *node_ptr = NULL; dir = opendir(SYS_NODE_PATH); if (!dir) return -1; while ((entry = readdir(dir)) != NULL) { uint32_t node_id; node_t *node; if (strncmp(entry->d_name, "node", 4)) continue; if (!isdigit(entry->d_name[4])) continue; if (sscanf(&entry->d_name[4], "%u10", &node_id) != 1) continue; node = calloc(1, sizeof(*node)); if (!node) { break; } node->node_id = node_id; node->next = *node_ptr; *node_ptr = node; if (!tail) tail = node; tail->next = node; n++; } (void)closedir(dir); return n; } /* * stress_numa() * stress the Linux NUMA interfaces */ int stress_numa( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { long numa_nodes; unsigned long max_nodes, nbits, lbits = 8 * sizeof(unsigned long); uint8_t *buf; const pid_t mypid = getpid(); const unsigned long page_sz = stress_get_pagesize(); const unsigned long num_pages = MMAP_SZ / page_sz; node_t *n; int rc = EXIT_FAILURE; (void)instance; numa_nodes = stress_numa_get_nodes(&n); if (numa_nodes <= 1) { pr_inf(stderr, "%s: multiple NUMA nodes not found, " "aborting test.\n", name); rc = EXIT_SUCCESS; goto numa_free; } nbits = (numa_nodes + lbits - 1) / lbits; max_nodes = nbits * lbits; /* * We need a buffer to migrate around NUMA nodes */ buf = mmap(NULL, MMAP_SZ, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if (buf == MAP_FAILED) { rc = exit_status(errno); pr_fail(stderr, "%s: mmap'd region of %zu bytes failed", name, (size_t)MMAP_SZ); goto numa_free; } do { int j, mode, ret, status[num_pages], dest_nodes[num_pages]; unsigned long i, node_mask[lbits], old_node_mask[lbits]; void *pages[num_pages]; uint8_t *ptr; node_t *n_tmp; unsigned cpu, curr_node; /* * Fetch memory policy */ ret = sys_get_mempolicy(&mode, node_mask, max_nodes, (unsigned long)buf, MPOL_F_ADDR); if (ret < 0) { pr_fail(stderr, "%s: get_mempolicy: errno=%d (%s)\n", name, errno, strerror(errno)); } if (!opt_do_run) break; memset(node_mask, 0, sizeof(node_mask)); STRESS_SETBIT(node_mask, n->node_id); ret = sys_set_mempolicy(MPOL_PREFERRED, node_mask, max_nodes); if (ret < 0) { pr_fail(stderr, "%s: set_mempolicy: errno=%d (%s)\n", name, errno, strerror(errno)); } memset(buf, 0xff, MMAP_SZ); if (!opt_do_run) break; /* * Fetch CPU and node, we just waste some cycled * doing this for stress reasons only */ (void)sys_getcpu(&cpu, &curr_node, NULL); /* * mbind the buffer, first try MPOL_STRICT which * may fail with EIO */ memset(node_mask, 0, sizeof(node_mask)); STRESS_SETBIT(node_mask, n->node_id); ret = sys_mbind(buf, MMAP_SZ, MPOL_BIND, node_mask, max_nodes, MPOL_MF_STRICT); if (ret < 0) { if (errno != EIO) pr_fail(stderr, "%s: mbind: errno=%d (%s)\n", name, errno, strerror(errno)); } else { memset(buf, 0xaa, MMAP_SZ); } if (!opt_do_run) break; /* * mbind the buffer, now try MPOL_DEFAULT */ memset(node_mask, 0, sizeof(node_mask)); STRESS_SETBIT(node_mask, n->node_id); ret = sys_mbind(buf, MMAP_SZ, MPOL_BIND, node_mask, max_nodes, MPOL_DEFAULT); if (ret < 0) { if (errno != EIO) pr_fail(stderr, "%s: mbind: errno=%d (%s)\n", name, errno, strerror(errno)); } else { memset(buf, 0x5c, MMAP_SZ); } if (!opt_do_run) break; /* Move to next node */ n = n->next; /* * Migrate all this processes pages to the current new node */ memset(old_node_mask, 0xff, sizeof(old_node_mask)); memset(node_mask, 0, sizeof(node_mask)); STRESS_SETBIT(node_mask, n->node_id); ret = sys_migrate_pages(mypid, max_nodes, old_node_mask, node_mask); if (ret < 0) { pr_fail(stderr, "%s: migrate_pages: errno=%d (%s)\n", name, errno, strerror(errno)); } if (!opt_do_run) break; n_tmp = n; for (j = 0; j < 16; j++) { /* * Now move pages to lots of different numa nodes */ for (ptr = buf, i = 0; i < num_pages; i++, ptr += page_sz, n_tmp = n_tmp->next) { pages[i] = ptr; dest_nodes[i] = n_tmp->node_id; } memset(status, 0, sizeof(status)); ret = sys_move_pages(mypid, num_pages, pages, dest_nodes, status, MPOL_MF_MOVE); if (ret < 0) { pr_fail(stderr, "%s: move_pages: errno=%d (%s)\n", name, errno, strerror(errno)); } memset(buf, j, MMAP_SZ); if (!opt_do_run) break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; munmap(buf, MMAP_SZ); numa_free: stress_numa_free_nodes(n); return rc; } #endif stress-ng-0.05.23/helper.c0000664000175000017500000004112012702231255013672 0ustar kingking/* * Copyright (C) 2014-2016 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" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__linux__) #include #include #include #endif #include #if !defined(PR_SET_DISABLE) #define SUID_DUMP_DISABLE (0) /* No setuid dumping */ #endif #if !defined(SUID_DUMP_USER) #define SUID_DUMP_USER (1) /* Dump as user of process */ #endif #if defined(__linux__) && defined(PRCTL_TIMER_SLACK) static unsigned long timer_slack = 0; #endif static const char *stress_temp_path = "."; /* * 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 */ int32_t stress_get_processors_online(void) { static uint32_t processors_online = 0; if (processors_online > 0) return processors_online; #ifdef _SC_NPROCESSORS_ONLN processors_online = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN); return processors_online; #else return -1; #endif } /* * stress_get_processors_configured() * get number of processors that are configured */ int32_t stress_get_processors_configured(void) { static uint32_t processors_configured = 0; if (processors_configured > 0) return processors_configured; #ifdef _SC_NPROCESSORS_CONF processors_configured = sysconf(_SC_NPROCESSORS_CONF); return processors_configured; #else return -1; #endif } /* * stress_get_ticks_per_second() * get number of ticks perf second */ int32_t stress_get_ticks_per_second(void) { static uint32_t 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 } /* * stress_get_memlimits() * get SHMALL and memory in system * these are set to zero on failure */ void stress_get_memlimits( size_t *shmall, size_t *freemem, size_t *totalmem) { #if defined(__linux__) struct sysinfo info; FILE *fp; #endif *shmall = 0; *freemem = 0; *totalmem = 0; #if defined(__linux__) if (sysinfo(&info) == 0) { *freemem = info.freeram * info.mem_unit; *totalmem = info.totalram * info.mem_unit; } fp = fopen("/proc/sys/kernel/shmall", "r"); if (!fp) return; if (fscanf(fp, "%zu", shmall) != 1) { fclose(fp); return; } fclose(fp); #endif } /* * stress_get_load_avg() * get load average */ int stress_get_load_avg( double *min1, double *min5, double *min15) { #if NEED_GLIBC(2, 2, 0) int rc; double loadavg[3]; rc = getloadavg(loadavg, 3); if (rc < 0) goto fail; *min1 = loadavg[0]; *min5 = loadavg[1]; *min15 = loadavg[2]; return 0; fail: #elif defined(__linux__) struct sysinfo info; const double scale = 1.0 / (double)(1 << SI_LOAD_SHIFT); if (sysinfo(&info) < 0) goto fail; *min1 = info.loads[0] * scale; *min5 = info.loads[1] * scale; *min15 = info.loads[2] * scale; return 0; fail: #endif *min1 = *min5 = *min15 = 0.0; return -1; } /* * stress_parent_died_alarm() * send child SIGALRM if the parent died */ void stress_parent_died_alarm(void) { #if defined(__linux__) && defined(PR_SET_PDEATHSIG) (void)prctl(PR_SET_PDEATHSIG, SIGALRM); #endif } /* * stress_process_dumpable() * set dumpable flag, e.g. produce a core dump or not, * don't print an error if these fail, it's not that * critical */ int stress_process_dumpable(const bool dumpable) { char path[PATH_MAX]; int fd, rc = 0; #if defined(__linux__) && defined(PR_SET_DUMPABLE) (void)prctl(PR_SET_DUMPABLE, dumpable ? SUID_DUMP_USER : SUID_DUMP_DISABLE); #endif snprintf(path, sizeof(path), "/proc/%u/coredump_filter", getpid()); if ((fd = open(path, O_WRONLY)) >= 0) { char const *str = dumpable ? "0x33" : "0x00"; if (write(fd, str, strlen(str)) < 0) rc = -1; (void)close(fd); } return rc; } /* * stress_set_timer_slackigned_longns() * set timer slack in nanoseconds */ void stress_set_timer_slack_ns(const char *optarg) { #if defined(__linux__) && defined(PRCTL_TIMER_SLACK) timer_slack = get_unsigned_long(optarg); #else (void)optarg; #endif } /* * stress_set_timer_slack() * set timer slack */ void stress_set_timer_slack(void) { #if defined(__linux__) && defined(PRCTL_TIMER_SLACK) (void)prctl(PR_SET_TIMERSLACK, timer_slack); #endif } /* * set_proc_name() * Set process name, we don't care if it fails */ void set_proc_name(const char *name) { #if defined(__linux__) && defined(PR_SET_NAME) if (!(opt_flags & OPT_FLAGS_KEEP_NAME)) (void)prctl(PR_SET_NAME, name); #else (void)name; /* No-op */ #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 = STRESS_MINIMUM(str_len, sizeof(munged) - 1); for (src = str, dst = munged; *src && (dst - munged) < len; src++) *dst++ = (*src == '_' ? '-' : *src); *dst = '\0'; return munged; } /* * stress_get_stack_direction() * determine which way the stack goes, up / down * just pass in any var on the stack before calling */ ssize_t stress_get_stack_direction(const void *val1) { uint8_t val2; return ((uint8_t *)val1 - &val2) > 0 ? 1 : -1; } /* * 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_set_temp_path() * set temporary file path, default * is . - current dir */ int stress_set_temp_path(char *path) { stress_temp_path = path; if (access(path, R_OK | W_OK) < 0) { fprintf(stderr, "temp-path '%s' must be readable " "and writeable\n", path); return -1; } return 0; } /* * 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/tmp-%s-%i-%" PRIu32 "/%s-%i-%" PRIu32 "-%" PRIu64, stress_temp_path, 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/tmp-%s-%i-%" PRIu32, stress_temp_path, name, pid, instance); } /* * stress_temp_dir_mk() * create a temporary 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) { ret = -errno; pr_fail_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) { ret = -errno; pr_fail_err(name, "rmdir"); } return ret; } /* * stress_cwd_readwriteable() * check if cwd is read/writeable */ void stress_cwd_readwriteable(void) { char path[PATH_MAX]; if (getcwd(path, sizeof(path)) == NULL) { pr_dbg(stderr, "Cannot determine current working directory\n"); return; } if (access(path, R_OK | W_OK)) { pr_inf(stderr, "Working directory %s is not read/writeable, " "some I/O tests may fail\n", path); return; } } /* * stress_strsignal() * signum to human readable string */ const char *stress_strsignal(const int signum) { static char buffer[128]; char *str = NULL; #if defined(NSIG) if ((signum >= 0) && (signum < NSIG)) str = strsignal(signum); #elif defined(_NSIG) if ((signum >= 0) && (signum < N_SIG)) str = strsignal(signum); #endif if (str) { snprintf(buffer, sizeof(buffer), "signal %d (%s)", signum, str); } else { snprintf(buffer, sizeof(buffer), "signal %d", signum); } return buffer; } /* * stress_strnrnd() * fill string with random chars */ void stress_strnrnd(char *str, const size_t len) { char *end = str + len; while (str < end - 1) *str++ = (mwc8() % 26) + 'a'; *str = '\0'; } /* * pr_yaml_runinfo() * log info about the system we are running stress-ng on */ void pr_yaml_runinfo(FILE *yaml) { #if defined(__linux__) struct utsname uts; struct sysinfo info; #endif time_t t; struct tm *tm = NULL; char hostname[128]; char *user = getlogin(); pr_yaml(yaml, "system-info:\n"); if (time(&t) != ((time_t)-1)) tm = localtime(&t); pr_yaml(yaml, " stress-ng-version: " VERSION "\n"); pr_yaml(yaml, " run-by: %s\n", user ? user : "unknown"); if (tm) { pr_yaml(yaml, " date-yyyy-mm-dd: %4.4d:%2.2d:%2.2d\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); pr_yaml(yaml, " time-hh-mm-ss: %2.2d:%2.2d:%2.2d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); pr_yaml(yaml, " epoch-secs: %ld\n", (long)t); } if (!gethostname(hostname, sizeof(hostname))) pr_yaml(yaml, " hostname: %s\n", hostname); #if defined(__linux__) if (uname(&uts) == 0) { pr_yaml(yaml, " sysname: %s\n", uts.sysname); pr_yaml(yaml, " nodename: %s\n", uts.nodename); pr_yaml(yaml, " release: %s\n", uts.release); pr_yaml(yaml, " version: %s\n", uts.version); pr_yaml(yaml, " machine: %s\n", uts.machine); } if (sysinfo(&info) == 0) { pr_yaml(yaml, " uptime: %ld\n", info.uptime); pr_yaml(yaml, " totalram: %lu\n", info.totalram); pr_yaml(yaml, " freeram: %lu\n", info.freeram); pr_yaml(yaml, " sharedram: %lu\n", info.sharedram); pr_yaml(yaml, " bufferram: %lu\n", info.bufferram); pr_yaml(yaml, " totalswap: %lu\n", info.totalswap); pr_yaml(yaml, " freeswap: %lu\n", info.freeswap); } #endif pr_yaml(yaml, " pagesize: %zd\n", stress_get_pagesize()); pr_yaml(yaml, " cpus: %ld\n", stress_get_processors_configured()); pr_yaml(yaml, " cpus-online: %ld\n", stress_get_processors_online()); pr_yaml(yaml, " ticks-per-second: %ld\n", stress_get_ticks_per_second()); pr_yaml(yaml, "\n"); } /* * stress_cache_alloc() * allocate shared cache buffer */ int stress_cache_alloc(const char *name) { #if defined(__linux__) cpus_t *cpu_caches = NULL; cpu_cache_t *cache = NULL; uint16_t max_cache_level = 0; #endif #if !defined(__linux__) shared->mem_cache_size = MEM_CACHE_SIZE; #else cpu_caches = get_all_cpu_cache_details(); if (!cpu_caches) { pr_inf(stderr, "%s: using built-in defaults as unable to " "determine cache details\n", name); shared->mem_cache_size = MEM_CACHE_SIZE; goto init_done; } max_cache_level = get_max_cache_level(cpu_caches); if (shared->mem_cache_level > max_cache_level) { pr_dbg(stderr, "%s: reducing cache level from L%d (too high) " "to L%d\n", name, shared->mem_cache_level, max_cache_level); shared->mem_cache_level = max_cache_level; } cache = get_cpu_cache(cpu_caches, shared->mem_cache_level); if (!cache) { pr_inf(stderr, "%s: using built-in defaults as no suitable " "cache found\n", name); shared->mem_cache_size = MEM_CACHE_SIZE; goto init_done; } if (shared->mem_cache_ways > 0) { uint64_t way_size; if (shared->mem_cache_ways > cache->ways) { pr_inf(stderr, "%s: cache way value too high - " "defaulting to %d (the maximum)\n", name, cache->ways); shared->mem_cache_ways = cache->ways; } way_size = cache->size / cache->ways; /* only fill the specified number of cache ways */ shared->mem_cache_size = way_size * shared->mem_cache_ways; } else { /* fill the entire cache */ shared->mem_cache_size = cache->size; } if (!shared->mem_cache_size) { pr_inf(stderr, "%s: using built-in defaults as unable to " "determine cache size\n", name); shared->mem_cache_size = MEM_CACHE_SIZE; } init_done: free_cpu_caches(cpu_caches); #endif shared->mem_cache = calloc(shared->mem_cache_size, 1); if (!shared->mem_cache) { pr_err(stderr, "%s: failed to allocate shared cache buffer\n", name); return -1; } pr_inf(stderr, "%s: default cache size: %" PRIu64 "K\n", name, shared->mem_cache_size / 1024); return 0; } /* * stress_cache_free() * free shared cache buffer */ void stress_cache_free(void) { free(shared->mem_cache); } /* * system_write() * write a buffer to a /sys or /proc entry */ int system_write( const char *path, const char *buf, const size_t buf_len) { int fd; ssize_t ret; fd = open(path, O_WRONLY); if (fd < 0) return -errno; ret = write(fd, buf, buf_len); if (ret < (ssize_t)buf_len) ret = -errno; (void)close(fd); return ret; } /* * system_read() * read a buffer from a /sys or /proc entry */ int system_read( const char *path, char *buf, const size_t buf_len) { int fd; ssize_t ret; memset(buf, 0, buf_len); fd = open(path, O_RDONLY); if (fd < 0) return -errno; ret = read(fd, buf, buf_len); if (ret < 0) ret = -errno; (void)close(fd); return ret; } /* * stress_is_prime64() * return true if 64 bit value n is prime * http://en.wikipedia.org/wiki/Primality_test */ static inline bool stress_is_prime64(uint64_t n) { register uint64_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_get_prime64() * find a prime that is not a multiple of n, * used for file name striding */ uint64_t stress_get_prime64(const uint64_t n) { static uint p = 1009; if (n != p) return p; /* Search for next prime.. */ for (;;) { p += 2; if ((n % p) && stress_is_prime64(p)) return p; } } /* * stress_get_file_limit() * get max number of files that the current * process can open; */ size_t stress_get_file_limit(void) { struct rlimit rlim; size_t i, opened = 0, max = 65536; /* initial guess */ if (!getrlimit(RLIMIT_NOFILE, &rlim)) max = (size_t)rlim.rlim_cur; /* Determine max number of free file descriptors we have */ for (i = 0; i < max; i++) { if (fcntl((int)i, F_GETFL) > -1) opened++; } return max - opened; } /* * stress_sighandler() * set signal handler in generic way */ int stress_sighandler( const char *name, const int signum, void (*handler)(int), struct sigaction *orig_action) { struct sigaction new_action; memset(&new_action, 0, sizeof new_action); new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(signum, &new_action, orig_action) < 0) { pr_fail(stderr, "%s: sigaction %s: errno=%d (%s)\n", name, stress_strsignal(signum), errno, strerror(errno)); return -1; } return 0; } /* * stress_sigrestore() * restore a handler */ int stress_sigrestore( const char *name, const int signum, struct sigaction *orig_action) { if (sigaction(signum, orig_action, NULL) < 0) { pr_fail(stderr, "%s: sigaction %s restore: errno=%d (%s)\n", name, stress_strsignal(signum), errno, strerror(errno)); return -1; } return 0; } stress-ng-0.05.23/stress-str.c0000664000175000017500000002632312702231255014554 0ustar kingking/* * Copyright (C) 2013-2016 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" /* * the STR stress test has different classes of string stressors */ typedef void (*stress_str_func)( const char *name, char *str1, const size_t len1, char *str2, const size_t len2); typedef struct { const char *name; /* human readable form of stressor */ const stress_str_func func; /* the stressor function */ } stress_str_stressor_info_t; static const stress_str_stressor_info_t *opt_str_stressor; static const stress_str_stressor_info_t str_methods[]; static inline void strchk( const char *name, const int ok, const char *msg) { if ((opt_flags & OPT_FLAGS_VERIFY) && (!ok)) pr_fail(stderr, "%s: %s did not return expected result\n", name, msg); } #define STR(x) # x #define STRCHK(name, test) \ strchk(name, test, STR(test)) /* * stress_strcasecmp() * stress on strcasecmp */ static void stress_strcasecmp( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { STRCHK(name, 0 == strcasecmp(str1, str1)); STRCHK(name, 0 == strcasecmp(str2, str2)); STRCHK(name, 0 != strcasecmp(str2, str1)); STRCHK(name, 0 != strcasecmp(str1, str2)); STRCHK(name, 0 != strcasecmp(str1 + i, str1)); STRCHK(name, 0 != strcasecmp(str1, str1 + i)); STRCHK(name, 0 == strcasecmp(str1 + i, str1 + i)); STRCHK(name, 0 != strcasecmp(str1 + i, str2)); STRCHK(name, 0 != strcasecmp(str2, str1 + i)); } } /* * stress_strncasecmp() * stress on strncasecmp */ static void stress_strncasecmp( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { STRCHK(name, 0 == strncasecmp(str1, str1, len1)); STRCHK(name, 0 == strncasecmp(str2, str2, len2)); STRCHK(name, 0 != strncasecmp(str2, str1, len2)); STRCHK(name, 0 != strncasecmp(str1, str2, len1)); STRCHK(name, 0 != strncasecmp(str1 + i, str1, len1)); STRCHK(name, 0 != strncasecmp(str1, str1 + i, len1)); STRCHK(name, 0 == strncasecmp(str1 + i, str1 + i, len1)); STRCHK(name, 0 != strncasecmp(str1 + i, str2, len1)); STRCHK(name, 0 != strncasecmp(str2, str1 + i, len2)); } } /* * stress_index() * stress on index */ static void stress_index( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { STRCHK(name, NULL == index(str1, '_')); STRCHK(name, NULL != index(str1, str1[0])); STRCHK(name, NULL == index(str2, '_')); STRCHK(name, NULL != index(str2, str2[0])); } } /* * stress_rindex() * stress on rindex */ static void stress_rindex( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { STRCHK(name, NULL == rindex(str1, '_')); STRCHK(name, NULL != rindex(str1, str1[0])); STRCHK(name, NULL == rindex(str2, '_')); STRCHK(name, NULL != rindex(str2, str2[0])); } } /* * stress_strcpy() * stress on strcpy */ static void stress_strcpy( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; char buf[len1 + len2]; for (i = 0; i < len1 - 1; i++) { STRCHK(name, buf == strcpy(buf, str1)); STRCHK(name, buf == strcpy(buf, str2)); } } /* * stress_strcat() * stress on strcat */ static void stress_strcat( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; char buf[len1 + len2 + 1]; for (i = 0; i < len1 - 1; i++) { *buf = '\0'; STRCHK(name, buf == strcat(buf, str1)); *buf = '\0'; STRCHK(name, buf == strcat(buf, str2)); *buf = '\0'; STRCHK(name, buf == strcat(buf, str1)); STRCHK(name, buf == strcat(buf, str2)); *buf = '\0'; STRCHK(name, buf == strcat(buf, str2)); STRCHK(name, buf == strcat(buf, str1)); } } /* * stress_strncat() * stress on strncat */ static void stress_strncat( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; char buf[len1 + len2 + 1]; for (i = 0; i < len1 - 1; i++) { *buf = '\0'; STRCHK(name, buf == strncat(buf, str1, len1)); *buf = '\0'; STRCHK(name, buf == strncat(buf, str2, len2)); *buf = '\0'; STRCHK(name, buf == strncat(buf, str1, len1)); STRCHK(name, buf == strncat(buf, str2, len1 + len2)); *buf = '\0'; STRCHK(name, buf == strncat(buf, str2, i)); STRCHK(name, buf == strncat(buf, str1, i)); } } /* * stress_strchr() * stress on strchr */ static void stress_strchr( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { STRCHK(name, NULL == strchr(str1, '_')); STRCHK(name, NULL != strchr(str1, str1[0])); STRCHK(name, NULL == strchr(str2, '_')); STRCHK(name, NULL != strchr(str2, str2[0])); } } /* * stress_strrchr() * stress on strrchr */ static void stress_strrchr( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { STRCHK(name, NULL == strrchr(str1, '_')); STRCHK(name, NULL != strrchr(str1, str1[0])); STRCHK(name, NULL == strrchr(str2, '_')); STRCHK(name, NULL != strrchr(str2, str2[0])); } } /* * stress_strcmp() * stress on strcmp */ static void stress_strcmp( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { STRCHK(name, 0 == strcmp(str1, str1)); STRCHK(name, 0 == strcmp(str2, str2)); STRCHK(name, 0 != strcmp(str2, str1)); STRCHK(name, 0 != strcmp(str1, str2)); STRCHK(name, 0 != strcmp(str1 + i, str1)); STRCHK(name, 0 != strcmp(str1, str1 + i)); STRCHK(name, 0 == strcmp(str1 + i, str1 + i)); STRCHK(name, 0 != strcmp(str1 + i, str2)); STRCHK(name, 0 != strcmp(str2, str1 + i)); } } /* * stress_strncmp() * stress on strncmp */ static void stress_strncmp( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; for (i = 1; i < len1; i++) { STRCHK(name, 0 == strncmp(str1, str1, len1)); STRCHK(name, 0 == strncmp(str2, str2, len2)); STRCHK(name, 0 != strncmp(str2, str1, len2)); STRCHK(name, 0 != strncmp(str1, str2, len1)); STRCHK(name, 0 != strncmp(str1 + i, str1, len1)); STRCHK(name, 0 != strncmp(str1, str1 + i, len1)); STRCHK(name, 0 == strncmp(str1 + i, str1 + i, len1)); STRCHK(name, 0 != strncmp(str1 + i, str2, len2)); STRCHK(name, 0 != strncmp(str2, str1 + i, len2)); } } /* * stress_strcoll() * stress on strcoll */ static void stress_strcoll( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { STRCHK(name, 0 == strcoll(str1, str1)); STRCHK(name, 0 == strcoll(str2, str2)); STRCHK(name, 0 != strcoll(str2, str1)); STRCHK(name, 0 != strcoll(str1, str2)); STRCHK(name, 0 != strcoll(str1 + i, str1)); STRCHK(name, 0 != strcoll(str1, str1 + i)); STRCHK(name, 0 == strcoll(str1 + i, str1 + i)); STRCHK(name, 0 != strcoll(str1 + i, str2)); STRCHK(name, 0 != strcoll(str2, str1 + i)); } } /* * stress_strlen() * stress on strlen */ static void stress_strlen( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; for (i = 0; i < len1 - 1; i++) { STRCHK(name, len1 - 1 == strlen(str1)); STRCHK(name, len1 - 1 - i == strlen(str1 + i)); } for (i = 0; i < len2 - 1; i++) { STRCHK(name, len2 - 1 == strlen(str2)); STRCHK(name, len2 - 1 - i == strlen(str2 + i)); } } /* * stress_strxfrm() * stress on strxfrm */ static void stress_strxfrm( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { register size_t i; char buf[len1 + len2]; for (i = 0; i < len1 - 1; i++) { *buf = '\0'; STRCHK(name, 0 != strxfrm(buf, str1, sizeof(buf))); *buf = '\0'; STRCHK(name, 0 != strxfrm(buf, str2, sizeof(buf))); *buf = '\0'; STRCHK(name, 0 != strxfrm(buf, str1, sizeof(buf))); STRCHK(name, 0 != strxfrm(buf, str2, sizeof(buf))); *buf = '\0'; STRCHK(name, 0 != strxfrm(buf, str2, sizeof(buf))); STRCHK(name, 0 != strxfrm(buf, str1, sizeof(buf))); } } /* * stress_str_all() * iterate over all string stressors */ static void stress_str_all( const char *name, char *str1, const size_t len1, char *str2, const size_t len2) { static int i = 1; /* Skip over stress_str_all */ str_methods[i++].func(name, str1, len1, str2, len2); if (!str_methods[i].func) i = 1; } /* * Table of string stress methods */ static const stress_str_stressor_info_t str_methods[] = { { "all", stress_str_all }, /* Special "all test */ { "index", stress_index }, { "rindex", stress_rindex }, { "strcasecmp", stress_strcasecmp }, { "strcat", stress_strcat }, { "strchr", stress_strchr }, { "strcoll", stress_strcoll }, { "strcmp", stress_strcmp }, { "strcpy", stress_strcpy }, { "strlen", stress_strlen }, { "strncasecmp", stress_strncasecmp }, { "strncat", stress_strncat }, { "strncmp", stress_strncmp }, { "strrchr", stress_strrchr }, { "strxfrm", stress_strxfrm }, { NULL, NULL } }; /* * stress_set_str_method() * set the default string stress method */ int stress_set_str_method(const char *name) { stress_str_stressor_info_t const *info = str_methods; for (info = str_methods; info->func; info++) { if (!strcmp(info->name, name)) { opt_str_stressor = info; return 0; } } fprintf(stderr, "str-method must be one of:"); for (info = str_methods; info->func; info++) { fprintf(stderr, " %s", info->name); } fprintf(stderr, "\n"); return -1; } /* * stress_str() * stress CPU by doing various string operations */ int stress_str( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { stress_str_func func = opt_str_stressor->func; (void)instance; do { char str1[256], str2[128]; stress_strnrnd(str1, sizeof(str1)); stress_strnrnd(str2, sizeof(str2)); (void)func(name, str1, sizeof(str1), str2, sizeof(str2)); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-wait.c0000664000175000017500000001067412702231255014712 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_WAIT) #include #include #include #include #include #include #include #include #include #define ABORT_TIMEOUT (8.0) /* * spawn() * spawn a process */ static pid_t spawn( const char *name, void (*func)(const char *name, 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; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); func(name, pid_arg, counter, max_ops); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); return pid; } /* * runner() * this process pauses, but is continually being * stopped and continued by the killer process */ static void runner( const char *name, const pid_t pid, uint64_t *counter, const uint64_t max_ops) { (void)pid; pr_dbg(stderr, "%s: wait: runner started [%d]\n", name, 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 char *name, const pid_t pid, uint64_t *counter, const uint64_t max_ops) { double start = time_now(); uint64_t last_counter = *counter; pr_dbg(stderr, "%s: wait: killer started [%d]\n", name, 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, "%s: waits were blocked, " "aborting\n", name); 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(name, runner, 0, counter, max_ops); if (pid_r < 0) { pr_fail_dbg(name, "fork"); exit(EXIT_FAILURE); } pid_k = spawn(name, killer, pid_r, counter, max_ops); if (pid_k < 0) { pr_fail_dbg(name, "fork"); ret = EXIT_FAILURE; goto tidy; } do { (void)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; (void)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.05.23/stress-link.c0000664000175000017500000001005012702231255014667 0ustar kingking/* * Copyright (C) 2013-2016 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, bool symlink) { const pid_t pid = getpid(); int rc, ret, fd; char oldpath[PATH_MAX]; size_t oldpathlen; ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(oldpath, sizeof(oldpath), name, pid, instance, ~0); if ((fd = open(oldpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { ret = exit_status(errno); pr_fail_err(name, "open"); (void)stress_temp_dir_rm(name, pid, instance); return ret; } (void)close(fd); oldpathlen = strlen(oldpath); rc = EXIT_SUCCESS; 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) { rc = exit_status(errno); pr_fail_err(name, funcname); n = i; break; } if (symlink) { char buf[PATH_MAX]; ssize_t ret; ret = readlink(newpath, buf, sizeof(buf)); if (ret < 0) { rc = exit_status(errno); pr_fail_err(name, "readlink"); } else { if ((size_t)ret != oldpathlen) pr_fail_err(name, "readlink length error"); else if (strncmp(oldpath, buf, ret)) pr_fail_err(name, "readlink path error"); } } 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 rc; } /* * 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", false); } /* * 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", true); } stress-ng-0.05.23/stress-malloc.c0000664000175000017500000001360412702231255015211 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #include #include #include #include #include #if defined(STRESS_MALLOPT) #include #endif static size_t opt_malloc_bytes = DEFAULT_MALLOC_BYTES; static bool set_malloc_bytes = false; static size_t opt_malloc_max = DEFAULT_MALLOC_MAX; static bool set_malloc_max = false; #if defined(STRESS_MALLOPT) static int opt_malloc_threshold = DEFAULT_MALLOC_THRESHOLD; static bool set_malloc_threshold = false; #endif void stress_set_malloc_bytes(const char *optarg) { set_malloc_bytes = true; 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) { set_malloc_max = true; opt_malloc_max = (size_t)get_uint64_byte(optarg); check_range("malloc-max", opt_malloc_max, MIN_MALLOC_MAX, MAX_MALLOC_MAX); } #if defined(STRESS_MALLOPT) void stress_set_malloc_threshold(const char *optarg) { set_malloc_threshold = true; opt_malloc_threshold = (size_t)get_uint64_byte(optarg); check_range("malloc-threshold", opt_malloc_threshold, MIN_MALLOC_THRESHOLD, MAX_MALLOC_THRESHOLD); } #endif /* * 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 = mwc64() % 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; if (!set_malloc_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_malloc_bytes = MAX_MALLOC_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_malloc_bytes = MIN_MALLOC_BYTES; } if (!set_malloc_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_malloc_max = MAX_MALLOC_MAX; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_malloc_max = MIN_MALLOC_MAX; } #if defined(STRESS_MALLOPT) if (set_malloc_threshold) mallopt(M_MMAP_THRESHOLD, opt_malloc_threshold); #endif again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); stress_parent_died_alarm(); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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; setpgid(0, pgrp); memset(addr, 0, sizeof(addr)); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { unsigned int rnd = mwc32(); 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(n, len / n); 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.05.23/perf.c0000664000175000017500000004224512702231255013360 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_PERF_STATS) /* perf enabled systems */ #include #include #include #include #include #include #include #define THOUSAND (1000.0) #define MILLION (THOUSAND * THOUSAND) #define BILLION (THOUSAND * MILLION) #define TRILLION (THOUSAND * BILLION) #define QUADRILLION (THOUSAND * TRILLION) #define QUINTILLION (THOUSAND * QUADRILLION) #include #include #include /* used for table of perf events to gather */ typedef struct { int id; /* stress-ng perf ID */ unsigned long type; /* perf types */ unsigned long config; /* perf type specific config */ char *label; /* human readable name for perf type */ } perf_info_t; /* perf data */ typedef struct { uint64_t counter; /* perf counter */ uint64_t time_enabled; /* perf time enabled */ uint64_t time_running; /* perf time running */ } perf_data_t; /* perf trace point id -> path resolution */ typedef struct { int id; /* stress-ng perf ID */ char *path; /* path to config value */ } perf_tp_info_t; #define PERF_TP_INFO(id, path) \ { STRESS_PERF_ ## id, path } #define PERF_INFO(type, config, label) \ { STRESS_PERF_ ## config, PERF_TYPE_ ## type, \ PERF_COUNT_ ## config, label } #define UNRESOLVED (~0UL) #define PERF_COUNT_TP_SYSCALLS_ENTER UNRESOLVED #define PERF_COUNT_TP_SYSCALLS_EXIT UNRESOLVED #define PERF_COUNT_TP_TLB_FLUSH UNRESOLVED #define PERF_COUNT_TP_KMALLOC UNRESOLVED #define PERF_COUNT_TP_KMALLOC_NODE UNRESOLVED #define PERF_COUNT_TP_KFREE UNRESOLVED #define PERF_COUNT_TP_KMEM_CACHE_ALLOC UNRESOLVED #define PERF_COUNT_TP_KMEM_CACHE_ALLOC_NODE UNRESOLVED #define PERF_COUNT_TP_KMEM_CACHE_FREE UNRESOLVED #define PERF_COUNT_TP_MM_PAGE_ALLOC UNRESOLVED #define PERF_COUNT_TP_MM_PAGE_FREE UNRESOLVED #define PERF_COUNT_TP_RCU_UTILIZATION UNRESOLVED #define PERF_COUNT_TP_SCHED_MIGRATE_TASK UNRESOLVED #define PERF_COUNT_TP_SCHED_MOVE_NUMA UNRESOLVED #define PERF_COUNT_TP_SCHED_WAKEUP UNRESOLVED #define PERF_COUNT_TP_SIGNAL_GENERATE UNRESOLVED #define PERF_COUNT_TP_SIGNAL_DELIVER UNRESOLVED #define PERF_COUNT_TP_PAGE_FAULT_USER UNRESOLVED #define PERF_COUNT_TP_PAGE_FAULT_KERNEL UNRESOLVED #define PERF_COUNT_TP_IRQ_ENTRY UNRESOLVED #define PERF_COUNT_TP_IRQ_EXIT UNRESOLVED #define PERF_COUNT_TP_SOFTIRQ_ENTRY UNRESOLVED #define PERF_COUNT_TP_SOFTIRQ_EXIT UNRESOLVED #define PERF_COUNT_TP_RCU_UTILIZATION UNRESOLVED #define PERF_COUNT_TP_WRITEBACK_DIRTY_INODE UNRESOLVED #define PERF_COUNT_TP_WRITEBACK_DIRTY_PAGE UNRESOLVED /* perf counters to be read */ static perf_info_t perf_info[STRESS_PERF_MAX + 1] = { PERF_INFO(HARDWARE, HW_CPU_CYCLES, "CPU Cycles"), PERF_INFO(HARDWARE, HW_INSTRUCTIONS, "Instructions"), PERF_INFO(HARDWARE, HW_CACHE_REFERENCES, "Cache References"), PERF_INFO(HARDWARE, HW_CACHE_MISSES, "Cache Misses"), PERF_INFO(HARDWARE, HW_STALLED_CYCLES_FRONTEND, "Stalled Cycles Frontend"), PERF_INFO(HARDWARE, HW_STALLED_CYCLES_BACKEND, "Stalled Cycles Backend"), PERF_INFO(HARDWARE, HW_BRANCH_INSTRUCTIONS, "Branch Instructions"), PERF_INFO(HARDWARE, HW_BRANCH_MISSES, "Branch Misses"), PERF_INFO(HARDWARE, HW_BUS_CYCLES, "Bus Cycles"), PERF_INFO(HARDWARE, HW_REF_CPU_CYCLES, "Total Cycles"), PERF_INFO(SOFTWARE, SW_PAGE_FAULTS_MIN, "Page Faults Minor"), PERF_INFO(SOFTWARE, SW_PAGE_FAULTS_MAJ, "Page Faults Major"), PERF_INFO(SOFTWARE, SW_CONTEXT_SWITCHES, "Context Switches"), PERF_INFO(SOFTWARE, SW_CPU_MIGRATIONS, "CPU Migrations"), PERF_INFO(SOFTWARE, SW_ALIGNMENT_FAULTS, "Alignment Faults"), PERF_INFO(TRACEPOINT, TP_PAGE_FAULT_USER, "Page Faults User"), PERF_INFO(TRACEPOINT, TP_PAGE_FAULT_KERNEL, "Page Faults Kernel"), PERF_INFO(TRACEPOINT, TP_SYSCALLS_ENTER, "System Call Enter"), PERF_INFO(TRACEPOINT, TP_SYSCALLS_EXIT, "System Call Exit"), PERF_INFO(TRACEPOINT, TP_TLB_FLUSH, "TLB Flushes"), PERF_INFO(TRACEPOINT, TP_KMALLOC, "Kmalloc"), PERF_INFO(TRACEPOINT, TP_KMALLOC_NODE, "Kmalloc Node"), PERF_INFO(TRACEPOINT, TP_KFREE, "Kfree"), PERF_INFO(TRACEPOINT, TP_KMEM_CACHE_ALLOC, "Kmem Cache Alloc"), PERF_INFO(TRACEPOINT, TP_KMEM_CACHE_ALLOC_NODE, "Kmem Cache Alloc Node"), PERF_INFO(TRACEPOINT, TP_KMEM_CACHE_FREE, "Kmem Cache Free"), PERF_INFO(TRACEPOINT, TP_MM_PAGE_ALLOC, "MM Page Alloc"), PERF_INFO(TRACEPOINT, TP_MM_PAGE_FREE, "MM Page Free"), PERF_INFO(TRACEPOINT, TP_RCU_UTILIZATION, "RCU Utilization"), PERF_INFO(TRACEPOINT, TP_SCHED_MIGRATE_TASK, "Sched Migrate Task"), PERF_INFO(TRACEPOINT, TP_SCHED_MOVE_NUMA, "Sched Move NUMA"), PERF_INFO(TRACEPOINT, TP_SCHED_WAKEUP, "Sched Wakeup"), PERF_INFO(TRACEPOINT, TP_SIGNAL_GENERATE, "Signal Generate"), PERF_INFO(TRACEPOINT, TP_SIGNAL_DELIVER, "Signal Deliver"), PERF_INFO(TRACEPOINT, TP_IRQ_ENTRY, "IRQ Entry"), PERF_INFO(TRACEPOINT, TP_IRQ_EXIT, "IRQ Exit"), PERF_INFO(TRACEPOINT, TP_SOFTIRQ_ENTRY, "Soft IRQ Entry"), PERF_INFO(TRACEPOINT, TP_SOFTIRQ_EXIT, "Soft IRQ Exit"), PERF_INFO(TRACEPOINT, TP_WRITEBACK_DIRTY_INODE, "Writeback Dirty Inode"), PERF_INFO(TRACEPOINT, TP_WRITEBACK_DIRTY_PAGE, "Writeback Dirty Page"), { 0, 0, 0, NULL } }; static const perf_tp_info_t perf_tp_info[] = { PERF_TP_INFO(TP_SYSCALLS_ENTER, "raw_syscalls/sys_enter"), PERF_TP_INFO(TP_SYSCALLS_EXIT, "raw_syscalls/sys_exit"), PERF_TP_INFO(TP_TLB_FLUSH, "tlb/tlb_flush"), PERF_TP_INFO(TP_KMALLOC, "kmem/kmalloc"), PERF_TP_INFO(TP_KMALLOC_NODE, "kmem/kmalloc_node"), PERF_TP_INFO(TP_KFREE, "kmem/kfree"), PERF_TP_INFO(TP_KMEM_CACHE_ALLOC, "kmem/kmem_cache_alloc"), PERF_TP_INFO(TP_KMEM_CACHE_ALLOC_NODE, "kmem/kmem_cache_alloc_node"), PERF_TP_INFO(TP_KMEM_CACHE_FREE, "kmem/kmem_cache_free"), PERF_TP_INFO(TP_MM_PAGE_ALLOC, "kmem/mm_page_alloc"), PERF_TP_INFO(TP_MM_PAGE_FREE, "kmem/mm_page_free"), PERF_TP_INFO(TP_RCU_UTILIZATION, "rcu/rcu_utilization"), PERF_TP_INFO(TP_SCHED_MIGRATE_TASK, "sched/sched_migrate_task"), PERF_TP_INFO(TP_SCHED_MOVE_NUMA, "sched/sched_move_numa"), PERF_TP_INFO(TP_SCHED_WAKEUP, "sched/sched_wakeup"), PERF_TP_INFO(TP_SIGNAL_GENERATE, "signal/signal_generate"), PERF_TP_INFO(TP_SIGNAL_DELIVER, "signal/signal_deliver"), PERF_TP_INFO(TP_PAGE_FAULT_USER, "exceptions/page_fault_user"), PERF_TP_INFO(TP_PAGE_FAULT_KERNEL, "exceptions/page_fault_kernel"), PERF_TP_INFO(TP_IRQ_ENTRY, "irq/irq_handler_entry"), PERF_TP_INFO(TP_IRQ_EXIT, "irq/irq_handler_exit"), PERF_TP_INFO(TP_SOFTIRQ_ENTRY, "irq/softirq_entry"), PERF_TP_INFO(TP_SOFTIRQ_EXIT, "irq/softirq_exit"), PERF_TP_INFO(TP_WRITEBACK_DIRTY_INODE, "writeback/writeback_dirty_inode"), PERF_TP_INFO(TP_WRITEBACK_DIRTY_PAGE, "writeback/writeback_dirty_page"), { 0, NULL } }; static unsigned long perf_type_tracepoint_resolve_config(const int id) { char path[PATH_MAX]; size_t i; unsigned long config; bool not_found = true; FILE *fp; for (i = 0; perf_tp_info[i].path; i++) { if (perf_tp_info[i].id == id) { not_found = false; break; } } if (not_found) return UNRESOLVED; snprintf(path, sizeof(path), "/sys/kernel/debug/tracing/events/%s/id", perf_tp_info[i].path); if ((fp = fopen(path, "r")) == NULL) return UNRESOLVED; if (fscanf(fp, "%lu", &config) != 1) { fclose(fp); return UNRESOLVED; } fclose(fp); return config; } void perf_init(void) { size_t i; for (i = 0; i < STRESS_PERF_MAX; i++) { if (perf_info[i].type == PERF_TYPE_TRACEPOINT) { perf_info[i].config = perf_type_tracepoint_resolve_config(perf_info[i].id); } } } static inline int sys_perf_event_open( struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); } /* * perf_yaml_label() * turns text into a yaml compatible lable. */ static char *perf_yaml_label(char *dst, const char *src, size_t n) { if (n) { char *d = dst; const char *s = src; do { if (*s == ' ') *d = '_'; else if (isupper(*s)) *d = tolower(*s); else if (*s) *d = *s; else { while (--n != 0) *d++ = 0; break; } s++; d++; } while (--n != 0); } return dst; } /* * perf_open() * open perf, get leader and perf fd's */ int perf_open(stress_perf_t *sp) { size_t i; if (!sp) return -1; if (shared->perf.no_perf) return -1; memset(sp, 0, sizeof(stress_perf_t)); sp->perf_opened = 0; for (i = 0; i < STRESS_PERF_MAX; i++) { sp->perf_stat[i].fd = -1; sp->perf_stat[i].counter = 0; } for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) { if (perf_info[i].config != UNRESOLVED) { struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); attr.type = perf_info[i].type; attr.config = perf_info[i].config; attr.disabled = 1; attr.inherit = 1; attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; attr.size = sizeof(attr); sp->perf_stat[i].fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (sp->perf_stat[i].fd > -1) sp->perf_opened++; } } if (!sp->perf_opened) { pthread_spin_lock(&shared->perf.lock); if (!shared->perf.no_perf) { pr_dbg(stderr, "perf_event_open failed, no " "perf events [%u]\n", getpid()); shared->perf.no_perf = true; } pthread_spin_unlock(&shared->perf.lock); return -1; } return 0; } /* * perf_enable() * enable perf counters */ int perf_enable(stress_perf_t *sp) { size_t i; if (!sp) return -1; if (!sp->perf_opened) return 0; for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) { int fd = sp->perf_stat[i].fd; if (fd > -1) { if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) < 0) { (void)close(fd); sp->perf_stat[i].fd = -1; continue; } if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) < 0) { (void)close(fd); sp->perf_stat[i].fd = -1; } } } return 0; } /* * perf_disable() * disable perf counters */ int perf_disable(stress_perf_t *sp) { size_t i; if (!sp) return -1; if (!sp->perf_opened) return 0; for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) { int fd = sp->perf_stat[i].fd; if (fd > -1) { if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) < 0) { (void)close(fd); sp->perf_stat[i].fd = -1; } } } return 0; } /* * perf_close() * read counters and close */ int perf_close(stress_perf_t *sp) { size_t i = 0; perf_data_t data; ssize_t ret; int rc = -1; double scale; if (!sp) return -1; if (!sp->perf_opened) goto out_ok; for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) { int fd = sp->perf_stat[i].fd; if (fd < 0 ) { sp->perf_stat[i].counter = STRESS_PERF_INVALID; continue; } memset(&data, 0, sizeof(data)); ret = read(fd, &data, sizeof(data)); if (ret != sizeof(data)) sp->perf_stat[i].counter = STRESS_PERF_INVALID; else { /* Ensure we don't get division by zero */ if (data.time_running == 0) { scale = (data.time_enabled == 0) ? 1.0 : 0.0; } else { scale = (double)data.time_enabled / data.time_running; } sp->perf_stat[i].counter = (uint64_t) ((double)data.counter * scale); } (void)close(fd); sp->perf_stat[i].fd = -1; } out_ok: rc = 0; for (; i < STRESS_PERF_MAX; i++) sp->perf_stat[i].counter = STRESS_PERF_INVALID; return rc; } /* * perf_get_counter_by_index() * fetch counter and perf ID via index i */ int perf_get_counter_by_index( const stress_perf_t *sp, const int i, uint64_t *counter, int *id) { if ((i < 0) || (i >= STRESS_PERF_MAX)) goto fail; if (perf_info[i].label) { *id = perf_info[i].id; *counter = sp->perf_stat[i].counter; return 0; } fail: *id = -1; *counter = STRESS_PERF_INVALID; return -1; } /* * perf_get_label_by_index() * fetch label via index i */ const char *perf_get_label_by_index(const int i) { if ((i < 0) || (i >= STRESS_PERF_MAX)) return NULL; return perf_info[i].label; } /* * perf_get_counter_by_id() * fetch counter and index via perf ID */ int perf_get_counter_by_id( const stress_perf_t *sp, int id, uint64_t *counter, int *index) { int i; for (i = 0; perf_info[i].label; i++) { if (perf_info[i].id == id) { *index = i; *counter = sp->perf_stat[i].counter; return 0; } } *index = -1; *counter = 0; return -1; } /* * perf_stat_succeeded() * did perf event open work OK? */ bool perf_stat_succeeded(const stress_perf_t *sp) { return sp->perf_opened > 0; } typedef struct { double threshold; double scale; char *suffix; } perf_scale_t; static perf_scale_t perf_scale[] = { { THOUSAND, 1.0, "sec" }, { 100 * THOUSAND, THOUSAND, "K/sec" }, { 100 * MILLION, MILLION, "M/sec" }, { 100 * BILLION, BILLION, "B/sec" }, { 100 * TRILLION, TRILLION, "T/sec" }, { 100 * QUADRILLION, QUADRILLION, "P/sec" }, { 100 * QUINTILLION, QUINTILLION, "E/sec" }, { -1, -1, NULL } }; /* * perf_stat_scale() * scale a counter by duration seconds * into a human readable form */ const char *perf_stat_scale(const uint64_t counter, const double duration) { static char buffer[40]; char *suffix = "E/sec"; double scale = QUINTILLION; size_t i; double scaled = duration > 0.0 ? (double)counter / duration : 0.0; for (i = 0; perf_scale[i].suffix; i++) { if (scaled < perf_scale[i].threshold) { suffix = perf_scale[i].suffix; scale = perf_scale[i].scale; break; } } scaled /= scale; snprintf(buffer, sizeof(buffer), "%11.2f %-5s", scaled, suffix); return buffer; } void perf_stat_dump( FILE *yaml, const stress_t stressors[], const proc_info_t procs[STRESS_MAX], const int32_t max_procs, const double duration) { int32_t i; bool no_perf_stats = true; setlocale(LC_ALL, ""); pr_yaml(yaml, "perfstats:\n"); for (i = 0; i < STRESS_MAX; i++) { int p; uint64_t counter_totals[STRESS_PERF_MAX]; uint64_t total_cpu_cycles = 0; uint64_t total_cache_refs = 0; uint64_t total_branches = 0; int ids[STRESS_PERF_MAX]; bool got_data = false; char *munged; memset(counter_totals, 0, sizeof(counter_totals)); /* Sum totals across all instances of the stressor */ for (p = 0; p < STRESS_PERF_MAX; p++) { int32_t j, n = (i * max_procs); stress_perf_t *sp = &shared->stats[n].sp; if (!perf_stat_succeeded(sp)) continue; ids[p] = ~0; for (j = 0; j < procs[i].started_procs; j++, n++) { uint64_t counter; if (perf_get_counter_by_index(sp, p, &counter, &ids[p]) < 0) break; if (counter == STRESS_PERF_INVALID) { counter_totals[p] = STRESS_PERF_INVALID; break; } counter_totals[p] += counter; got_data |= (counter > 0); } if (ids[p] == STRESS_PERF_HW_CPU_CYCLES) total_cpu_cycles = counter_totals[p]; if (ids[p] == STRESS_PERF_HW_CACHE_REFERENCES) total_cache_refs = counter_totals[p]; if (ids[p] == STRESS_PERF_HW_BRANCH_INSTRUCTIONS) total_branches = counter_totals[p]; } if (!got_data) continue; munged = munge_underscore((char *)stressors[i].name); pr_inf(stdout, "%s:\n", munged); pr_yaml(yaml, " - stressor: %s\n", munged); pr_yaml(yaml, " duration: %f\n", duration); for (p = 0; p < STRESS_PERF_MAX; p++) { const char *l = perf_get_label_by_index(p); uint64_t ct = counter_totals[p]; if (l && (ct != STRESS_PERF_INVALID)) { char extra[32]; char yaml_label[128]; *extra = '\0'; no_perf_stats = false; if ((ids[p] == STRESS_PERF_HW_INSTRUCTIONS) && (total_cpu_cycles > 0)) snprintf(extra, sizeof(extra), " (%.3f instr. per cycle)", (double)ct / (double)total_cpu_cycles); if ((ids[p] == STRESS_PERF_HW_CACHE_MISSES) && (total_cache_refs > 0)) snprintf(extra, sizeof(extra), " (%5.2f%%)", 100.0 * (double)ct / (double)total_cache_refs); if ((ids[p] == STRESS_PERF_HW_BRANCH_MISSES) && (total_branches > 0)) snprintf(extra, sizeof(extra), " (%5.2f%%)", 100.0 * (double)ct / (double)total_branches); pr_inf(stdout, "%'26" PRIu64 " %-23s %s%s\n", ct, l, perf_stat_scale(ct, duration), extra); perf_yaml_label(yaml_label, l, sizeof(yaml_label)); pr_yaml(yaml, " %s_total: %" PRIu64 "\n", yaml_label, ct); pr_yaml(yaml, " %s_per_second: %f\n", yaml_label, (double)ct / duration); } } pr_yaml(yaml, "\n"); } if (no_perf_stats) pr_inf(stdout, "perf counters are not available " "on this device\n"); } #endif stress-ng-0.05.23/README.Android0000664000175000017500000000174712702231255014521 0ustar kingking= Android porting notes = How to setup a Ubuntu 12.04 machine to cross compile for different architectures. == Setup == Install tools: sudo apt-get install kernel-package build-essential git gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-4.6-multilib-arm-linux-gnueabihf gcc-4.6-multilib-arm-linux-gnueabi == Environment == Ubuntu has a command called ''dpkg-architecture'' which setups up most of the cross compile environment. 64-bit x86: export $(dpkg-architecture -aamd64) 32-bit x86: export $(dpkg-architecture -ai386) armhf (RaspberryPi/uPC): export $(dpkg-architecture -aarmhf) export CROSS_COMPILE=arm-linux-gnueabihf- export CCPREFIX=${CROSS_COMPILE} armel: export $(dpkg-architecture -aarmel) export CROSS_COMPILE=arm-linux-gnueabi- export CCPREFIX=${CROSS_COMPILE} Shared Variables: export CONCURRENCY_LEVEL=`grep -c '^processor' /proc/cpuinfo` export ROOT_CMD=fakeroot == Build == #Make export CC=${CROSS_COMPILE} make ARCH=arm M.Srikanth Kumar, Jul 14, 2015 stress-ng-0.05.23/mascot/0000775000175000017500000000000012702231255013537 5ustar kingkingstress-ng-0.05.23/mascot/stress-ng.svg0000664000175000017500000066572612702231255016233 0ustar kingking image/svg+xml stress-ng-0.05.23/stress-fstat.c0000664000175000017500000000752512702231255015070 0ustar kingking/* * Copyright (C) 2013-2016 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; } static const char *blacklist[] = { "/dev/watchdog" }; /* * do_not_stat() * Check if file should not be stat'd */ static bool do_not_stat(const char *filename) { size_t i; for (i = 0; i < SIZEOF_ARRAY(blacklist); i++) { if (!strncmp(filename, blacklist[i], strlen(blacklist[i]))) return true; } return false; } /* * 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 (do_not_stat(path)) continue; 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 | O_NONBLOCK); 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.05.23/io-priority.c0000664000175000017500000000721512702231255014710 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #if defined(STRESS_IOPRIO) #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 /* * get_opt_ionice_class() * string io scheduler to IOPRIO_CLASS */ int32_t 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(STRESS_IOPRIO) /* * 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 int32_t class, const int32_t 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 int32_t class, const int32_t level) { (void)class; (void)level; } #endif stress-ng-0.05.23/stress-sem-sysv.c0000664000175000017500000001330412702231255015525 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SEMAPHORE_SYSV) #include #include #include #include #include #include #include #include #include #include #include static uint64_t opt_semaphore_sysv_procs = DEFAULT_SEMAPHORE_PROCS; static bool set_semaphore_sysv_procs = false; typedef union _semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ } semun_t; void stress_set_semaphore_sysv_procs(const char *optarg) { set_semaphore_sysv_procs = true; 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)mwc16(); shared->sem_sysv.sem_id = semget(shared->sem_sysv.key_id, 1, IPC_CREAT | S_IRUSR | S_IWUSR); if (shared->sem_sysv.sem_id >= 0) break; count++; } if (shared->sem_sysv.sem_id >= 0) { semun_t arg; arg.val = 1; if (semctl(shared->sem_sysv.sem_id, 0, SETVAL, arg) == 0) { shared->sem_sysv.init = true; return; } /* Clean up */ (void)semctl(shared->sem_sysv.sem_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.sem_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; struct timespec timeout; if (clock_gettime(CLOCK_REALTIME, &timeout) < 0) { pr_fail_dbg(name, "clock_gettime"); return; } timeout.tv_sec++; 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 (semtimedop(shared->sem_sysv.sem_id, &semwait, 1, &timeout) < 0) { if (errno == EAGAIN) { pr_inf(stderr, "Semaphore timed out: errno=%d (%s)\n", errno, strerror(errno)); goto timed_out; } if (errno != EINTR) pr_fail_dbg(name, "semop wait"); break; } (*counter)++; if (semop(shared->sem_sysv.sem_id, &semsignal, 1) < 0) { if (errno != EINTR) pr_fail_dbg(name, "semop signal"); break; } timed_out: if (!opt_do_run) break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * semaphore_sysv_spawn() * spawn a process */ static pid_t semaphore_sysv_spawn( const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); semaphore_sysv_thrash(name, max_ops, counter); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); 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 (!set_semaphore_sysv_procs) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_semaphore_sysv_procs = MAX_SEMAPHORE_PROCS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_semaphore_sysv_procs = MIN_SEMAPHORE_PROCS; } 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 (!opt_do_run || pids[i] < 0) goto reap; } /* Wait for termination */ while (opt_do_run && (!max_ops || *counter < max_ops)) usleep(100000); reap: for (i = 0; i < opt_semaphore_sysv_procs; i++) { if (pids[i] > 0) (void)kill(pids[i], SIGKILL); } for (i = 0; i < opt_semaphore_sysv_procs; i++) { if (pids[i] > 0) { int status; (void)waitpid(pids[i], &status, 0); } } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-itimer.c0000664000175000017500000000770012702231255015233 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include static volatile uint64_t itimer_counter = 0; static uint64_t opt_itimer_freq = DEFAULT_TIMER_FREQ; static bool set_itimer_freq = false; static double rate_us; static double start; /* * stress_set_itimer_freq() * set itimer frequency from given option */ void stress_set_itimer_freq(const char *optarg) { set_itimer_freq = true; opt_itimer_freq = get_uint64(optarg); check_range("itimer-freq", opt_itimer_freq, MIN_TIMER_FREQ, MAX_TIMER_FREQ); } /* * stress_itimer_set() * set timer, ensure it is never zero */ void stress_itimer_set(struct itimerval *timer) { double rate; if (opt_flags & OPT_FLAGS_TIMER_RAND) { /* Mix in some random variation */ double r = ((double)(mwc32() % 10000) - 5000.0) / 40000.0; rate = rate_us + (rate_us * r); } else { rate = rate_us; } timer->it_value.tv_sec = (long long int)rate / 1000000; timer->it_value.tv_usec = (long long int)rate % 1000000; if (timer->it_value.tv_sec == 0 && timer->it_value.tv_usec < 1) timer->it_value.tv_usec = 1; timer->it_interval.tv_sec = timer->it_value.tv_sec; timer->it_interval.tv_usec = timer->it_value.tv_usec; } /* * stress_itimer_handler() * catch itimer signal and cancel if no more runs flagged */ static void stress_itimer_handler(int sig) { struct itimerval timer; sigset_t mask; (void)sig; itimer_counter++; if (sigpending(&mask) == 0) if (sigismember(&mask, SIGINT)) goto cancel; /* High freq timer, check periodically for timeout */ if ((itimer_counter & 65535) == 0) if ((time_now() - start) > (double)opt_timeout) goto cancel; if (opt_do_run) { stress_itimer_set(&timer); return; } cancel: opt_do_run = false; /* Cancel timer if we detect no more runs */ memset(&timer, 0, sizeof(timer)); (void)setitimer(ITIMER_PROF, &timer, NULL); } /* * stress_itimer * stress itimer */ int stress_itimer( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct itimerval timer; sigset_t mask; (void)instance; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigprocmask(SIG_SETMASK, &mask, NULL); if (!set_itimer_freq) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_itimer_freq = MAX_ITIMER_FREQ; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_itimer_freq = MIN_ITIMER_FREQ; } rate_us = opt_itimer_freq ? 1000000 / opt_itimer_freq : 1000000; if (stress_sighandler(name, SIGPROF, stress_itimer_handler, NULL) < 0) return EXIT_FAILURE; stress_itimer_set(&timer); if (setitimer(ITIMER_PROF, &timer, NULL) < 0) { pr_fail_err(name, "setitimer"); return EXIT_FAILURE; } do { struct itimerval t; getitimer(ITIMER_PROF, &t); *counter = itimer_counter; } while (opt_do_run && (!max_ops || itimer_counter < max_ops)); memset(&timer, 0, sizeof(timer)); (void)setitimer(ITIMER_PROF, &timer, NULL); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-getrandom.c0000664000175000017500000000364712702231255015730 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_GETRANDOM) #include #include #include /* * getrandom() syscall */ static inline int sys_getrandom(void *buff, size_t buflen, unsigned int flags) { #if defined(__NR_getrandom) return syscall(__NR_getrandom, buff, buflen, flags); #else errno = ENOSYS; return -1; #endif } /* * stress_getrandom * stress reading random values using getrandom() */ int stress_getrandom( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; do { char buffer[8192]; ssize_t ret; ret = sys_getrandom(buffer, sizeof(buffer), 0); if (ret < 0) { if (errno == EAGAIN) continue; pr_fail_err(name, "getrandom"); return EXIT_FAILURE; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-sigq.c0000664000175000017500000000523612702231255014707 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SIGQUEUE) #include #include #include #include #include #include #include static void MLOCKED 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; if (stress_sighandler(name, SIGUSR1, stress_sigqhandler, NULL) < 0) return EXIT_FAILURE; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { sigset_t mask; setpgid(0, pgrp); stress_parent_died_alarm(); sigemptyset(&mask); sigaddset(&mask, SIGUSR1); while (opt_do_run) { 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.05.23/stress-tsc.c0000664000175000017500000000667512702231255014545 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #if defined(STRESS_TSC) static bool tsc_supported = false; #include /* * stress_tsc_supported() * check if tsc is supported */ int stress_tsc_supported(void) { uint32_t eax, ebx, ecx, edx; /* 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_inf(stderr, "tsc stressor will be skipped, " "not a recognised Intel CPU.\n"); return -1; } /* ..and supports tsc? */ __cpuid(1, eax, ebx, ecx, edx); if (!(edx & 0x10)) { pr_inf(stderr, "tsc stressor will be skipped, CPU " "does not support the rdtsc instruction.\n"); return -1; } tsc_supported = true; return 0; } /* * read tsc */ static inline void rdtsc(void) { #if STRESS_TSC_SERIALIZED asm volatile("cpuid\nrdtsc\n" : : : "%edx", "%eax"); #else asm volatile("rdtsc\n" : : : "%edx", "%eax"); #endif } /* * Unrolled 32 times */ #define TSCx32() \ { \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ rdtsc(); \ } /* * stress_tsc() * stress Intel tsc instruction */ int stress_tsc( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; if (tsc_supported) { do { TSCx32(); TSCx32(); TSCx32(); TSCx32(); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } #else /* * stress_tsc_supported() * check if tsc is supported */ int stress_tsc_supported(void) { pr_inf(stderr, "tsc stressor will be skipped, CPU does not " "support the tsc instruction.\n"); return -1; } /* * stress_tsc() * no-op for non-intel */ int stress_tsc( 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; } #endif stress-ng-0.05.23/stress-bsearch.c0000664000175000017500000000655012702231255015353 0ustar kingking/* * Copyright (C) 2013-2016 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_bsearch_size = DEFAULT_BSEARCH_SIZE; static bool set_bsearch_size = false; /* * stress_set_bsearch_size() * set bsearch size from given option string */ void stress_set_bsearch_size(const char *optarg) { set_bsearch_size = true; 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; size_t n, n8, i; (void)instance; if (!set_bsearch_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_bsearch_size = MAX_BSEARCH_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_bsearch_size = MIN_BSEARCH_SIZE; } n = (size_t)opt_bsearch_size; n8 = (n + 7) & ~7; /* allocate in multiples of 8 */ if ((data = calloc(n8, sizeof(int32_t))) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_NO_RESOURCE; } /* Populate with ascending data */ prev = 0; for (i = 0; i < n;) { uint64_t v = mwc64(); 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, "%s: element %zu could not be found\n", name, i); else if (*result != *ptr) pr_fail(stderr, "%s: element %zu found %" PRIu32 ", expecting %" PRIu32 "\n", name, i, *result, *ptr); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(data); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-bigheap.c0000664000175000017500000001221312702231255015334 0ustar kingking/* * Copyright (C) 2013-2016 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; static bool set_bigheap_growth = false; /* * stress_set_bigheap_growth() * Set bigheap growth from given opt arg string */ void stress_set_bigheap_growth(const char *optarg) { set_bigheap_growth = true; 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; const size_t page_size = stress_get_pagesize(); const size_t stride = stress_get_pagesize(); size_t size = 0; uint32_t restarts = 0, nomems = 0; pid_t pid; uint8_t *last_ptr_end = NULL; if (!set_bigheap_growth) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_bigheap_growth = MAX_BIGHEAP_GROWTH; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_bigheap_growth = MIN_BIGHEAP_GROWTH; } again: if (!opt_do_run) return EXIT_SUCCESS; pid = fork(); if (pid < 0) { if (errno == EAGAIN) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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) { setpgid(0, pgrp); stress_parent_died_alarm(); /* 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, "%s: byte at location %p was 0x%" PRIx8 " instead of 0x%" PRIx8 "\n", name, 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.05.23/stress-longjmp.c0000664000175000017500000000320712702231255015406 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include /* * stress_jmp() * stress system by setjmp/longjmp calls */ int stress_longjmp( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int ret; static jmp_buf buf; (void)instance; (void)name; ret = setjmp(buf); if (ret) { static int c = 0; c++; if (c >= 1000) { (*counter)++; c = 0; } } if (opt_do_run && (!max_ops || *counter < max_ops)) longjmp(buf, 1); return EXIT_SUCCESS; } stress-ng-0.05.23/personality.c0000664000175000017500000000216712702231255014774 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include "stress-ng.h" #if defined(STRESS_PERSONALITY) #include #endif stress-ng-0.05.23/stress-remap-file-pages.c0000664000175000017500000000753712702231255017070 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_REMAP_FILE_PAGES) #include #include #include #include #include #include #include #define N_PAGES (512) typedef uint16_t mapdata_t; /* * check_order() * check page order */ static void check_order( const char *name, const size_t stride, const mapdata_t *data, const size_t *order, const char *ordering) { size_t i; bool failed; for (failed = false, i = 0; i < N_PAGES; i++) { if (data[i * stride] != order[i]) { failed = true; break; } } if (failed) pr_fail(stderr, "%s: remap %s order pages failed\n", name, ordering); } /* * remap_order() * remap based on given order */ static int remap_order( const char *name, const size_t stride, mapdata_t *data, const size_t *order, const size_t page_size) { size_t i; for (i = 0; i < N_PAGES; i++) { int ret; ret = remap_file_pages(data + (i * stride), page_size, 0, order[i], 0); if (ret < 0) { pr_fail(stderr, "%s: remap_file_pages: errno=%d (%s)\n", name, errno, strerror(errno)); } } return 0; } /* * stress_remap_file_pages * stress page remapping */ int stress_remap_file_pages( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { mapdata_t *data; const size_t page_size = stress_get_pagesize(); const size_t data_size = N_PAGES * page_size; const size_t stride = page_size / sizeof(*data); size_t i; (void)instance; data = mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (data == MAP_FAILED) { pr_err(stderr, "%s: mmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_NO_RESOURCE; } for (i = 0; i < N_PAGES; i++) data[i * stride] = i; do { size_t order[N_PAGES]; /* Reverse pages */ for (i = 0; i < N_PAGES; i++) order[i] = N_PAGES - 1 - i; remap_order(name, stride, data, order, page_size); check_order(name, stride, data, order, "reverse"); /* random order pages */ for (i = 0; i < N_PAGES; i++) order[i] = i; for (i = 0; i < N_PAGES; i++) { size_t tmp, j = mwc32() % N_PAGES; tmp = order[i]; order[i] = order[j]; order[j] = tmp; } remap_order(name, stride, data, order, page_size); check_order(name, stride, data, order, "random"); /* all mapped to 1 page */ for (i = 0; i < N_PAGES; i++) order[i] = 0; remap_order(name, stride, data, order, page_size); check_order(name, stride, data, order, "all-to-1"); /* reorder pages back again */ for (i = 0; i < N_PAGES; i++) order[i] = i; remap_order(name, stride, data, order, page_size); check_order(name, stride, data, order, "forward"); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); munmap(data, data_size); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-seccomp.c0000664000175000017500000001425012702231255015371 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SECCOMP) #include #include #include #include #include #include #include #include #include #include #include #include #include #define SYSCALL_NR (offsetof(struct seccomp_data, nr)) #define ALLOW_SYSCALL(syscall) \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##syscall, 0, 1), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) static struct sock_filter filter_allow_write[] = { BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SYSCALL_NR), #if defined(__NR_open) ALLOW_SYSCALL(open), #endif #if defined(__NR_write) ALLOW_SYSCALL(write), #endif #if defined(__NR_close) ALLOW_SYSCALL(close), #endif #if defined(__NR_exit_group) ALLOW_SYSCALL(exit_group), #endif #if defined(__NR_set_robust_list) ALLOW_SYSCALL(set_robust_list), #endif BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) }; static struct sock_filter filter[] = { BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SYSCALL_NR), #if defined(__NR_open) ALLOW_SYSCALL(open), #endif #if defined(__NR_close) ALLOW_SYSCALL(close), #endif #if defined(__NR_exit_group) ALLOW_SYSCALL(exit_group), #endif #if defined(__NR_set_robust_list) ALLOW_SYSCALL(set_robust_list), #endif BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) }; static struct sock_fprog prog_allow_write = { .len = (unsigned short)SIZEOF_ARRAY(filter_allow_write), .filter = filter_allow_write, }; static struct sock_fprog prog = { .len = (unsigned short)SIZEOF_ARRAY(filter), .filter = filter }; #if defined(__NR_seccomp) static int sys_seccomp(unsigned int operation, unsigned int flags, void *args) { return (int)syscall(__NR_seccomp, operation, flags, args); } #endif /* * stress_seccomp_set_filter() * set up a seccomp filter, allow writes * if allow_write is true. */ static inline int stress_seccomp_set_filter( const char *name, const bool allow_write) { #if defined(__NR_seccomp) static bool use_seccomp = true; #endif /* * Depending on allow_write we either use the * filter that allows writes or the filter * that does not allow writes */ struct sock_fprog *p = allow_write ? &prog_allow_write : &prog; if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { pr_fail(stderr, "%s: prctl PR_SET_NEW_PRIVS failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } #if defined(__NR_seccomp) /* * Try using the newer seccomp syscall first */ if (use_seccomp) { if (sys_seccomp(SECCOMP_SET_MODE_FILTER, 0, p) == 0) return 0; if (errno != ENOSYS) { pr_fail(stderr, "%s: seccomp SECCOMP_SET_MODE_FILTER " "failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } use_seccomp = false; } #endif if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, p) < 0) { pr_fail(stderr, "%s: prctl PR_SET_SECCOMP failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } return 0; } /* * stress_seccomp() * stress seccomp */ int stress_seccomp( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; do { pid_t pid; int allow_write = (mwc32() % 50) != 0; pid = fork(); if (pid == -1) { pr_fail(stderr, "%s: fork failed: %d (%s)\n", name, errno, strerror(errno)); break; } if (pid == 0) { /* * The child has a seccomp filter applied and * 1 in 50 chance that write() is not allowed * causing seccomp to kill it and the parent * sees it die on a SIGSYS */ int fd, rc = EXIT_SUCCESS; if (stress_seccomp_set_filter(name, allow_write) < 0) _exit(EXIT_FAILURE); if ((fd = open("/dev/null", O_WRONLY)) < 0) { pr_err(stderr, "%s: open failed on /dev/null, " "errno=%d (%s)\n", name, errno, strerror(errno)); _exit(EXIT_FAILURE); } if (write(fd, "TEST\n", 5) < 0) { pr_err(stderr, "%s: write to /dev/null failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } (void)close(fd); _exit(rc); } if (pid > 0) { int status; /* Wait for child to exit or get killed by seccomp */ if (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) pr_dbg(stderr, "%s: waitpid failed, errno = %d (%s)\n", name, errno, strerror(errno)); } else { /* Did the child hit a weird error? */ if (WIFEXITED(status) && (WEXITSTATUS(status) != EXIT_SUCCESS)) { pr_fail(stderr, "%s: aborting because of unexpected " "failure in child process\n", name); return EXIT_FAILURE; } /* ..exited OK but we expected SIGSYS death? */ if (WIFEXITED(status) && !allow_write) { pr_fail_err(name, "expecting SIGSYS seccomp trap " "but got a successful exit which " "was not expected"); } /* ..exited with a SIGSYS but we expexted OK exit? */ if (WIFSIGNALED(status) && allow_write) { if (WTERMSIG(status) == SIGSYS) { pr_fail_err(name, "expecting a successful exit " "but got a seccomp SIGSYS " "which was not expected"); } } } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-inotify.c0000664000175000017500000004205512702231255015425 0ustar kingking/* * Copyright (C) 2012-2016 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 #include "stress-ng.h" #if defined(STRESS_INOTIFY) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 *name, const char *path, const void *private); typedef void (*inotify_func)(const char *name, 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 *name, /* Stressor name */ 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, n = 0; char buffer[1024]; retry: n++; if ((fd = inotify_init()) < 0) { if (!opt_do_run) return; /* This is just so wrong... */ if (n < 10000 && 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, "%s: inotify_init failed: errno=%d (%s) after %" PRIu32 " calls\n", name, errno, strerror(errno), n); return; } if ((wd = inotify_add_watch(fd, watchname, flags)) < 0) { (void)close(fd); pr_fail(stderr, "%s: inotify_add_watch failed: errno=%d (%s)", name, errno, strerror(errno)); return; } if (func(name, 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, "%s: select error: errno=%d (%s)\n", name, errno, strerror(errno)); break; } else if (err == 0) { if (opt_flags & OPT_FLAGS_VERIFY) pr_fail(stderr, "%s: timed waiting for event flags 0x%x\n", name, flags); break; } redo: if (!opt_do_run) break; len = read(fd, buffer, sizeof(buffer)); if ((len <= 0) || (len > (ssize_t)sizeof(buffer))) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; if (errno) { pr_fail(stderr, "%s: error reading inotify: errno=%d (%s)\n", name, errno, strerror(errno)); break; } } /* Scan through inotify events */ while ((i >= 0) && (i <= len - (ssize_t)sizeof(struct inotify_event))) { 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; } } cleanup: (void)inotify_rm_watch(fd, wd); if (close(fd) < 0) { pr_err(stderr, "%s: close error: errno=%d (%s)\n", name, errno, strerror(errno)); } } /* * rm_file() * remove a file */ static int rm_file(const char *name, const char *path) { if ((unlink(path) < 0) && errno != ENOENT) { pr_err(stderr, "%s: cannot remove file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } return 0; } /* * rm_dir() * clean files in directory and directory */ static int rm_dir(const char *name, 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(name, filename); } (void)closedir(dp); } ret = rmdir(path); if (ret < 0 && errno != ENOENT) pr_err(stderr, "%s: cannot remove directory %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return ret; } /* * mk_dir() * make a directory */ static int mk_dir(const char *name, const char *path) { if (mkdir(path, DIR_FLAGS) < 0) { pr_err(stderr, "%s: cannot mkdir %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } return 0; } /* * mk_filename() * simple helper to create a filename */ static inline 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 *name, const char *filename, const size_t len) { int fd; size_t sz = len; char buffer[BUF_SIZE]; (void)rm_file(name, filename); if ((fd = open(filename, O_CREAT | O_RDWR, FILE_FLAGS)) < 0) { pr_err(stderr, "%s: cannot create file %s: errno=%d (%s)\n", name, 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, "%s: error writing to file %s: errno=%d (%s)\n", name, filename, errno, strerror(errno)); (void)close(fd); return -1; } sz -= ret; } if (close(fd) < 0) { pr_err(stderr, "%s: cannot close file %s: errno=%d (%s)\n", name, filename, errno, strerror(errno)); return -1; } return 0; } static int inotify_attrib_helper( const char *name, const char *path, const void *dummy) { (void)dummy; if (chmod(path, S_IRUSR | S_IWUSR) < 0) { pr_err(stderr, "%s: cannot chmod file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } return 0; } void inotify_attrib_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; inotify_exercise(name, filepath, path, "inotify_file", inotify_attrib_helper, IN_ATTRIB, NULL); (void)rm_file(name, filepath); } static int inotify_access_helper( const char *name, 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, "%s: cannot open file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } /* Just want to force an access */ do_access: if (opt_do_run && (read(fd, buffer, 1) < 0)) { if ((errno == EAGAIN) || (errno == EINTR)) goto do_access; pr_err(stderr, "%s: cannot read file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); rc = -1; } (void)close(fd); return rc; } static void inotify_access_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; inotify_exercise(name, filepath, path, "inotify_file", inotify_access_helper, IN_ACCESS, NULL); (void)rm_file(name, filepath); } static int inotify_modify_helper( const char *name, const char *path, const void *dummy) { int fd, rc = 0; char buffer[1] = { 0 }; (void)dummy; if (mk_file(name, path, 4096) < 0) return -1; if ((fd = open(path, O_RDWR)) < 0) { pr_err(stderr, "%s: cannot open file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); rc = -1; goto remove; } do_modify: if (opt_do_run && (write(fd, buffer, 1) < 0)) { if ((errno == EAGAIN) || (errno == EINTR)) goto do_modify; pr_err(stderr, "%s: cannot write to file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); rc = -1; } (void)close(fd); remove: (void)rm_file(name, path); return rc; } static void inotify_modify_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); inotify_exercise(name, filepath, path, "inotify_file", inotify_modify_helper, IN_MODIFY, NULL); } static int inotify_creat_helper( const char *name, const char *path, const void *dummy) { (void)dummy; int fd; if ((fd = creat(path, FILE_FLAGS)) < 0) { pr_err(stderr, "%s: cannot create file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } (void)close(fd); return 0; } static void inotify_creat_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); inotify_exercise(name, filepath, path, "inotify_file", inotify_creat_helper, IN_CREATE, NULL); (void)rm_file(name, filepath); } static int inotify_open_helper( const char *name, const char *path, const void *dummy) { int fd; (void)dummy; if ((fd = open(path, O_RDONLY)) < 0) { pr_err(stderr, "%s: cannot open file %s: errno=%d (%s)\n", name, path, errno, strerror(errno)); return -1; } (void)close(fd); return 0; } static void inotify_open_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; inotify_exercise(name, filepath, path, "inotify_file", inotify_open_helper, IN_OPEN, NULL); (void)rm_file(name, filepath); } static int inotify_delete_helper( const char *name, const char *path, const void *dummy) { (void)dummy; return rm_file(name, path); } static void inotify_delete_file(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; inotify_exercise(name, filepath, path, "inotify_file", inotify_delete_helper, IN_DELETE, NULL); /* We remove (again) it just in case the test failed */ (void)rm_file(name, filepath); } static int inotify_delete_self_helper( const char *name, const char *path, const void *dummy) { (void)dummy; return rm_dir(name, path); } static void inotify_delete_self(const char *name, const char *path) { char filepath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_dir"); if (mk_dir(name, filepath) < 0) return; inotify_exercise(name, filepath, filepath, "inotify_dir", inotify_delete_self_helper, IN_DELETE_SELF, NULL); /* We remove (again) in case the test failed */ (void)rm_dir(name, filepath); } static int inotify_move_self_helper( const char *name, const char *oldpath, const void *private) { char *newpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "%s: cannot rename %s to %s: errno=%d (%s)\n", name, oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_move_self(const char *name, const char *path) { char filepath[PATH_MAX], newpath[PATH_MAX]; mk_filename(filepath, PATH_MAX, path, "inotify_dir"); if (mk_dir(name, filepath) < 0) return; mk_filename(newpath, PATH_MAX, path, "renamed_dir"); inotify_exercise(name, filepath, filepath, "inotify_dir", inotify_move_self_helper, IN_MOVE_SELF, newpath); (void)rm_dir(name, newpath); (void)rm_dir(name, filepath); /* In case rename failed */ } static int inotify_moved_to_helper( const char *name, const char *newpath, const void *private) { char *oldpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "%s: cannot rename %s to %s: errno=%d (%s)\n", name, oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_moved_to(const char *name, const char *path) { char olddir[PATH_MAX], oldfile[PATH_MAX], newfile[PATH_MAX]; mk_filename(olddir, PATH_MAX, path, "new_dir"); (void)rm_dir(name, olddir); if (mk_dir(name, olddir) < 0) return; mk_filename(oldfile, PATH_MAX, olddir, "inotify_file"); if (mk_file(name, oldfile, 4096) < 0) return; mk_filename(newfile, PATH_MAX, path, "inotify_file"); inotify_exercise(name, newfile, path, "inotify_dir", inotify_moved_to_helper, IN_MOVED_TO, oldfile); (void)rm_file(name, newfile); (void)rm_dir(name, olddir); } static int inotify_moved_from_helper( const char *name, const char *oldpath, const void *private) { char *newpath = (char*)private; if (rename(oldpath, newpath) < 0) { pr_err(stderr, "%s: cannot rename %s to %s: errno=%d (%s)\n", name, oldpath, newpath, errno, strerror(errno)); return -1; } return 0; } static void inotify_moved_from(const char *name, const char *path) { char oldfile[PATH_MAX], newdir[PATH_MAX], newfile[PATH_MAX]; mk_filename(oldfile, PATH_MAX, path, "inotify_file"); if (mk_file(name, oldfile, 4096) < 0) return; mk_filename(newdir, PATH_MAX, path, "new_dir"); (void)rm_dir(name, newdir); if (mk_dir(name, newdir) < 0) return; mk_filename(newfile, PATH_MAX, newdir, "inotify_file"); inotify_exercise(name, oldfile, path, "inotify_dir", inotify_moved_from_helper, IN_MOVED_FROM, newfile); (void)rm_file(name, newfile); (void)rm_file(name, oldfile); /* In case rename failed */ (void)rm_dir(name, newdir); } static int inotify_close_write_helper( const char *name, const char *path, const void *fdptr) { (void)name; (void)path; (void)close(*(int *)fdptr); return 0; } static void inotify_close_write_file(const char *name, const char *path) { char filepath[PATH_MAX]; int fd; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; if ((fd = open(filepath, O_RDWR)) < 0) { pr_err(stderr, "%s: cannot re-open %s: errno=%d (%s)\n", name, filepath, errno, strerror(errno)); return; } inotify_exercise(name, filepath, path, "inotify_file", inotify_close_write_helper, IN_CLOSE_WRITE, (void*)&fd); (void)rm_file(name, filepath); (void)close(fd); } static int inotify_close_nowrite_helper( const char *name, const char *path, const void *fdptr) { (void)name; (void)path; (void)close(*(int *)fdptr); return 0; } static void inotify_close_nowrite_file(const char *name, const char *path) { char filepath[PATH_MAX]; int fd; mk_filename(filepath, PATH_MAX, path, "inotify_file"); if (mk_file(name, filepath, 4096) < 0) return; if ((fd = open(filepath, O_RDONLY)) < 0) { pr_err(stderr, "%s: cannot re-open %s: errno=%d (%s)\n", name, filepath, errno, strerror(errno)); (void)rm_file(name, filepath); return; } inotify_exercise(name, filepath, path, "inotify_file", inotify_close_nowrite_helper, IN_CLOSE_NOWRITE, (void*)&fd); (void)rm_file(name, 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 ret, i; const pid_t pid = getpid(); stress_temp_dir(dirname, sizeof(dirname), name, pid, instance); ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); do { for (i = 0; opt_do_run && inotify_stressors[i].func; i++) inotify_stressors[i].func(name, 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.05.23/stress-shm-sysv.c0000664000175000017500000002706012702231255015534 0ustar kingking/* * Copyright (C) 2013-2016 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 "stress-ng.h" #define KEY_GET_RETRIES (40) /* * Note, running this test with the --maximize option on * low memory systems with many instances can trigger the * OOM killer fairly easily. The test tries hard to reap * reap shared memory segments that are left over if the * child is killed, however if the OOM killer kills the * parent that does the reaping, then one can be left with * a system with many shared segments still reserved and * little free memory. */ typedef struct { int index; int shm_id; } shm_msg_t; static size_t opt_shm_sysv_bytes = DEFAULT_SHM_SYSV_BYTES; static size_t opt_shm_sysv_segments = DEFAULT_SHM_SYSV_SEGMENTS; static bool set_shm_sysv_bytes = false; static bool set_shm_sysv_segments = false; static int shm_flags[] = { #if defined(SHM_HUGETLB) SHM_HUGETLB, #endif #if defined(SHM_HUGE_2MB) SHM_HUGE_2MB, #endif #if defined(SHM_HUGE_1GB) SHM_HUGE_1GB, #endif /* This will segv if no backing, so don't use it for now */ /* #if defined(SHM_NO_RESERVE) SHM_NO_RESERVE #endif */ 0 }; void stress_set_shm_sysv_bytes(const char *optarg) { set_shm_sysv_bytes = true; 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 = true; 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, const size_t page_size) { uint8_t *ptr, *end = buf + sz; uint8_t val; for (val = 0, ptr = buf; ptr < end; ptr += page_size, val++) { *ptr = val; } for (val = 0, ptr = buf; ptr < end; ptr += page_size, val++) { if (*ptr != val) return -1; } return 0; } /* * handle_shm_sysv_sigalrm() * catch SIGALRM, flag termination */ static MLOCKED void handle_shm_sysv_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_shm_sysv_child() * stress out the shm allocations. This can be killed by * the out of memory killer, so we need to keep the parent * informed of the allocated shared memory ids so these can * be reaped cleanly if this process gets prematurely killed. */ static int stress_shm_sysv_child( const int fd, uint64_t *const counter, const uint64_t max_ops, const char *name, const size_t max_sz, const size_t page_size) { void *addrs[MAX_SHM_SYSV_SEGMENTS]; key_t keys[MAX_SHM_SYSV_SEGMENTS]; int shm_ids[MAX_SHM_SYSV_SEGMENTS]; shm_msg_t msg; size_t i; int rc = EXIT_SUCCESS; bool ok = true; int mask = ~0; int32_t instances; if (stress_sighandler(name, SIGALRM, handle_shm_sysv_sigalrm, NULL) < 0) return EXIT_FAILURE; memset(addrs, 0, sizeof(addrs)); memset(keys, 0, sizeof(keys)); for (i = 0; i < MAX_SHM_SYSV_SEGMENTS; i++) shm_ids[i] = -1; /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); if ((instances = stressor_instances(STRESS_SHM_SYSV)) < 1) instances = stress_get_processors_configured(); /* Should never happen, but be safe */ if (instances < 1) instances = 1; do { size_t sz = max_sz; for (i = 0; i < opt_shm_sysv_segments; i++) { int shm_id, count = 0; void *addr; key_t key; size_t shmall, freemem, totalmem; /* Try hard not to overcommit at this current time */ stress_get_memlimits(&shmall, &freemem, &totalmem); shmall /= instances; freemem /= instances; if ((shmall > page_size) && sz > shmall) sz = shmall; if ((freemem > page_size) && sz > freemem) sz = freemem; if (!opt_do_run) goto reap; for (count = 0; count < KEY_GET_RETRIES; count++) { bool unique = true; const int rnd = mwc32() % SIZEOF_ARRAY(shm_flags); const int rnd_flag = shm_flags[rnd] & mask; if (sz < page_size) goto reap; /* Get a unique key */ do { size_t j; if (!opt_do_run) goto reap; /* Get a unique random key */ key = (key_t)mwc16(); for (j = 0; j < i; j++) { if (key == keys[j]) { unique = false; break; } } if (!opt_do_run) goto reap; } while (!unique); shm_id = shmget(key, sz, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | rnd_flag); if (shm_id >= 0) break; if (errno == EINTR) goto reap; if (errno == EPERM) { /* ignore using the flag again */ mask &= ~rnd_flag; } if ((errno == EINVAL) || (errno == ENOMEM)) { /* * On some systems we may need * to reduce the 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; } /* Inform parent of the new shm ID */ msg.index = i; msg.shm_id = shm_id; if (write(fd, &msg, sizeof(msg)) < 0) { pr_err(stderr, "%s: write 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, page_size) < 0) { ok = false; pr_fail(stderr, "%s: memory check failed\n", name); rc = EXIT_FAILURE; goto reap; } (*counter)++; } reap: for (i = 0; i < 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)); } } /* Inform parent shm ID is now free */ msg.index = i; msg.shm_id = -1; if (write(fd, &msg, sizeof(msg)) < 0) { pr_dbg(stderr, "%s: write failed: errno=%d: (%s)\n", name, errno, strerror(errno)); ok = false; } addrs[i] = NULL; shm_ids[i] = -1; keys[i] = 0; } } while (ok && opt_do_run && (!max_ops || *counter < max_ops)); /* Inform parent of end of run */ msg.index = -1; msg.shm_id = -1; if (write(fd, &msg, sizeof(msg)) < 0) { pr_err(stderr, "%s: write failed: errno=%d: (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } return rc; } /* * 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 orig_sz, sz; int pipefds[2]; int rc = EXIT_SUCCESS; ssize_t i; pid_t pid; bool retry = true; uint32_t restarts = 0; if (!set_shm_sysv_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_shm_sysv_bytes = MAX_SHM_SYSV_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_shm_sysv_bytes = MIN_SHM_SYSV_BYTES; } if (!set_shm_sysv_segments) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_shm_sysv_segments = MAX_SHM_SYSV_SEGMENTS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_shm_sysv_segments = MIN_SHM_SYSV_SEGMENTS; } orig_sz = sz = opt_shm_sysv_bytes & ~(page_size - 1); while (opt_do_run && retry) { if (pipe(pipefds) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } fork_again: pid = fork(); if (pid < 0) { /* Can't fork, retry? */ if (errno == EAGAIN) goto fork_again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)close(pipefds[0]); (void)close(pipefds[1]); /* Nope, give up! */ return EXIT_FAILURE; } else if (pid > 0) { /* Parent */ int status, shm_ids[MAX_SHM_SYSV_SEGMENTS]; setpgid(pid, pgrp); set_oom_adjustment(name, false); (void)close(pipefds[1]); for (i = 0; i < (ssize_t)MAX_SHM_SYSV_SEGMENTS; i++) shm_ids[i] = -1; while (opt_do_run) { shm_msg_t msg; ssize_t n; /* * Blocking read on child shm ID info * pipe. We break out if pipe breaks * on child death, or child tells us * off its demise. */ n = read(pipefds[0], &msg, sizeof(msg)); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "read"); break; } pr_fail_dbg(name, "zero byte read"); break; } if ((msg.index < 0) || (msg.index >= MAX_SHM_SYSV_SEGMENTS)) { retry = false; break; } shm_ids[msg.index] = msg.shm_id; } (void)kill(pid, SIGALRM); (void)waitpid(pid, &status, 0); if (WIFSIGNALED(status)) { if ((WTERMSIG(status) == SIGKILL) || (WTERMSIG(status) == SIGBUS)) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; } } (void)close(pipefds[0]); /* * The child may have been killed by the OOM killer or * some other way, so it may have left the shared * memory segment around. At this point the child * has died, so we should be able to remove the * shared memory segment. */ for (i = 0; i < (ssize_t)opt_shm_sysv_segments; i++) { if (shm_ids[i] != -1) (void)shmctl(shm_ids[i], IPC_RMID, NULL); } } else if (pid == 0) { /* Child, stress memory */ setpgid(0, pgrp); stress_parent_died_alarm(); /* * Nicing the child may OOM it first as this * doubles the OOM score */ if (nice(5) < 0) pr_dbg(stderr, "%s: nice of child failed, " "(instance %d)\n", name, instance); (void)close(pipefds[0]); rc = stress_shm_sysv_child(pipefds[1], counter, max_ops, name, sz, page_size); (void)close(pipefds[1]); _exit(rc); } } if (orig_sz != sz) pr_dbg(stderr, "%s: reduced shared memory size from " "%zu to %zu bytes\n", name, orig_sz, sz); if (restarts) { pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 "\n", name, restarts); } return rc; } stress-ng-0.05.23/stress-fcntl.c0000664000175000017500000001252612702231255015052 0ustar kingking/* * Copyright (C) 2013-2016 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_return() * sanity check fcntl() return for errors */ static void check_return(const int ret, const char *name, const char *cmd) { if (ret < 0) { pr_fail(stderr, "%s: name: fcntl %s failed: " "errno=%d (%s)\n", name, cmd, errno, strerror(errno)); } } /* * do_fcntl() */ static int do_fcntl(const int fd, const char *name) { #if defined(F_DUPFD) { int ret; ret = fcntl(fd, F_DUPFD, mwc8()); check_return(ret, name, "F_DUPFD"); if (ret > -1) (void)close(ret); } #endif #if defined(F_DUPFD_CLOEXEC) { int ret; ret = fcntl(fd, F_DUPFD_CLOEXEC, mwc8()); check_return(ret, name, "F_DUPFD_CLOEXEC"); if (ret > -1) (void)close(ret); } #endif #if defined(F_GETFD) { int old_flags; old_flags = fcntl(fd, F_GETFD); check_return(old_flags, name, "F_GETFD"); #if defined(F_SETFD) && defined(O_CLOEXEC) if (old_flags > -1) { int new_flags, ret; new_flags = old_flags |= O_CLOEXEC; ret = fcntl(fd, F_SETFD, new_flags); check_return(ret, name, "F_SETFD"); new_flags &= ~O_CLOEXEC; ret = fcntl(fd, F_SETFD, new_flags); check_return(ret, name, "F_SETFD"); } #endif } #endif #if defined(F_GETFL) { int old_flags; old_flags = fcntl(fd, F_GETFL); check_return(old_flags, name, "F_GETFL"); #if defined(F_SETFL) && defined(O_APPEND) if (old_flags > -1) { int new_flags, ret; new_flags = old_flags |= O_APPEND; ret = fcntl(fd, F_SETFL, new_flags); check_return(ret, name, "F_SETFL"); new_flags &= ~O_APPEND; ret = fcntl(fd, F_SETFL, new_flags); check_return(ret, name, "F_SETFL"); } #endif } #endif #if defined(F_SETOWN) && defined(__linux__) { int ret; ret = fcntl(fd, F_SETOWN, getpid()); check_return(ret, name, "F_SETOWN"); } #endif #if defined(F_GETOWN) && defined(__linux__) { int ret; ret = fcntl(fd, F_GETOWN); check_return(ret, name, "F_GETOWN"); } #endif #if defined(F_SETOWN_EX) { int ret; struct f_owner_ex owner; owner.type = F_OWNER_PID; owner.pid = getpid(); ret = fcntl(fd, F_SETOWN_EX, &owner); check_return(ret, name, "F_SETOWN_EX"); } #endif #if defined(F_GETOWN_EX) { int ret; struct f_owner_ex owner; owner.type = F_OWNER_PID; ret = fcntl(fd, F_GETOWN_EX, &owner); check_return(ret, name, "F_GETOWN_EX"); } #endif #if defined(F_SETSIG) { int ret; ret = fcntl(fd, F_SETSIG, SIGKILL); check_return(ret, name, "F_SETSIG"); ret = fcntl(fd, F_SETSIG, 0); check_return(ret, name, "F_SETSIG"); ret = fcntl(fd, F_SETSIG, SIGIO); check_return(ret, name, "F_SETSIG"); } #endif #if defined(F_GETSIG) { int ret; ret = fcntl(fd, F_GETSIG); check_return(ret, name, "F_GETSIG"); } #endif return 0; } /* * stress_fcntl * stress various fcntl calls */ int stress_fcntl( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t ppid = getppid(); int fd = -1, rc = EXIT_FAILURE, retries = 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_fail_err(name, "mkdir"); return exit_status(errno); } } (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 fcntl stressors have * already created it */ if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { if ((errno == EPERM) || (errno == EACCES) || (errno == ENOMEM) || (errno == ENOSPC)) { (void)usleep(100000); continue; } pr_fail_err(name, "open"); goto tidy; } break; } while (opt_do_run && ++retries < 100); if (retries >= 100) { pr_err(stderr, "%s: chmod: file %s took %d " "retries to create (instance %" PRIu32 ")\n", name, filename, retries, instance); goto tidy; } do { do_fcntl(fd, name); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy: if (fd >= 0) (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return rc; } stress-ng-0.05.23/stress-sync-file.c0000664000175000017500000001107412702231255015632 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SYNC_FILE) #include #include #include #include #include #include #include #include static off_t opt_sync_file_bytes = DEFAULT_SYNC_FILE_BYTES; static bool set_sync_file_bytes = false; static const int sync_modes[] = { SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER, SYNC_FILE_RANGE_WRITE, SYNC_FILE_RANGE_WAIT_BEFORE, SYNC_FILE_RANGE_WAIT_AFTER, 0 /* No-op */ }; void stress_set_sync_file_bytes(const char *optarg) { set_sync_file_bytes = true; opt_sync_file_bytes = (off_t)get_uint64_byte(optarg); check_range("sync_file-bytes", opt_sync_file_bytes, MIN_SYNC_FILE_BYTES, MAX_SYNC_FILE_BYTES); } /* * shrink and re-allocate the file to be sync'd * */ static int stress_sync_allocate(const char *name, const int fd) { int ret; ret = ftruncate(fd, 0); if (ret < 0) { pr_err(stderr, "%s: ftruncate failed: errno=%d (%s)\n", name, errno, strerror(errno)); return -errno; } ret = fdatasync(fd); if (ret < 0) { pr_err(stderr, "%s: fdatasync failed: errno=%d (%s)\n", name, errno, strerror(errno)); return -errno; } ret = fallocate(fd, 0, (off_t)0, opt_sync_file_bytes); if (ret < 0) { pr_err(stderr, "%s: fallocate failed: errno=%d (%s)\n", name, errno, strerror(errno)); return -errno; } return 0; } /* * stress_sync_file * stress the sync_file_range system call */ int stress_sync_file( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); int fd, ret; char filename[PATH_MAX]; if (!set_sync_file_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_sync_file_bytes = MAX_SYNC_FILE_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_sync_file_bytes = MIN_SYNC_FILE_BYTES; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { ret = exit_status(errno); pr_fail_err(name, "open"); (void)stress_temp_dir_rm(name, pid, instance); return ret; } (void)unlink(filename); do { off64_t i, offset; const size_t mode = mwc32() % SIZEOF_ARRAY(sync_modes); if (stress_sync_allocate(name, fd) < 0) break; for (offset = 0; offset < (off64_t)opt_sync_file_bytes; ) { off64_t sz = (mwc32() & 0x1fc00) + KB; ret = sync_file_range(fd, offset, sz, mode); if (ret < 0) pr_fail_err(name, "sync_file_range (forward)"); offset += sz; } if (!opt_do_run) break; if (stress_sync_allocate(name, fd) < 0) break; for (offset = 0; offset < (off64_t)opt_sync_file_bytes; ) { off64_t sz = (mwc32() & 0x1fc00) + KB; ret = sync_file_range(fd, opt_sync_file_bytes - offset, sz, mode); if (ret < 0) pr_fail_err(name, "sync_file_range (reverse)"); offset += sz; } if (!opt_do_run) break; if (stress_sync_allocate(name, fd) < 0) break; for (i = 0; i < (off64_t)(opt_sync_file_bytes / (128 * KB)); i++) { offset = (mwc64() % opt_sync_file_bytes) & ~((128 * KB) - 1); ret = sync_file_range(fd, offset, 128 * KB, mode); if (ret < 0) pr_fail_err(name, "sync_file_range (random)"); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-bind-mount.c0000664000175000017500000000572412702231255016022 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_BIND_MOUNT) #include #include #include #include #include #define CLONE_STACK_SIZE (64*1024) /* Context for clone */ typedef struct { uint64_t max_ops; uint64_t *counter; const char *name; } context_t; /* * stress_bind_mount_child() * aggressively perform bind mounts, this can force out of memory * situations */ int stress_bind_mount_child(void *arg) { context_t *context = (context_t *)arg; setpgid(0, pgrp); stress_parent_died_alarm(); do { if (mount("/", "/", "", MS_BIND | MS_REC, 0) < 0) { pr_fail(stderr, "%s: mount failed: errno=%d (%s)\n", context->name, errno, strerror(errno)); break; } /* * The following fails with -EBUSY, but try it anyhow ` * just to make the kernel work harder */ (void)umount("/"); } while (opt_do_run && (!context->max_ops || *(context->counter) < context->max_ops)); return 0; } /* * stress_bind_mount() * stress bind mounting */ int stress_bind_mount( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int pid = 0, status; context_t context; const ssize_t stack_offset = stress_get_stack_direction(&pid) * (CLONE_STACK_SIZE - 64); char stack[CLONE_STACK_SIZE]; char *stack_top = stack + stack_offset; (void)instance; context.name = name; context.max_ops = max_ops; context.counter = counter; pid = clone(stress_bind_mount_child, stack_top, CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWPID | CLONE_VM, &context, 0); if (pid < 0) { int rc = exit_status(errno); pr_fail(stderr, "%s: clone failed: errno=%d (%s)\n", name, errno, strerror(errno)); return rc; } do { /* Twiddle thumbs */ sleep(1); } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-quota.c0000664000175000017500000001457512702231255015103 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_QUOTA) #include #include #include #include #include #include #include #include #include #include #define MAX_DEVS (128) typedef struct { char *name; char *mount; dev_t st_dev; bool valid; } dev_info_t; #define DO_Q_GETQUOTA 0x0001 #define DO_Q_GETFMT 0x0002 #define DO_Q_GETINFO 0x0004 #define DO_Q_GETSTATS 0x0008 #define DO_Q_SYNC 0x0010 /* * do_quotactl() * do a quotactl command */ static int do_quotactl( const char *name, const int flag, const char *cmdname, int *tested, int *failed, int *enosys, int cmd, const char *special, int id, caddr_t addr) { static int failed_mask = 0; int ret = quotactl(cmd, special, id, addr); (*tested)++; if (ret < 0) { if (errno == EPERM) { pr_inf(stderr, "%s: need CAP_SYS_ADMIN capability to " "run quota stressor, aborting stress test\n", name); return errno; } if ((failed_mask & flag) == 0) { /* Just issue the warning once, reduce log spamming */ failed_mask |= flag; pr_fail(stderr, "%s: quotactl command %s failed: errno=%d (%s)\n", name, cmdname, errno, strerror(errno)); } if (errno == ENOSYS) (*enosys)++; else (*failed)++; } return errno; } /* * do_quotas() * do quotactl commands */ static int do_quotas(const dev_info_t *dev, const char *name) { int tested = 0, failed = 0, enosys = 0; int errno; #if defined(Q_GETQUOTA) if (opt_do_run) { struct dqblk dqblk; errno = do_quotactl(name, DO_Q_GETQUOTA, "Q_GETQUOTA", &tested, &failed, &enosys, QCMD(Q_GETQUOTA, USRQUOTA), dev->name, 0, (caddr_t)&dqblk); if (errno == EPERM) return errno; } #endif #if defined(Q_GETFMT) if (opt_do_run) { uint32_t format; errno = do_quotactl(name, DO_Q_GETFMT, "Q_GETFMT", &tested, &failed, &enosys, QCMD(Q_GETFMT, USRQUOTA), dev->name, 0, (caddr_t)&format); if (errno == EPERM) return errno; } #endif #if defined(Q_GETINFO) if (opt_do_run) { struct dqinfo dqinfo; errno = do_quotactl(name, DO_Q_GETINFO, "Q_GETINFO", &tested, &failed, &enosys, QCMD(Q_GETINFO, USRQUOTA), dev->name, 0, (caddr_t)&dqinfo); if (errno == EPERM) return errno; } #endif #if defined(Q_GETSTATS) /* Obsolete in recent kernels */ if (opt_do_run) { struct dqstats dqstats; errno = do_quotactl(name, DO_Q_GETSTATS, "Q_GETSTATS", &tested, &failed, &enosys, QCMD(Q_GETSTATS, USRQUOTA), dev->name, 0, (caddr_t)&dqstats); if (errno == EPERM) return errno; } #endif #if defined(Q_SYNC) if (opt_do_run) { errno = do_quotactl(name, DO_Q_SYNC, "Q_SYNC", &tested, &failed, &enosys, QCMD(Q_SYNC, USRQUOTA), dev->name, 0, 0); if (errno == EPERM) return errno; } #endif if (tested == 0) { errno = pr_err(stderr, "%s: quotactl() failed, quota commands " "not available\n", name); return -1; } if (tested == enosys) { pr_err(stderr, "%s: quotactl() failed, not available " "on this kernel\n", name); return -1; } if (tested == failed) { pr_err(stderr, "%s: quotactl() failed, all quota commands " "failed (maybe privilege issues, use -v " "to see why)\n", name); return -1; } return 0; } /* * stress_quota * stress various quota options */ int stress_quota( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int i, n_mounts, n_devs = 0; int rc = EXIT_FAILURE; char *mnts[MAX_DEVS]; dev_info_t devs[MAX_DEVS]; DIR *dir; struct dirent *d; struct stat buf; (void)instance; memset(mnts, 0, sizeof(mnts)); memset(devs, 0, sizeof(devs)); n_mounts = mount_get(mnts, SIZEOF_ARRAY(mnts)); dir = opendir("/dev/"); if (!dir) { pr_err(stderr, "%s: opendir on /dev failed: errno=%d: (%s)\n", name, errno, strerror(errno)); return rc; } for (i = 0; i < n_mounts; i++) { if (lstat(mnts[i], &buf) == 0) { devs[i].st_dev = buf.st_dev; devs[i].valid = true; } } while ((d = readdir(dir)) != NULL) { char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/%s", d->d_name); if (lstat(path, &buf) < 0) continue; if ((buf.st_mode & S_IFBLK) == 0) continue; for (i = 0; i < n_mounts; i++) { if (devs[i].valid && !devs[i].name && (buf.st_rdev == devs[i].st_dev)) { devs[i].name = strdup(path); devs[i].mount = mnts[i]; if (!devs[i].name) { pr_err(stderr, "%s: out of memory\n", name); closedir(dir); goto tidy; } } } } closedir(dir); /* Compact up, remove duplicates too */ for (i = 0; i < n_mounts; i++) { int j; bool unique = true; for (j = 0; j < n_devs; j++) { if (devs[i].st_dev == devs[j].st_dev) { unique = false; break; } } if (unique && devs[i].name) devs[n_devs++] = devs[i]; else free(devs[i].name); } for (i = n_devs; i < n_mounts; i++) memset(&devs[i], 0, sizeof(devs[i])); if (!n_devs) { pr_err(stderr, "%s: cannot find any candidate block " "devices with quota enabled\n", name); } else { do { for (i = 0; opt_do_run && (i < n_devs); i++) { int ret = do_quotas(&devs[i], name); if (ret == EPERM) rc = EXIT_SUCCESS; if (ret) goto tidy; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } rc = EXIT_SUCCESS; tidy: for (i = 0; i < n_devs; i++) free(devs[i].name); mount_free(mnts, n_mounts); return rc; } #endif stress-ng-0.05.23/test-libz.c0000664000175000017500000000225112702231255014332 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include "zlib.h" int main(void) { z_stream strm; (void)deflateInit(&strm, Z_DEFAULT_COMPRESSION); (void)deflateEnd(&strm); return 0; } stress-ng-0.05.23/stress-klog.c0000664000175000017500000000665512702231255014706 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_KLOG) #include #include #include #include #define SYSLOG_ACTION_CLOSE (0) #define SYSLOG_ACTION_OPEN (1) #define SYSLOG_ACTION_READ (2) #define SYSLOG_ACTION_READ_ALL (3) #define SYSLOG_ACTION_READ_CLEAR (4) #define SYSLOG_ACTION_CLEAR (5) #define SYSLOG_ACTION_CONSOLE_OFF (6) #define SYSLOG_ACTION_CONSOLE_ON (7) #define SYSLOG_ACTION_CONSOLE_LEVEL (8) #define SYSLOG_ACTION_SIZE_UNREAD (9) #define SYSLOG_ACTION_SIZE_BUFFER (10) /* * sys_syslog() * wrapper for syslog system call */ static inline int sys_syslog(int type, char *bufp, int len) { return syscall(__NR_syslog, type, bufp, len); } /* * stress_klog * stress kernel logging interface */ int stress_klog( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char *buffer; ssize_t len; (void)instance; len = sys_syslog(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); if (len < 0) { if (!instance) pr_err(stderr, "%s: cannot determine syslog buffer " "size: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_NO_RESOURCE; } if (len == 0) { if (!instance) pr_err(stderr, "%s: zero sized syslog buffer, aborting.\n", name); return EXIT_NO_RESOURCE; } if (len > (ssize_t)(4 * MB)) { if (!instance) pr_inf(stderr, "%s: truncating syslog buffer to 4MB\n", name); len = 4 * MB; } buffer = malloc((size_t)len); if (!buffer) { pr_err(stderr, "%s: cannot allocate syslog buffer\n", name); return EXIT_NO_RESOURCE; } do { int ret, buflen = (mwc32() % len) + 1; ret = sys_syslog(SYSLOG_ACTION_READ_ALL, buffer, buflen); if (ret < 0) pr_fail(stderr, "%s: syslog ACTION_READ_ALL failed: " "errno=%d (%s)\n", name, errno, strerror(errno)); if (ret > buflen) pr_fail(stderr, "%s: syslog ACTION_READ_ALL returned more " "data than was requested.\n", name); /* open, no-op, ignore failure */ (void)sys_syslog(SYSLOG_ACTION_OPEN, NULL, 0); /* close, no-op, ignore failure */ (void)sys_syslog(SYSLOG_ACTION_CLOSE, NULL, 0); /* get unread size, ignore failure */ (void)sys_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0); /* get size of kernel buffer, ignore return */ (void)sys_syslog(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(buffer); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-lsearch.c0000664000175000017500000000615112702231255015362 0ustar kingking/* * Copyright (C) 2013-2016 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; static bool set_lsearch_size = false; /* * stress_set_lsearch_size() * set lsearch size from given option string */ void stress_set_lsearch_size(const char *optarg) { set_lsearch_size = true; 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; size_t i, max; (void)instance; if (!set_lsearch_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_lsearch_size = MAX_LSEARCH_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_lsearch_size = MIN_LSEARCH_SIZE; } max = (size_t)opt_lsearch_size; if ((data = calloc(max, sizeof(int32_t))) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_FAILURE; } if ((root = calloc(max, sizeof(int32_t))) == NULL) { free(data); pr_fail_dbg(name, "malloc"); return EXIT_FAILURE; } do { size_t n = 0; /* Step #1, populate with data */ for (i = 0; opt_do_run && i < max; i++) { data[i] = ((mwc32() & 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, "%s: element %zu could not be found\n", name, i); else if (*result != data[i]) pr_fail(stderr, "%s: element %zu found %" PRIu32 ", expecting %" PRIu32 "\n", name, i, *result, data[i]); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); free(root); free(data); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-memfd.c0000664000175000017500000001165212702231255015033 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MEMFD) #include #include #include #include #include #include #include #include #include #include #include #define MAX_MEM_FDS (256) #define MEM_PAGES (1024) /* * Ugly hack until glibc defines this */ static inline int sys_memfd_create(const char *name, unsigned int flags) { #if defined(__NR_memfd_create) return syscall(__NR_memfd_create, name, flags); #else errno = ENOSYS; return -1; #endif } /* * Create allocations using memfd_create, ftruncate and mmap */ static void stress_memfd_allocs( const char *name, uint64_t *const counter, const uint64_t max_ops) { int fds[MAX_MEM_FDS]; void *maps[MAX_MEM_FDS]; size_t i; const size_t size = stress_get_pagesize() * MEM_PAGES; const pid_t pid = getpid(); do { for (i = 0; i < MAX_MEM_FDS; i++) { fds[i] = -1; maps[i] = MAP_FAILED; } for (i = 0; i < MAX_MEM_FDS; i++) { char name[PATH_MAX]; snprintf(name, sizeof(name), "memfd-%u-%zu", pid, i); fds[i] = sys_memfd_create(name, 0); if (fds[i] < 0) { switch (errno) { case EMFILE: case ENFILE: break; case ENOMEM: goto clean; case ENOSYS: case EFAULT: default: pr_err(stderr, "%s: memfd_create failed: errno=%d (%s)\n", name, errno, strerror(errno)); opt_do_run = false; goto clean; } } } for (i = 0; i < MAX_MEM_FDS; i++) { if (fds[i] >= 0) { ssize_t ret; if (!opt_do_run) break; /* Allocate space */ ret = ftruncate(fds[i], size); if (ret < 0) { switch (errno) { case EINTR: break; default: pr_fail(stderr, "%s: ftruncate failed, errno=%d (%s)\n", name, errno, strerror(errno)); break; } } /* * ..and map it in, using MAP_POPULATE * to force page it in */ maps[i] = mmap(NULL, size, PROT_WRITE, MAP_FILE | MAP_SHARED | MAP_POPULATE, fds[i], 0); mincore_touch_pages(maps[i], size); } } clean: for (i = 0; i < MAX_MEM_FDS; i++) { if (maps[i] != MAP_FAILED) (void)munmap(maps[i], size); if (fds[i] >= 0) (void)close(fds[i]); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * stress_memfd() * stress memfd */ int stress_memfd( 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: if (!opt_do_run) return EXIT_SUCCESS; pid = fork(); if (pid < 0) { if (errno == EAGAIN) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); stress_parent_died_alarm(); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(WTERMSIG(status)), instance); /* If we got killed by OOM killer, re-start */ if ((WTERMSIG(status) == SIGKILL) || (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) { setpgid(0, pgrp); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); stress_memfd_allocs(name, counter, max_ops); } if (restarts + nomems > 0) pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 ", out of memory restarts: %" PRIu32 ".\n", name, restarts, nomems); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-wcstr.c0000664000175000017500000002533212702231255015105 0ustar kingking/* * * 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" #define STR1LEN 256 #define STR2LEN 128 /* * the wide string stress test has different classes of stressors */ typedef void (*stress_wcs_func)( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2); typedef struct { const char *name; /* human readable form of stressor */ const stress_wcs_func func; /* the stressor function */ } stress_wcs_stressor_info_t; static const stress_wcs_stressor_info_t *opt_wcs_stressor; static const stress_wcs_stressor_info_t wcs_methods[]; /* * stress_wcs_fill */ static void stress_wcs_fill(wchar_t *wcstr, const size_t len) { register size_t i; for (i = 0; i < (len-1); i++) { *wcstr++ = (mwc8() % 26) + L'a'; } *wcstr = L'\0'; } static inline void wcschk( const char *name, const int ok, const char *msg) { if ((opt_flags & OPT_FLAGS_VERIFY) && (!ok)) pr_fail(stderr, "%s: %s did not return expected result\n", name, msg); } #define STR(x) # x #define WCSCHK(name, test) \ wcschk(name, test, STR(test)) /* * stress_wcscasecmp() * stress on wcscasecmp */ static void stress_wcscasecmp( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { WCSCHK(name, 0 == wcscasecmp(str1, str1)); WCSCHK(name, 0 == wcscasecmp(str2, str2)); WCSCHK(name, 0 != wcscasecmp(str2, str1)); WCSCHK(name, 0 != wcscasecmp(str1, str2)); WCSCHK(name, 0 != wcscasecmp(str1 + i, str1)); WCSCHK(name, 0 != wcscasecmp(str1, str1 + i)); WCSCHK(name, 0 == wcscasecmp(str1 + i, str1 + i)); WCSCHK(name, 0 != wcscasecmp(str1 + i, str2)); WCSCHK(name, 0 != wcscasecmp(str2, str1 + i)); } } /* * stress_wcsncasecmp() * stress on wcsncasecmp */ static void stress_wcsncasecmp( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { WCSCHK(name, 0 == wcsncasecmp(str1, str1, len1)); WCSCHK(name, 0 == wcsncasecmp(str2, str2, len2)); WCSCHK(name, 0 != wcsncasecmp(str2, str1, len2)); WCSCHK(name, 0 != wcsncasecmp(str1, str2, len1)); WCSCHK(name, 0 != wcsncasecmp(str1 + i, str1, len1)); WCSCHK(name, 0 != wcsncasecmp(str1, str1 + i, len1)); WCSCHK(name, 0 == wcsncasecmp(str1 + i, str1 + i, len1)); WCSCHK(name, 0 != wcsncasecmp(str1 + i, str2, len1)); WCSCHK(name, 0 != wcsncasecmp(str2, str1 + i, len2)); } } /* * stress_wcscpy() * stress on wcscpy */ static void stress_wcscpy( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; wchar_t buf[len1 + len2]; for (i = 0; i < len1 - 1; i++) { WCSCHK(name, buf == wcscpy(buf, str1)); WCSCHK(name, buf == wcscpy(buf, str2)); } } /* * stress_wcscat() * stress on wcscat */ static void stress_wcscat( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; wchar_t buf[len1 + len2 + 1]; for (i = 0; i < len1 - 1; i++) { *buf = L'\0'; WCSCHK(name, buf == wcscat(buf, str1)); *buf = L'\0'; WCSCHK(name, buf == wcscat(buf, str2)); *buf = L'\0'; WCSCHK(name, buf == wcscat(buf, str1)); WCSCHK(name, buf == wcscat(buf, str2)); *buf = L'\0'; WCSCHK(name, buf == wcscat(buf, str2)); WCSCHK(name, buf == wcscat(buf, str1)); } } /* * stress_wcsncat() * stress on wcsncat */ static void stress_wcsncat( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; wchar_t buf[len1 + len2 + 1]; for (i = 0; i < len1 - 1; i++) { *buf = '\0'; WCSCHK(name, buf == wcsncat(buf, str1, len1)); *buf = '\0'; WCSCHK(name, buf == wcsncat(buf, str2, len2)); *buf = '\0'; WCSCHK(name, buf == wcsncat(buf, str1, len1)); WCSCHK(name, buf == wcsncat(buf, str2, len1 + len2)); *buf = '\0'; WCSCHK(name, buf == wcsncat(buf, str2, i)); WCSCHK(name, buf == wcsncat(buf, str1, i)); } } /* * stress_wcschr() * stress on wcschr */ static void stress_wcschr( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { WCSCHK(name, NULL == wcschr(str1, '_')); WCSCHK(name, NULL != wcschr(str1, str1[0])); WCSCHK(name, NULL == wcschr(str2, '_')); WCSCHK(name, NULL != wcschr(str2, str2[0])); } } /* * stress_wcsrchr() * stress on wcsrchr */ static void stress_wcsrchr( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 0; i < len1 - 1; i++) { WCSCHK(name, NULL == wcsrchr(str1, '_')); WCSCHK(name, NULL != wcsrchr(str1, str1[0])); WCSCHK(name, NULL == wcsrchr(str2, '_')); WCSCHK(name, NULL != wcsrchr(str2, str2[0])); } } /* * stress_wcscmp() * stress on wcscmp */ static void stress_wcscmp( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { WCSCHK(name, 0 == wcscmp(str1, str1)); WCSCHK(name, 0 == wcscmp(str2, str2)); WCSCHK(name, 0 != wcscmp(str2, str1)); WCSCHK(name, 0 != wcscmp(str1, str2)); WCSCHK(name, 0 != wcscmp(str1 + i, str1)); WCSCHK(name, 0 != wcscmp(str1, str1 + i)); WCSCHK(name, 0 == wcscmp(str1 + i, str1 + i)); WCSCHK(name, 0 != wcscmp(str1 + i, str2)); WCSCHK(name, 0 != wcscmp(str2, str1 + i)); } } /* * stress_wcsncmp() * stress on wcsncmp */ static void stress_wcsncmp( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; for (i = 1; i < len1; i++) { WCSCHK(name, 0 == wcsncmp(str1, str1, len1)); WCSCHK(name, 0 == wcsncmp(str2, str2, len2)); WCSCHK(name, 0 != wcsncmp(str2, str1, len2)); WCSCHK(name, 0 != wcsncmp(str1, str2, len1)); WCSCHK(name, 0 != wcsncmp(str1 + i, str1, len1)); WCSCHK(name, 0 != wcsncmp(str1, str1 + i, len1)); WCSCHK(name, 0 == wcsncmp(str1 + i, str1 + i, len1)); WCSCHK(name, 0 != wcsncmp(str1 + i, str2, len2)); WCSCHK(name, 0 != wcsncmp(str2, str1 + i, len2)); } } /* * stress_wcslen() * stress on wcslen */ static void stress_wcslen( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; for (i = 0; i < len1 - 1; i++) { WCSCHK(name, len1 - 1 == wcslen(str1)); WCSCHK(name, len1 - 1 - i == wcslen(str1 + i)); } for (i = 0; i < len2 - 1; i++) { WCSCHK(name, len2 - 1 == wcslen(str2)); WCSCHK(name, len2 - 1 - i == wcslen(str2 + i)); } } /* * stress_wcscoll() * stress on wcscoll */ static void stress_wcscoll( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; (void)len2; for (i = 1; i < len1; i++) { WCSCHK(name, 0 == wcscoll(str1, str1)); WCSCHK(name, 0 == wcscoll(str2, str2)); WCSCHK(name, 0 != wcscoll(str2, str1)); WCSCHK(name, 0 != wcscoll(str1, str2)); WCSCHK(name, 0 != wcscoll(str1 + i, str1)); WCSCHK(name, 0 != wcscoll(str1, str1 + i)); WCSCHK(name, 0 == wcscoll(str1 + i, str1 + i)); WCSCHK(name, 0 != wcscoll(str1 + i, str2)); WCSCHK(name, 0 != wcscoll(str2, str1 + i)); } } /* * stress_wcsxfrm() * stress on wcsxfrm */ static void stress_wcsxfrm( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { register size_t i; wchar_t buf[len1 + len2]; for (i = 0; i < len1 - 1; i++) { *buf = '\0'; WCSCHK(name, 0 != wcsxfrm(buf, str1, sizeof(buf))); *buf = '\0'; WCSCHK(name, 0 != wcsxfrm(buf, str2, sizeof(buf))); *buf = '\0'; WCSCHK(name, 0 != wcsxfrm(buf, str1, sizeof(buf))); WCSCHK(name, 0 != wcsxfrm(buf, str2, sizeof(buf))); *buf = '\0'; WCSCHK(name, 0 != wcsxfrm(buf, str2, sizeof(buf))); WCSCHK(name, 0 != wcsxfrm(buf, str1, sizeof(buf))); } } /* * stress_wcs_all() * iterate over all wcs stressors */ static void stress_wcs_all( const char *name, wchar_t *str1, const size_t len1, wchar_t *str2, const size_t len2) { static int i = 1; /* Skip over stress_wcs_all */ wcs_methods[i++].func(name, str1, len1, str2, len2); if (!wcs_methods[i].func) i = 1; } /* * Table of wcs stress methods */ static const stress_wcs_stressor_info_t wcs_methods[] = { { "all", stress_wcs_all }, /* Special "all" test */ { "wcscasecmp", stress_wcscasecmp }, { "wcscat", stress_wcscat }, { "wcschr", stress_wcschr }, { "wcscmp", stress_wcscmp }, { "wcscpy", stress_wcscpy }, { "wcslen", stress_wcslen }, { "wcsncasecmp", stress_wcsncasecmp }, { "wcsncat", stress_wcsncat }, { "wcsncmp", stress_wcsncmp }, { "wcsrchr", stress_wcsrchr }, { "wcscoll", stress_wcscoll }, { "wcsxfrm", stress_wcsxfrm }, { NULL, NULL } }; /* * stress_set_wcs_method() * set the specified wcs stress method */ int stress_set_wcs_method(const char *name) { stress_wcs_stressor_info_t const *wcsfunction = wcs_methods; for (wcsfunction = wcs_methods; wcsfunction->func; wcsfunction++) { if (!strcmp(wcsfunction->name, name)) { opt_wcs_stressor = wcsfunction; return 0; } } fprintf(stderr, "wcs-method must be one of:"); for (wcsfunction = wcs_methods; wcsfunction->func; wcsfunction++) { fprintf(stderr, " %s", wcsfunction->name); } fprintf(stderr, "\n"); return -1; } /* * stress_wcs() * stress CPU by doing wide character string ops */ int stress_wcs( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { stress_wcs_func func = opt_wcs_stressor->func; (void)instance; do { wchar_t str1[STR1LEN], str2[STR2LEN]; stress_wcs_fill(str1, STR1LEN); stress_wcs_fill(str2, STR2LEN); (void)func(name, str1, STR1LEN, str2, STR2LEN); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/parse-opts.c0000664000175000017500000001041712702231255014515 0ustar kingking/* * Copyright (C) 2013-2016 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; 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_unsigned_long() * string to unsigned long */ unsigned long get_unsigned_long(const char *const str) { unsigned long val; ensure_positive(str); if (sscanf(str, "%lu" , &val) != 1) { fprintf(stderr, "Invalid number %s\n", str); exit(EXIT_FAILURE); } return val; } /* * get_int32() * string to int */ int32_t get_int32(const char *const str) { int32_t val; if (sscanf(str, "%12" SCNd32, &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.05.23/stress-fp-error.c0000664000175000017500000000771712702231255015506 0ustar kingking/* * Copyright (C) 2013-2016 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 SET_VOLATILE(d, val) \ do { \ d = val; \ (void)&d; \ } while (0) \ static inline void stress_fp_clear_error(void) { errno = 0; feclearexcept(FE_ALL_EXCEPT); } static inline bool stress_double_same(const double d1, const double d2) { if (isnan(d1) && isnan(d2)) return true; if (isinf(d1) && isinf(d2)) return true; return d1 == d2; } static void stress_fp_check( const char *name, const char *expr, const double val, const double val_wanted, const int errno_wanted, const int excepts_wanted) { if (stress_double_same(val, val_wanted) && (fetestexcept(excepts_wanted) & excepts_wanted) && (errno == errno_wanted)) return; pr_fail(stderr, "%s: %s return was %f (expected %f), " "errno=%d (expected %d), " "excepts=%d (expected %d)\n", name, expr, val, val_wanted, errno, errno_wanted, fetestexcept(excepts_wanted), excepts_wanted); } /* * stress_fp_error() * stress floating point error handling */ int stress_fp_error( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; do { volatile double d1, d2; stress_fp_clear_error(); stress_fp_check(name, "log(-1.0)", log(-1.0), NAN, EDOM, FE_INVALID); stress_fp_clear_error(); stress_fp_check(name, "log(0.0)", log(0.0), -HUGE_VAL, ERANGE, FE_DIVBYZERO); stress_fp_clear_error(); stress_fp_check(name, "log2(-1.0)", log2(-1.0), NAN, EDOM, FE_INVALID); stress_fp_clear_error(); stress_fp_check(name, "log2(0.0)", log2(0.0), -HUGE_VAL, ERANGE, FE_DIVBYZERO); stress_fp_clear_error(); stress_fp_check(name, "sqrt(-1.0)", sqrt(-1.0), NAN, EDOM, FE_INVALID); stress_fp_clear_error(); stress_fp_check(name, "sqrt(-1.0)", sqrt(-1.0), NAN, EDOM, FE_INVALID); /* * Use volatiles to force compiler to generate code * to perform run time computation of 1.0 / M_PI */ stress_fp_clear_error(); SET_VOLATILE(d1, 1.0); SET_VOLATILE(d2, M_PI); stress_fp_check(name, "1.0 / M_PI", d1 / d2, d1 / d2, 0, FE_INEXACT); /* * Use volatiles to force compiler to generate code * to perform run time overflow computation */ stress_fp_clear_error(); SET_VOLATILE(d1, DBL_MAX); SET_VOLATILE(d2, DBL_MAX / 2.0); stress_fp_check(name, "DBL_MAX + DBL_MAX / 2.0", DBL_MAX + DBL_MAX / 2.0, INFINITY, 0, FE_OVERFLOW | FE_INEXACT); stress_fp_clear_error(); stress_fp_check(name, "exp(-1000000.0)", exp(-1000000.0), 0.0, ERANGE, FE_UNDERFLOW); stress_fp_clear_error(); stress_fp_check(name, "exp(DBL_MAX)", exp(DBL_MAX), HUGE_VAL, ERANGE, FE_OVERFLOW); if (fegetround() == -1) pr_fail(stderr, "%s: fegetround() returned -1\n", name); } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-hdd.c0000664000175000017500000004027412702231255014504 0ustar kingking/* * Copyright (C) 2013-2016 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 BUF_ALIGNMENT (4096) #define HDD_IO_VEC_MAX (16) /* Must be power of 2 */ /* 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) /* Other modes */ #define HDD_OPT_IOVEC (0x00100000) #define HDD_OPT_UTIMES (0x00200000) #define HDD_OPT_FSYNC (0x00400000) #define HDD_OPT_FDATASYNC (0x00800000) #define HDD_OPT_SYNCFS (0x01000000) static uint64_t opt_hdd_bytes = DEFAULT_HDD_BYTES; static uint64_t opt_hdd_write_size = DEFAULT_HDD_WRITE_SIZE; static bool set_hdd_bytes = false; static bool set_hdd_write_size = false; 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_RANDOM) && !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 #if _BSD_SOURCE || _XOPEN_SOURCE || _POSIX_C_SOURCE >= 200112L { "fsync", HDD_OPT_FSYNC, 0, 0, 0 }, #endif #if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 { "fdatasync", HDD_OPT_FDATASYNC, 0, 0, 0 }, #endif { "iovec", HDD_OPT_IOVEC, 0, 0, 0 }, #if defined(_GNU_SOURCE) && NEED_GLIBC(2,14,0) && defined(__linux__) { "syncfs", HDD_OPT_SYNCFS, 0, 0, 0 }, #endif { "utimes", HDD_OPT_UTIMES, 0, 0, 0 }, { NULL, 0, 0, 0, 0 } }; void stress_set_hdd_bytes(const char *optarg) { set_hdd_bytes = true; 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) { set_hdd_write_size = true; 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_write() * write with writev or write depending on mode */ static ssize_t stress_hdd_write(const int fd, uint8_t *buf, size_t count) { ssize_t ret; if (opt_hdd_flags & HDD_OPT_UTIMES) (void)futimes(fd, NULL); if (opt_hdd_flags & HDD_OPT_IOVEC) { struct iovec iov[HDD_IO_VEC_MAX]; size_t i; uint8_t *data = buf; const uint64_t sz = opt_hdd_write_size / HDD_IO_VEC_MAX; for (i = 0; i < HDD_IO_VEC_MAX; i++) { iov[i].iov_base = data; iov[i].iov_len = (size_t)sz; buf += sz; } ret = writev(fd, iov, HDD_IO_VEC_MAX); } else { ret = write(fd, buf, count); } #if _BSD_SOURCE || _XOPEN_SOURCE || _POSIX_C_SOURCE >= 200112L if (opt_hdd_flags & HDD_OPT_FSYNC) (void)fsync(fd); #endif #if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 if (opt_hdd_flags & HDD_OPT_FDATASYNC) (void)fdatasync(fd); #endif #if defined(_GNU_SOURCE) && NEED_GLIBC(2,14,0) && defined(__linux__) if (opt_hdd_flags & HDD_OPT_SYNCFS) (void)syncfs(fd); #endif return ret; } /* * stress_hdd_read() * read with readv or read depending on mode */ static ssize_t stress_hdd_read(const int fd, uint8_t *buf, size_t count) { if (opt_hdd_flags & HDD_OPT_UTIMES) (void)futimes(fd, NULL); if (opt_hdd_flags & HDD_OPT_IOVEC) { struct iovec iov[HDD_IO_VEC_MAX]; size_t i; uint8_t *data = buf; const uint64_t sz = opt_hdd_write_size / HDD_IO_VEC_MAX; for (i = 0; i < HDD_IO_VEC_MAX; i++) { iov[i].iov_base = data; iov[i].iov_len = (size_t)sz; buf += sz; } return readv(fd, iov, HDD_IO_VEC_MAX); } else { return read(fd, buf, count); } } /* * stress_hdd_opts * parse --hdd-opts option(s) list */ int stress_hdd_opts(char *opts) { char *str, *token; for (str = opts; (token = strtok(str, ",")) != 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_RANDOM) || \ 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_fail_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, min_size, remainder; 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 (!set_hdd_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_hdd_bytes = MAX_HDD_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_hdd_bytes = MIN_HDD_BYTES; } if (!set_hdd_write_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_hdd_write_size = MAX_HDD_WRITE_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_hdd_write_size = MIN_HDD_WRITE_SIZE; } if (opt_hdd_flags & HDD_OPT_O_DIRECT) { min_size = (opt_hdd_flags & HDD_OPT_IOVEC) ? HDD_IO_VEC_MAX * BUF_ALIGNMENT : MIN_HDD_WRITE_SIZE; } else { min_size = (opt_hdd_flags & HDD_OPT_IOVEC) ? HDD_IO_VEC_MAX * MIN_HDD_WRITE_SIZE : MIN_HDD_WRITE_SIZE; } /* Ensure I/O size is not too small */ if (opt_hdd_write_size < min_size) { opt_hdd_write_size = min_size; pr_inf(stderr, "%s: increasing read/write size to %" PRIu64 " bytes\n", name, opt_hdd_write_size); } /* Ensure we get same sized iovec I/O sizes */ remainder = opt_hdd_write_size % HDD_IO_VEC_MAX; if ((opt_hdd_flags & HDD_OPT_IOVEC) && (remainder != 0)) { opt_hdd_write_size += HDD_IO_VEC_MAX - remainder; pr_inf(stderr, "%s: increasing read/write size to %" PRIu64 " bytes in iovec mode\n", name, opt_hdd_write_size); } /* Ensure complete file size is not less than the I/O size */ if (opt_hdd_bytes < opt_hdd_write_size) { opt_hdd_bytes = opt_hdd_write_size; pr_inf(stderr, "%s: increasing file size to write size of %" PRIu64 " bytes\n", name, opt_hdd_bytes); } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); /* Must have some write option */ if ((opt_hdd_flags & HDD_OPT_WR_MASK) == 0) opt_hdd_flags |= HDD_OPT_WR_SEQ; /* Must have some read option */ if ((opt_hdd_flags & HDD_OPT_RD_MASK) == 0) opt_hdd_flags |= HDD_OPT_RD_SEQ; ret = posix_memalign((void **)&buf, BUF_ALIGNMENT, (size_t)opt_hdd_write_size); if (ret || !buf) { rc = exit_status(errno); pr_err(stderr, "%s: cannot allocate buffer\n", name); (void)stress_temp_dir_rm(name, pid, instance); return rc; } stress_strnrnd((char *)buf, opt_hdd_write_size); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); do { int fd; struct stat statbuf; uint64_t hdd_read_size; (void)umask(0077); if ((fd = open(filename, flags, S_IRUSR | S_IWUSR)) < 0) { if ((errno == ENOSPC) || (errno == ENOMEM)) continue; /* Retry */ pr_fail_err(name, "open"); goto finish; } if (ftruncate(fd, (off_t)0) < 0) { pr_fail_err(name, "ftruncate"); (void)close(fd); goto finish; } (void)unlink(filename); if (stress_hdd_advise(name, fd, fadvise_flags) < 0) { (void)close(fd); goto finish; } /* Random Write */ if (opt_hdd_flags & HDD_OPT_WR_RND) { for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { size_t j; off_t offset = (i == 0) ? opt_hdd_bytes : (mwc64() % opt_hdd_bytes) & ~511; ssize_t ret; if (lseek(fd, offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); (void)close(fd); goto finish; } rnd_wr_retry: if (!opt_do_run || (max_ops && *counter >= max_ops)) break; for (j = 0; j < opt_hdd_write_size; j++) buf[j] = (offset + j) & 0xff; ret = stress_hdd_write(fd, buf, (size_t)opt_hdd_write_size); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto rnd_wr_retry; if (errno == ENOSPC) break; if (errno) { pr_fail_err(name, "write"); (void)close(fd); goto finish; } continue; } (*counter)++; } } /* Sequential Write */ if (opt_hdd_flags & HDD_OPT_WR_SEQ) { for (i = 0; i < opt_hdd_bytes; i += opt_hdd_write_size) { ssize_t ret; size_t j; seq_wr_retry: if (!opt_do_run || (max_ops && *counter >= max_ops)) break; for (j = 0; j < opt_hdd_write_size; j += 512) buf[j] = (i + j) & 0xff; ret = stress_hdd_write(fd, buf, (size_t)opt_hdd_write_size); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto seq_wr_retry; if (errno == ENOSPC) break; if (errno) { pr_fail_err(name, "write"); (void)close(fd); goto finish; } continue; } (*counter)++; } } if (fstat(fd, &statbuf) < 0) { pr_fail_err(name, "fstat"); (void)close(fd); continue; } /* Round to write size to get no partial reads */ hdd_read_size = (uint64_t)statbuf.st_size - (statbuf.st_size % opt_hdd_write_size); /* Sequential Read */ if (opt_hdd_flags & HDD_OPT_RD_SEQ) { uint64_t misreads = 0; uint64_t baddata = 0; if (lseek(fd, 0, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); (void)close(fd); goto finish; } for (i = 0; i < hdd_read_size; i += opt_hdd_write_size) { ssize_t ret; seq_rd_retry: if (!opt_do_run || (max_ops && *counter >= max_ops)) break; ret = stress_hdd_read(fd, buf, (size_t)opt_hdd_write_size); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto seq_rd_retry; if (errno) { pr_fail_err(name, "read"); (void)close(fd); goto finish; } continue; } if (ret != (ssize_t)opt_hdd_write_size) misreads++; if (opt_flags & OPT_FLAGS_VERIFY) { size_t j; for (j = 0; j < opt_hdd_write_size; j += 512) { uint8_t v = (i + j) & 0xff; if (opt_hdd_flags & HDD_OPT_WR_SEQ) { /* Write seq has written to all of the file, so it should always be OK */ if (buf[0] != v) baddata++; } else { /* Write rnd has written to some of the file, so data either zero or OK */ if (buf[0] != 0 && buf[0] != v) baddata++; } } } (*counter)++; } if (misreads) pr_dbg(stderr, "%s: %" PRIu64 " incomplete sequential reads\n", name, misreads); if (baddata) pr_fail(stderr, "%s: incorrect data found %" PRIu64 " times\n", name, baddata); } /* Random Read */ if (opt_hdd_flags & HDD_OPT_RD_RND) { uint64_t misreads = 0; uint64_t baddata = 0; for (i = 0; i < hdd_read_size; i += opt_hdd_write_size) { ssize_t ret; off_t offset = (mwc64() % (opt_hdd_bytes - opt_hdd_write_size)) & ~511; if (lseek(fd, offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); (void)close(fd); goto finish; } rnd_rd_retry: if (!opt_do_run || (max_ops && *counter >= max_ops)) break; ret = stress_hdd_read(fd, buf, (size_t)opt_hdd_write_size); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto rnd_rd_retry; if (errno) { pr_fail_err(name, "read"); (void)close(fd); goto finish; } continue; } if (ret != (ssize_t)opt_hdd_write_size) misreads++; if (opt_flags & OPT_FLAGS_VERIFY) { size_t j; for (j = 0; j < opt_hdd_write_size; j += 512) { uint8_t v = (i + j) & 0xff; if (opt_hdd_flags & HDD_OPT_WR_SEQ) { /* Write seq has written to all of the file, so it should always be OK */ if (buf[0] != v) baddata++; } else { /* Write rnd has written to some of the file, so data either zero or OK */ if (buf[0] != 0 && buf[0] != v) baddata++; } } } (*counter)++; } if (misreads) pr_dbg(stderr, "%s: %" PRIu64 " incomplete random 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.05.23/stress-msg.c0000664000175000017500000000654712702231255014540 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MSG) #include #include #include #include #include #include #include #include #include #include #include #include #include #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_fail_dbg(name, "msgget"); return exit_status(errno); } pr_dbg(stderr, "System V message queue created, id: %d\n", msgq_id); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); while (opt_do_run) { 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_fail_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, "%s: msgrcv: expected msg containing 0x%" PRIx64 " but received 0x%" PRIx64 " instead\n", name, i, v); } } exit(EXIT_SUCCESS); } } else { msg_t msg; uint64_t i = 0; int status; /* Parent */ setpgid(pid, pgrp); do { memcpy(msg.msg, &i, sizeof(i)); msg.mtype = 1; if (msgsnd(msgq_id, &msg, sizeof(i), 0) < 0) { if (errno != EINTR) pr_fail_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_fail_dbg(name, "termination msgsnd"); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); if (msgctl(msgq_id, IPC_RMID, NULL) < 0) pr_fail_dbg(name, "msgctl"); else pr_dbg(stderr, "System V message queue deleted, id: %d\n", msgq_id); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/usr.bin.pulseaudio.eg0000664000175000017500000000466612702231255016333 0ustar kingking# Last Modified: Mon Dec 31 16:52:55 2012 #include /usr/bin/pulseaudio-eg { #include #include #include #include #include /usr/bin/pulseaudio mixr, /dev/null rw, /dev/random r, /dev/urandom r, /etc/pulse/ r, /etc/pulse/* r, /etc/udev/udev.conf r, /etc/timidity/.pulse_cookie w, @{HOME}/.esd_auth rwk, @{HOME}/.pulse-cookie rwk, @{HOME}/.config/pulse/cookie rwk, @{HOME}/{.config/pulse,.pulse}/ rw, @{HOME}/{.config/pulse,.pulse}/* rw, /run/pulse/ rw, /run/pulse/.pulse-cookie rwk, /run/pulse/dbus-socket rwk, /run/pulse/native rwk, /run/pulse/pid rwk, /run/udev/data/+sound:card* r, # logind /run/systemd/users/* r, /run/user/*/dconf/user k, /sys/bus/ r, /sys/class/ r, /sys/class/sound/ r, /sys/devices/pci[0-9]*/**/*class r, /sys/devices/pci[0-9]*/**/uevent r, /sys/devices/system/cpu/ r, /sys/devices/system/cpu/online r, /sys/devices/virtual/dmi/id/bios_vendor r, /sys/devices/virtual/dmi/id/board_vendor r, /sys/devices/virtual/dmi/id/sys_vendor r, /sys/devices/**/sound/card[0-9]*/uevent r, /usr/share/alsa/** r, /usr/share/applications/ r, /usr/share/applications/* r, /usr/share/pulseaudio/** r, /usr/lib/pulse-[2-9].[0-9]/modules/*.so mr, /usr/lib/pulseaudio/pulse/gconf-helper Cx, owner /var/lib/gdm3/.config/pulse/ rw, owner /var/lib/gdm3/.config/pulse/* rw, owner /var/lib/gdm3/.config/pulse/cookie rwk, owner /var/lib/lightdm/.Xauthority r, owner /var/lib/lightdm/.esd_auth rwk, owner /var/lib/lightdm/.pulse-cookie rwk, owner /var/lib/lightdm/.pulse/ rw, owner /var/lib/lightdm/.pulse/* w, owner /var/lib/lightdm/.pulse/* r, # are these needed? /var/lib/pulse/ rw, /var/lib/pulse/*-default-sink rw, /var/lib/pulse/*-default-source rw, /var/lib/pulse/*.tdb rw, @{PROC}/[0-9]*/fd/ r, @{PROC}/[0-9]*/maps r, @{PROC}/[0-9]*/stat r, owner /tmp/pulse-*/pid rwk, owner /tmp/pulse-*/native rwk, owner /tmp/pulse-*/autospawn.lock rwk, owner /tmp/orcexec.* mrw, owner /{,var/}run/user/[0-9]*/orcexec.* mrw, # needed if /tmp is mounted noexec: owner @{HOME}/orcexec.* mr, # replace with @{pid} owner /tmp/.esd-[0-9]*/ rw, owner /tmp/.esd-[0-9]*/socket rw, profile /usr/lib/pulseaudio/pulse/gconf-helper { #include /usr/lib/pulseaudio/pulse/gconf-helper mr, } } stress-ng-0.05.23/stress-get.c0000664000175000017500000001541012702231255014516 0ustar kingking/* * Copyright (C) 2013-2016 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 #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include #if defined(__linux__) #include #include #include #endif #include #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 const 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 sys_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) { const bool verify = (opt_flags & OPT_FLAGS_VERIFY); (void)instance; 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; struct utsname utsbuf; struct timex timexbuf; #endif const pid_t mypid = getpid(); int ret; size_t i; struct timeval tv; time_t t; check_do_run(); (void)getppid(); check_do_run(); ptr = getcwd(path, sizeof path); if (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 (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 (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 (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 (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 (verify && (ret < 0)) pr_fail(stderr, "%s: getrlimit(%zu, ..) failed, errno=%d (%s)\n", name, i, errno, strerror(errno)); check_do_run(); } #if defined(__linux__) for (i = 0; i < SIZEOF_ARRAY(rlimits); i++) { struct rlimit rlim[2]; ret = prlimit(mypid, rlimits[i], NULL, &rlim[0]); if (verify && (ret < 0)) pr_fail(stderr, "%s: prlimit(%d, %zu, ..) failed, errno=%d (%s)\n", name, mypid, i, errno, strerror(errno)); if (!ret) { prlimit(mypid, rlimits[i], &rlim[0], NULL); if (verify && (ret < 0)) pr_fail(stderr, "%s: prlimit(%d, %zu, ..) failed, errno=%d (%s)\n", name, mypid, i, errno, strerror(errno)); prlimit(mypid, rlimits[i], &rlim[0], &rlim[1]); if (verify && (ret < 0)) pr_fail(stderr, "%s: prlimit(%d, %zu, ..) failed, errno=%d (%s)\n", name, mypid, i, errno, strerror(errno)); } check_do_run(); } #endif for (i = 0; i < SIZEOF_ARRAY(rusages); i++) { struct rusage usage; ret = getrusage(rusages[i], &usage); if (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 (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)sys_gettid(); check_do_run(); #endif t = time(NULL); if (verify && (t == (time_t)-1)) pr_fail(stderr, "%s: time failed, errno=%d (%s)\n", name, errno, strerror(errno)); ret = gettimeofday(&tv, NULL); if (verify && (ret < 0)) pr_fail(stderr, "%s: gettimeval failed, errno=%d (%s)\n", name, errno, strerror(errno)); #if defined(__linux__) ret = uname(&utsbuf); if (verify && (ret < 0)) pr_fail(stderr, "%s: uname failed, errno=%d (%s)\n", name, errno, strerror(errno)); #endif #if defined(__linux__) timexbuf.modes = 0; ret = adjtimex(&timexbuf); if (verify && (ret < 0)) pr_fail(stderr, "%s: adjtimex failed, errno=%d (%s)\n", name, errno, strerror(errno)); #endif ret = adjtime(NULL, &tv); if (verify && (ret < 0)) pr_fail(stderr, "%s: adjtime 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.05.23/test-cap.c0000664000175000017500000000243412702231255014140 0ustar kingking/* * Copyright (C) 2013-2016 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 int main(void) { struct __user_cap_header_struct uch; struct __user_cap_data_struct ucd; uch.version = _LINUX_CAPABILITY_VERSION_3; uch.pid = getpid(); return capget(&uch, &ucd); } stress-ng-0.05.23/stress-socketpair.c0000664000175000017500000001076112702231255016107 0ustar kingking/* * Copyright (C) 2013-2016 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_SOCKET_PAIRS (32768) /* * socket_pair_memset() * set data to be incrementing chars from val upwards */ static inline void socket_pair_memset( uint8_t *buf, uint8_t val, const size_t sz) { register uint8_t *ptr; register uint8_t checksum = 0; for (ptr = buf + 1 ; ptr < buf + sz; *ptr++ = val++) checksum += val; *buf = checksum; } /* * socket_pair_memchk() * check data contains incrementing chars from val upwards */ static inline int socket_pair_memchk( uint8_t *buf, const size_t sz) { register uint8_t *ptr; register uint8_t checksum = 0; for (ptr = buf + 1; ptr < buf + sz; checksum += *ptr++) ; return !(checksum == *buf); } static void socket_pair_close( int fds[MAX_SOCKET_PAIRS][2], const int max, const int which) { int i; for (i = 0; i < max; i++) (void)close(fds[i][which]); } /* * stress_socket_pair * stress by heavy socket_pair I/O */ int stress_socket_pair( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; int socket_pair_fds[MAX_SOCKET_PAIRS][2], i, max; (void)instance; for (max = 0; max < MAX_SOCKET_PAIRS; max++) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair_fds[max]) < 0) break; } if (max == 0) { pr_fail_dbg(name, "socket_pair"); return EXIT_FAILURE; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; socket_pair_close(socket_pair_fds, max, 0); socket_pair_close(socket_pair_fds, max, 1); pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); socket_pair_close(socket_pair_fds, max, 1); while (opt_do_run) { uint8_t buf[SOCKET_PAIR_BUF]; ssize_t n; for (i = 0; opt_do_run && (i < max); i++) { n = read(socket_pair_fds[i][0], buf, sizeof(buf)); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno == ENFILE) /* Too many files! */ goto abort; if (errno == EMFILE) /* Occurs on socket shutdown */ goto abort; if (errno) { pr_fail_dbg(name, "read"); break; } continue; } if ((opt_flags & OPT_FLAGS_VERIFY) && socket_pair_memchk(buf, (size_t)n)) { pr_fail(stderr, "%s: socket_pair read error detected, " "failed to read expected data\n", name); } } } abort: socket_pair_close(socket_pair_fds, max, 0); exit(EXIT_SUCCESS); } else { uint8_t buf[SOCKET_PAIR_BUF]; int val = 0, status; setpgid(pid, pgrp); /* Parent */ socket_pair_close(socket_pair_fds, max, 0); do { for (i = 0; opt_do_run && (i < max); i++) { ssize_t ret; socket_pair_memset(buf, val++, sizeof(buf)); ret = write(socket_pair_fds[i][1], buf, sizeof(buf)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "write"); break; } continue; } (*counter)++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); for (i = 0; i < max; i++) { if (shutdown(socket_pair_fds[i][1], SHUT_RDWR) < 0) pr_fail_dbg(name, "socket shutdown"); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); socket_pair_close(socket_pair_fds, max, 1); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-getdent.c0000664000175000017500000001637312702231255015402 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_GETDENT) #include #include #include #include #include #include #include #include #define BUF_SIZE (256 * 1024) struct linux_dirent { unsigned long d_ino; /* Inode number */ unsigned long d_off; /* Offset to next linux_dirent */ unsigned short d_reclen; /* Length of this linux_dirent */ char d_name[]; /* Filename (null-terminated) */ }; struct linux_dirent64 { ino64_t d_ino; /* 64-bit inode number */ off64_t d_off; /* 64-bit offset to next structure */ unsigned short d_reclen; /* Size of this dirent */ unsigned char d_type; /* File type */ char d_name[]; /* Filename (null-terminated) */ }; typedef int (getdents_func)( const char *name, const char *path, const bool recurse, const int depth, uint64_t *counter, uint64_t max_ops, const size_t page_size); #if defined(__NR_getdents) static getdents_func stress_getdents_dir; #endif #if defined(__NR_getdents64) static getdents_func stress_getdents64_dir; #endif static getdents_func * getdents_funcs[] = { #if defined(__NR_getdents) stress_getdents_dir, #endif #if defined(__NR_getdents64) stress_getdents64_dir, #endif }; static inline int stress_getdents_rand( const char *name, const char *path, const bool recurse, const int depth, uint64_t *counter, uint64_t max_ops, const size_t page_size) { int ret = -ENOSYS; const size_t n = SIZEOF_ARRAY(getdents_funcs); size_t i, j = mwc32() % n; for (i = 0; i < n; i++) { getdents_func *func = getdents_funcs[j]; if (func) { ret = func(name, path, recurse, depth, counter, max_ops, page_size); if (ret == -ENOSYS) getdents_funcs[j] = NULL; else return ret; } j++; j = j % n; } pr_fail(stderr, "%s: getdents: errno=%d (%s)\n", name, -ret, strerror(-ret)); return ret; } /* * getdents syscall */ static inline int sys_getdents( unsigned int fd, struct linux_dirent *dirp, unsigned int count) { #if defined(__NR_getdents) return syscall(__NR_getdents, fd, dirp, count); #else (void)fd; (void)dirp; (void)count; errno = ENOSYS; return -1; #endif } /* * getdents64 syscall */ static inline int sys_getdents64( unsigned int fd, struct linux_dirent64 *dirp, unsigned int count) { #if defined(__NR_getdents64) return syscall(__NR_getdents64, fd, dirp, count); #else (void)fd; (void)dirp; (void)count; errno = ENOSYS; return -1; #endif } #if defined(__NR_getdents) /* * stress_getdents_dir() * read directory via the old 32 bit interface */ static int stress_getdents_dir( const char *name, const char *path, const bool recurse, const int depth, uint64_t *counter, uint64_t max_ops, const size_t page_size) { int fd, rc = 0; char *buf; size_t buf_sz; if (!opt_do_run || (max_ops && *counter >= max_ops)) return 0; fd = open(path, O_RDONLY | O_DIRECTORY); if (fd < 0) return 0; buf_sz = ((mwc32() % BUF_SIZE) + page_size) & ~(page_size - 1); buf = malloc(buf_sz); if (!buf) goto exit_close; do { int nread; char *ptr = buf; nread = sys_getdents(fd, (struct linux_dirent *)buf, buf_sz); if (nread < 0) { rc = -errno; goto exit_free; } if (nread == 0) break; (*counter)++; if (!recurse || depth < 1) continue; while (ptr < buf + nread) { struct linux_dirent *d = (struct linux_dirent *)ptr; unsigned char d_type = *(ptr + d->d_reclen - 1); if (d_type == DT_DIR && strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { char newpath[PATH_MAX]; snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name); rc = stress_getdents_rand(name, newpath, recurse, depth - 1, counter, max_ops, page_size); if (rc < 0) goto exit_free; } ptr += d->d_reclen; } } while (opt_do_run && (!max_ops || *counter < max_ops)); exit_free: free(buf); exit_close: (void)close(fd); return rc; } #endif #if defined(__NR_getdents64) /* * stress_getdents64_dir() * read directory via the 64 bit interface */ static int stress_getdents64_dir( const char *name, const char *path, const bool recurse, const int depth, uint64_t *counter, uint64_t max_ops, const size_t page_size) { int fd, rc = 0; char *buf; size_t buf_sz; if (!opt_do_run || (max_ops && *counter >= max_ops)) return 0; fd = open(path, O_RDONLY | O_DIRECTORY); if (fd < 0) return 0; buf_sz = ((mwc32() % BUF_SIZE) + page_size) & ~(page_size - 1); buf = malloc(buf_sz); if (!buf) goto exit_close; do { int nread; char *ptr = buf; nread = sys_getdents64(fd, (struct linux_dirent64 *)buf, buf_sz); if (nread < 0) { rc = -errno; goto exit_free; } if (nread == 0) break; (*counter)++; if (!recurse || depth < 1) continue; while (ptr < buf + nread) { struct linux_dirent64 *d = (struct linux_dirent64 *)ptr; if (d->d_type == DT_DIR && strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { char newpath[PATH_MAX]; snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name); rc = stress_getdents_rand(name, newpath, recurse, depth - 1, counter, max_ops, page_size); if (rc < 0) goto exit_free; } ptr += d->d_reclen; } } while (opt_do_run && (!max_ops || *counter < max_ops)); exit_free: free(buf); exit_close: (void)close(fd); return rc; } #endif /* * stress_getdent * stress reading directories */ int stress_getdent( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; (void)name; size_t page_size = stress_get_pagesize(); do { int ret; ret = stress_getdents_rand(name, "/proc", true, 8, counter, max_ops, page_size); if (ret == -ENOSYS) break; ret = stress_getdents_rand(name, "/dev", true, 1, counter, max_ops, page_size); if (ret == -ENOSYS) break; ret = stress_getdents_rand(name, "/tmp", true, 4, counter, max_ops, page_size); if (ret == -ENOSYS) break; ret = stress_getdents_rand(name, "/sys", true, 8, counter, max_ops, page_size); if (ret == -ENOSYS) break; ret = stress_getdents_rand(name, "/run", true, 2, counter, max_ops, page_size); if (ret == -ENOSYS) break; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-fiemap.c0000664000175000017500000001523412702231255015204 0ustar kingking/* * Copyright (C) 2016 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(STRESS_FIEMAP) #include #include #include #include #include #include #include #include #include #include #include #define MAX_FIEMAP_PROCS (4) /* Number of FIEMAP stressors */ static uint64_t opt_fiemap_size = DEFAULT_FIEMAP_SIZE; static bool set_fiemap_size = false; void stress_set_fiemap_size(const char *optarg) { set_fiemap_size = true; opt_fiemap_size = get_uint64_byte(optarg); check_range("fiemap-size", opt_fiemap_size, MIN_FIEMAP_SIZE, MAX_FIEMAP_SIZE); } /* * stress_fiemap_writer() * write data in random places and punch holes * in data in random places to try and maximize * extents in the file */ int stress_fiemap_writer( const char *name, const int fd, uint64_t *counters, const uint64_t max_ops) { uint8_t buf[1]; uint64_t len = (off_t)opt_fiemap_size - sizeof(buf); uint64_t counter; int rc = EXIT_FAILURE; #if defined(FALLOC_FL_PUNCH_HOLE) && \ defined(FALLOC_FL_KEEP_SIZE) bool punch_hole = true; #endif stress_strnrnd((char *)buf, sizeof(buf)); do { uint64_t offset; size_t i; counter = 0; offset = (mwc64() % len) & ~0x1fff; if (lseek(fd, (off_t)offset, SEEK_SET) < 0) break; if (write(fd, buf, sizeof(buf)) < 0) { if ((errno != EAGAIN) && (errno != EINTR)) { pr_fail_err(name, "write"); goto tidy; } } #if defined(FALLOC_FL_PUNCH_HOLE) && \ defined(FALLOC_FL_KEEP_SIZE) if (!punch_hole) continue; offset = mwc64() % len; if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, 8192) < 0) { if (errno == EOPNOTSUPP) punch_hole = false; } #endif for (i = 0; i < MAX_FIEMAP_PROCS; i++) counter += counters[i]; } while (opt_do_run && (!max_ops || counter < max_ops)); rc = EXIT_SUCCESS; tidy: (void)close(fd); return rc; } /* * stress_fiemap_ioctl() * exercise the FIEMAP ioctl */ void stress_fiemap_ioctl( const char *name, int fd, uint64_t *const counter, const uint64_t max_ops) { do { struct fiemap *fiemap, *tmp; size_t extents_size; fiemap = (struct fiemap *)calloc(1, sizeof(struct fiemap)); if (!fiemap) { pr_err(stderr, "Out of memory allocating fiemap\n"); break; } fiemap->fm_length = ~0; /* Find out how many extents there are */ if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { pr_fail_err(name, "FS_IOC_FIEMAP ioctl()\n"); free(fiemap); break; } /* Read in the extents */ extents_size = sizeof(struct fiemap_extent) * (fiemap->fm_mapped_extents); /* Resize fiemap to allow us to read in the extents */ tmp = (struct fiemap *)realloc(fiemap, sizeof(struct fiemap) + extents_size); if (!tmp) { pr_fail_err(name, "FS_IOC_FIEMAP ioctl()\n"); free(fiemap); break; } fiemap = tmp; memset(fiemap->fm_extents, 0, extents_size); fiemap->fm_extent_count = fiemap->fm_mapped_extents; fiemap->fm_mapped_extents = 0; if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { pr_fail_err(name, "FS_IOC_FIEMAP ioctl()\n"); free(fiemap); break; } free(fiemap); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * stress_fiemap_spawn() * helper to spawn off fiemap stressor */ static inline pid_t stress_fiemap_spawn( const char *name, const int fd, uint64_t *const counter, const uint64_t max_ops) { pid_t pid; pid = fork(); if (pid < 0) return -1; if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); stress_fiemap_ioctl(name, fd, counter, max_ops); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); return pid; } /* * stress_fiemap * stress fiemap IOCTL */ int stress_fiemap( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_FIEMAP_PROCS], mypid; int ret, fd, rc = EXIT_FAILURE, status; char filename[PATH_MAX]; size_t i; const size_t counters_sz = sizeof(uint64_t) * MAX_FIEMAP_PROCS; uint64_t *counters; uint64_t ops_per_proc = max_ops / MAX_FIEMAP_PROCS; uint64_t ops_remaining = max_ops % MAX_FIEMAP_PROCS; if (!set_fiemap_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_fiemap_size = MAX_SEEK_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_fiemap_size = MIN_SEEK_SIZE; } /* We need some share memory for counter accounting */ counters = mmap(NULL, counters_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (counters == MAP_FAILED) { pr_err(stderr, "%s: mmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_NO_RESOURCE; } memset(counters, 0, counters_sz); mypid = getpid(); ret = stress_temp_dir_mk(name, mypid, instance); if (ret < 0) { rc = exit_status(-ret); goto clean; } (void)stress_temp_filename(filename, sizeof(filename), name, mypid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto clean; } (void)unlink(filename); for (i = 0; i < MAX_FIEMAP_PROCS; i++) { uint64_t ops = ops_per_proc + ((i == 0) ? ops_remaining : 0); pids[i] = stress_fiemap_spawn(name, fd, &counters[i], ops); if (pids[i] < 0) goto fail; } rc = stress_fiemap_writer(name, fd, counters, max_ops); /* And reap stressors */ for (i = 0; i < MAX_FIEMAP_PROCS; i++) { (void)kill(pids[i], SIGKILL); (void)waitpid(pids[i], &status, 0); (*counter) += counters[i]; } fail: (void)close(fd); clean: (void)munmap(counters, counters_sz); (void)stress_temp_dir_rm(name, mypid, instance); return rc; } #endif stress-ng-0.05.23/stress-futex.c0000664000175000017500000000760512702231255015101 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_FUTEX) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define THRESHOLD (100000) /* * 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.futex[instance]; pid_t pid; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } if (pid > 0) { int status; setpgid(pid, pgrp); 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, "%s: futex wake failed: errno=%d (%s)\n", name, errno, strerror(errno)); } } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Kill waiter process */ (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); pr_dbg(stderr, "%s: futex timeouts: %" PRIu64 "\n", name, *timeout); } else { uint64_t threshold = THRESHOLD; setpgid(0, pgrp); stress_parent_died_alarm(); 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)++; if (*timeout > threshold) { /* Backoff for a short while and start again */ usleep(250000); threshold += THRESHOLD; } } else { if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: futex wait " "failed: errno=%d (%s)\n", name, errno, strerror(errno)); } (*counter)++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-personality.c0000664000175000017500000000500512702231255016307 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_PERSONALITY) #include #include #include #include #include /* Personalities are determined at build time */ static const unsigned long personalities[] = { #include "personality.h" }; /* * stress_personality() * stress system by rapid open/close calls */ int stress_personality( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t n = SIZEOF_ARRAY(personalities); bool failed[n]; (void)instance; memset(failed, 0, sizeof(failed)); if (n == 0) { pr_inf(stderr, "%s: no personalities to stress test\n", name); return EXIT_FAILURE; } pr_dbg(stderr, "%s: exercising %zu personalities\n", name, n); do { size_t i, fails = 0; for (i = 0; i < n; i++) { unsigned long p = personalities[i]; int ret; if (!opt_do_run) break; if (failed[i]) { fails++; continue; } ret = personality(p); if (ret < 0) { failed[i] = true; continue; } ret = personality(~0UL); if ((opt_flags & OPT_FLAGS_VERIFY) && (ret & 0xff) != (p & 0xff)) { pr_fail(stderr, "%s: fetched personality does " "not match set personality 0x%lu\n", name, p); } } if (fails == n) { pr_fail(stderr, "%s: all %zu personalities failed " "to be set\n", name, fails); break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-lockf.c0000664000175000017500000001556212702231255015045 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_LOCKF) #include #include #include #include #include #include #include #include #include #include #include #define LOCK_FILE_SIZE (64 * 1024) #define LOCK_SIZE (8) #define LOCK_MAX (1024) typedef struct lockf_info { off_t offset; struct lockf_info *next; } lockf_info_t; typedef struct { lockf_info_t *head; /* Head of lockf_info procs list */ lockf_info_t *tail; /* Tail of lockf_info procs list */ lockf_info_t *free; /* List of free'd lockf_infos */ uint64_t length; /* Length of list */ } lockf_info_list_t; static lockf_info_list_t lockf_infos; /* * stress_lockf_info_new() * allocate a new lockf_info, add to end of list */ static lockf_info_t *stress_lockf_info_new(void) { lockf_info_t *new; if (lockf_infos.free) { /* Pop an old one off the free list */ new = lockf_infos.free; lockf_infos.free = new->next; new->next = NULL; } else { new = calloc(1, sizeof(*new)); if (!new) return NULL; } if (lockf_infos.head) lockf_infos.tail->next = new; else lockf_infos.head = new; lockf_infos.tail = new; lockf_infos.length++; return new; } /* * stress_lockf_info_head_remove * reap a lockf_info and remove a lockf_info from head of list, put it onto * the free lockf_info list */ static void stress_lockf_info_head_remove(void) { if (lockf_infos.head) { lockf_info_t *head = lockf_infos.head; if (lockf_infos.tail == lockf_infos.head) { lockf_infos.tail = NULL; lockf_infos.head = NULL; } else { lockf_infos.head = head->next; } /* Shove it on the free list */ head->next = lockf_infos.free; lockf_infos.free = head; lockf_infos.length--; } } /* * stress_lockf_info_free() * free the lockf_infos off the lockf_info head and free lists */ static void stress_lockf_info_free(void) { while (lockf_infos.head) { lockf_info_t *next = lockf_infos.head->next; free(lockf_infos.head); lockf_infos.head = next; } while (lockf_infos.free) { lockf_info_t *next = lockf_infos.free->next; free(lockf_infos.free); lockf_infos.free = next; } } /* * stress_lockf_unlock() * pop oldest lock record off list and unlock it */ static int stress_lockf_unlock(const char *name, const int fd) { /* Pop one off list */ if (!lockf_infos.head) return 0; if (lseek(fd, lockf_infos.head->offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); return -1; } stress_lockf_info_head_remove(); if (lockf(fd, F_ULOCK, LOCK_SIZE) < 0) { pr_fail_err(name, "lockf unlock"); return -1; } return 0; } /* * stress_lockf_contention() * hammer lock/unlock to create some file lock contention */ static int stress_lockf_contention( const char *name, const int fd, uint64_t *const counter, const uint64_t max_ops) { const int lockf_cmd = (opt_flags & OPT_FLAGS_LOCKF_NONBLK) ? F_TLOCK : F_LOCK; mwc_reseed(); do { off_t offset; int rc; lockf_info_t *lockf_info; if (lockf_infos.length >= LOCK_MAX) if (stress_lockf_unlock(name, fd) < 0) return -1; offset = mwc64() % (LOCK_FILE_SIZE - LOCK_SIZE); if (lseek(fd, offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); return -1; } rc = lockf(fd, lockf_cmd, LOCK_SIZE); if (rc < 0) { if (stress_lockf_unlock(name, fd) < 0) return -1; continue; } /* Locked OK, add to lock list */ lockf_info = stress_lockf_info_new(); if (!lockf_info) { pr_fail_err(name, "calloc"); return -1; } lockf_info->offset = offset; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return 0; } /* * 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 pid = getpid(), cpid = -1; char filename[PATH_MAX]; char dirname[PATH_MAX]; char buffer[4096]; off_t offset; ssize_t rc; 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, pid, instance); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { ret = exit_status(errno); pr_fail_err(name, "mkdir"); return ret; } } /* * 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, pid, instance, mwc32()); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { ret = exit_status(errno); pr_fail_err(name, "open"); (void)rmdir(dirname); return ret; } if (lseek(fd, 0, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); goto tidy; } for (offset = 0; offset < LOCK_FILE_SIZE; offset += sizeof(buffer)) { redo: if (!opt_do_run) { ret = EXIT_SUCCESS; goto tidy; } rc = write(fd, buffer, sizeof(buffer)); if ((rc < 0) || (rc != sizeof(buffer))) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; ret = exit_status(errno); pr_fail_err(name, "write"); goto tidy; } } again: cpid = fork(); if (cpid < 0) { if (!opt_do_run) { ret = EXIT_SUCCESS; goto tidy; } if (errno == EAGAIN) goto again; pr_fail_err(name, "fork"); goto tidy; } if (cpid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); if (stress_lockf_contention(name, fd, counter, max_ops) < 0) exit(EXIT_FAILURE); stress_lockf_info_free(); exit(EXIT_SUCCESS); } setpgid(cpid, pgrp); if (stress_lockf_contention(name, fd, counter, max_ops) == 0) ret = EXIT_SUCCESS; tidy: if (cpid > 0) { int status; (void)kill(cpid, SIGKILL); (void)waitpid(cpid, &status, 0); } stress_lockf_info_free(); (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return ret; } #endif stress-ng-0.05.23/stress-spawn.c0000664000175000017500000000546112702231255015074 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #include #if defined(STRESS_SPAWN) /* * stress_spawn() * stress by forking and spawn'ing */ int stress_spawn( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char path[PATH_MAX + 1]; ssize_t len; uint64_t spawn_fails = 0, spawn_calls = 0; static char *argv_new[] = { NULL, "--exec-exit", NULL }; static char *env_new[] = { NULL }; (void)instance; /* * Don't want to run this when running as root as * this could allow somebody to try and run another * spawnutable as root. */ if (geteuid() == 0) { pr_inf(stderr, "%s: running as root, won't run test.\n", name); return EXIT_FAILURE; } /* * Determine our own self as the spawnutable, e.g. run stress-ng */ len = readlink("/proc/self/exe", path, sizeof(path)); if (len < 0 || len > PATH_MAX) { pr_fail(stderr, "%s: readlink on /proc/self/exe failed\n", name); return EXIT_FAILURE; } path[len] = '\0'; argv_new[0] = path; do { int ret; pid_t pid; spawn_calls++; ret = posix_spawn(&pid, path, NULL, NULL, argv_new, env_new); if (ret < 0) { pr_fail_err(name, "posix_spawn()"); spawn_fails++; } else { int status; /* Parent, wait for child */ (void)waitpid(pid, &status, 0); (*counter)++; if (WEXITSTATUS(status) != EXIT_SUCCESS) spawn_fails++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); if ((spawn_fails > 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: %" PRIu64 " spawns failed (%.2f%%)\n", name, spawn_fails, (double)spawn_fails * 100.0 / (double)(spawn_calls)); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-rename.c0000664000175000017500000000576512702231255015222 0ustar kingking/* * Copyright (C) 2013-2016 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(); const uint32_t inst1 = instance * 2; const uint32_t inst2 = inst1 + 1; if (stress_temp_dir_mk(name, pid, inst1) < 0) return EXIT_FAILURE; if (stress_temp_dir_mk(name, pid, inst2) < 0) { (void)stress_temp_dir_rm(name, pid, inst1); return EXIT_FAILURE; } restart: (void)stress_temp_filename(oldname, PATH_MAX, name, pid, inst1, i++); if ((fp = fopen(oldname, "w+")) == NULL) { int rc = exit_status(errno); pr_err(stderr, "%s: fopen failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, inst1); (void)stress_temp_dir_rm(name, pid, inst2); return rc; } (void)fclose(fp); for (;;) { (void)stress_temp_filename(newname, PATH_MAX, name, pid, inst2, i++); if (rename(oldname, newname) < 0) { (void)unlink(oldname); (void)unlink(newname); goto restart; } tmpname = oldname; oldname = newname; newname = tmpname; (*counter)++; if (!opt_do_run || (!max_ops || *counter >= max_ops)) break; (void)stress_temp_filename(newname, PATH_MAX, name, pid, inst1, i++); if (rename(oldname, newname) < 0) { (void)unlink(oldname); (void)unlink(newname); goto restart; } tmpname = oldname; oldname = newname; newname = tmpname; (*counter)++; if (!opt_do_run || (!max_ops || *counter >= max_ops)) break; } (void)unlink(oldname); (void)unlink(newname); (void)stress_temp_dir_rm(name, pid, inst1); (void)stress_temp_dir_rm(name, pid, inst2); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-chdir.c0000664000175000017500000000612212702231255015030 0ustar kingking/* * Copyright (C) 2013-2016 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_chdir * stress chdir calls */ int stress_chdir( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); uint64_t i; char path[PATH_MAX], cwd[PATH_MAX]; int rc, ret = EXIT_FAILURE; char *paths[DEFAULT_DIRS]; memset(paths, 0, sizeof(paths)); if (getcwd(cwd, sizeof(cwd)) == NULL) { pr_fail_err(name, "getcwd"); return ret; } rc = stress_temp_dir_mk(name, pid, instance); if (rc < 0) return exit_status(-rc); /* Populate */ for (i = 0; i < DEFAULT_DIRS; i++) { uint64_t gray_code = (i >> 1) ^ i; (void)stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); paths[i] = strdup(path); if (paths[i] == NULL) goto abort; rc = mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR); if (rc < 0) { ret = exit_status(errno); pr_fail_err(name, "mkdir"); goto abort; } if (!opt_do_run) goto done; } do { for (i = 0; i < DEFAULT_DIRS; i++) { if (!opt_do_run || (max_ops && *counter >= max_ops)) goto done; if (chdir(paths[i]) < 0) { if (errno != ENOMEM) { pr_fail_err(name, "chdir"); goto abort; } } redo: if (!opt_do_run || (max_ops && *counter >= max_ops)) goto done; /* We need chdir to cwd to always succeed */ if (chdir(cwd) < 0) { if (errno == ENOMEM) /* Maybe low memory, force retry */ goto redo; pr_fail_err(name, "chdir"); goto abort; } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); done: ret = EXIT_SUCCESS; abort: if (chdir(cwd) < 0) pr_fail_err(name, "chdir"); /* force unlink of all files */ pr_tidy(stderr, "%s: removing %" PRIu32 " directories\n", name, DEFAULT_DIRS); for (i = 0; (i < DEFAULT_DIRS) && paths[i] ; i++) { (void)rmdir(paths[i]); free(paths[i]); } (void)stress_temp_dir_rm(name, pid, instance); return ret; } stress-ng-0.05.23/stress-fifo.c0000664000175000017500000001235112702231255014663 0ustar kingking/* * Copyright (C) 2013-2016 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 "stress-ng.h" static uint64_t opt_fifo_readers = DEFAULT_FIFO_READERS; static bool set_fifo_readers = false; void stress_set_fifo_readers(const char *optarg) { set_fifo_readers = true; 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 pid_t 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) { setpgid(0, pgrp); stress_parent_died_alarm(); func(name, fifoname); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); return pid; } /* * stress_fifo_readers() * read fifo */ 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 | O_NONBLOCK); if (fd < 0) { pr_err(stderr, "%s: fifo read open failed: errno=%d (%s)\n", name, errno, strerror(errno)); return; } while (opt_do_run) { ssize_t sz; int ret; struct timeval timeout; fd_set rdfds; FD_ZERO(&rdfds); FD_SET(fd, &rdfds); timeout.tv_sec = 10; timeout.tv_usec = 0; ret = select(fd + 1, &rdfds, NULL, NULL, &timeout); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_err(stderr, "%s: select failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } else if (ret == 0) { pr_err(stderr, "%s: read timeout!\n", name); break; } sz = read(fd, &val, sizeof(val)); if (sz < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; 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 (!set_fifo_readers) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_fifo_readers = MAX_FIFO_READERS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_fifo_readers = MIN_FIFO_READERS; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(fifoname, sizeof(fifoname), name, pid, instance, mwc32()); (void)umask(0077); if (mkfifo(fifoname, S_IRUSR | S_IWUSR) < 0) { ret = exit_status(errno); 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; if (!opt_do_run) { ret = EXIT_SUCCESS; goto reap; } } fd = open(fifoname, O_WRONLY); if (fd < 0) { ret = exit_status(fd); pr_err(stderr, "%s: fifo write open failed: errno=%d (%s)\n", name, errno, strerror(errno)); goto reap; } do { ssize_t ret; ret = write(fd, &val, sizeof(val)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "write"); break; } continue; } 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); (void)waitpid(pids[i], &status, 0); } } tidy: (void)unlink(fifoname); (void)stress_temp_dir_rm(name, pid, instance); return ret; } stress-ng-0.05.23/stress-memcpy.c0000664000175000017500000000341712702231255015235 0ustar kingking/* * Copyright (C) 2013-2016 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[STR_SHARED_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) { uint8_t *str_shared = shared->str_shared; (void)instance; (void)name; do { memcpy(buffer, str_shared, STR_SHARED_SIZE); memcpy(str_shared, buffer, STR_SHARED_SIZE); memmove(buffer, buffer + 64, STR_SHARED_SIZE - 64); memmove(buffer + 64, buffer, STR_SHARED_SIZE - 64); memmove(buffer + 1, buffer, STR_SHARED_SIZE - 1); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-mremap.c0000664000175000017500000001227412702231255015225 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MREMAP) #include #include #include #include #include #include #include #include #include #include static size_t opt_mremap_bytes = DEFAULT_MREMAP_BYTES; static bool set_mremap_bytes = false; void stress_set_mremap_bytes(const char *optarg) { set_mremap_bytes = true; opt_mremap_bytes = (size_t)get_uint64_byte(optarg); check_range("mmap-bytes", opt_mremap_bytes, MIN_MREMAP_BYTES, MAX_MREMAP_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, const size_t page_size) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += page_size) { if (!opt_do_run) break; for (j = 0; j < page_size; j++) if (*ptr++ != val++) return -1; val++; } return 0; } static void stress_mremap_set( uint8_t *buf, const size_t sz, const size_t page_size) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += page_size) { if (!opt_do_run) break; for (j = 0; j < page_size; 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(); size_t sz, new_sz, old_sz; int flags = MAP_PRIVATE | MAP_ANONYMOUS; (void)instance; #ifdef MAP_POPULATE flags |= MAP_POPULATE; #endif if (!set_mremap_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_mremap_bytes = MAX_MREMAP_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_mremap_bytes = MIN_MREMAP_BYTES; } new_sz = sz = opt_mremap_bytes & ~(page_size - 1); /* 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, page_size); if (stress_mremap_check(buf, sz, page_size) < 0) { pr_fail(stderr, "%s: mmap'd region of %zu " "bytes does not contain expected data\n", name, 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, page_size) < 0) { pr_fail(stderr, "%s: mremap'd region " "of %zu bytes does " "not contain expected data\n", name, 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.05.23/stress-sigsegv.c0000664000175000017500000000422212702231255015405 0ustar kingking/* * Copyright (C) 2013-2016 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 MLOCKED 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 (;;) { int ret; if (stress_sighandler(name, SIGSEGV, stress_segvhandler, NULL) < 0) return EXIT_FAILURE; if (stress_sighandler(name, SIGILL, stress_segvhandler, NULL) < 0) 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.05.23/stress-zero.c0000664000175000017500000000355112702231255014721 0ustar kingking/* * Copyright (C) 2013-2016 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_fail_err(name, "open"); return EXIT_FAILURE; } do { char buffer[4096]; ssize_t ret; ret = read(fd, buffer, sizeof(buffer)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_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.05.23/mlock.c0000664000175000017500000000322212702231255013521 0ustar kingking/* * Copyright (C) 2013-2016 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" /* * stress_mlock_region * mlock a region of memory so it can't be swapped out * - used to lock sighandlers for faster response */ int stress_mlock_region(const void *addr_start, const void *addr_end) { const size_t page_size = stress_get_pagesize(); const void *m_addr_start = (void *)((ptrdiff_t)addr_start & ~(page_size - 1)); const void *m_addr_end = (void *)(((ptrdiff_t)addr_end + page_size - 1) & ~(page_size - 1)); const size_t len = (ptrdiff_t)m_addr_end - (ptrdiff_t)m_addr_start; return mlock(m_addr_start, len); } stress-ng-0.05.23/test-librt.c0000664000175000017500000000367712702231255014523 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include #include #include #include #include /* The following functions from librt are used by stress-ng */ static void *rt_funcs[] = { #if defined(__linux__) (void *)timer_create, (void *)timer_settime, (void *)timer_gettime, (void *)timer_getoverrun, (void *)timer_delete, #endif #if defined(__linux__) && \ defined(__NR_io_setup) && \ defined(__NR_io_destroy) && \ defined(__NR_io_submit) && \ defined(__NR_io_getevents) (void *)aio_write, (void *)aio_error, (void *)aio_cancel, (void *)aio_read, (void *)aio_write, #endif #if defined(__linux__) (void *)mq_open, (void *)mq_send, (void *)mq_send, (void *)mq_close, (void *)mq_unlink, (void *)mq_receive, (void *)mq_timedreceive, (void *)mq_getattr, #endif (void *)shm_open, (void *)shm_unlink, (void *)shm_unlink, }; int main(void) { return 0; } stress-ng-0.05.23/stress-handle.c0000664000175000017500000001067512702231255015202 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_HANDLE) #include #include #include #include #include #include #include #include #define MAX_MOUNT_IDS (1024) #define FILENAME "/dev/zero" typedef struct { char *mount_path; int mount_id; } mount_info_t; static mount_info_t mount_info[MAX_MOUNT_IDS]; void free_mount_info(const int mounts) { int i; for (i = 0; i < mounts; i++) free(mount_info[i].mount_path); } int get_mount_info(const char *name) { FILE *fp; int mounts = 0; if ((fp = fopen("/proc/self/mountinfo", "r")) == NULL) { pr_dbg(stderr, "%s: cannot open /proc/self/mountinfo\n", name); return -1; } for (;;) { char mount_path[PATH_MAX]; char *line = NULL; size_t line_len = 0; ssize_t nread = getline(&line, &line_len, fp); if (nread == -1) break; nread = sscanf(line, "%12d %*d %*s %*s %s", &mount_info[mounts].mount_id, mount_path); if (nread != 2) continue; mount_info[mounts].mount_path = strdup(mount_path); if (mount_info[mounts].mount_path == NULL) { pr_dbg(stderr, "%s: cannot allocate mountinfo mount path\n", name); free_mount_info(mounts); mounts = -1; break; } mounts++; } fclose(fp); return mounts; } /* * stress_handle() * stress system by rapid open/close calls via * name_to_handle_at and open_by_handle_at */ int stress_handle( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int mounts; (void)instance; if ((mounts = get_mount_info(name)) < 0) { pr_fail(stderr, "%s: failed to parse /proc/self/mountinfo\n", name); return EXIT_FAILURE; } do { struct file_handle *fhp, *tmp; int mount_id, mount_fd, fd, i; if ((fhp = malloc(sizeof(*fhp))) == NULL) continue; fhp->handle_bytes = 0; if ((name_to_handle_at(AT_FDCWD, FILENAME, fhp, &mount_id, 0) != -1) && (errno != EOVERFLOW)) { pr_fail(stderr, "%s: name_to_handle_at: failed to get file handle size: errno=%d (%s)\n", name, errno, strerror(errno)); free(fhp); break; } tmp = realloc(fhp, sizeof(struct file_handle) + fhp->handle_bytes); if (tmp == NULL) { free(fhp); continue; } fhp = tmp; if (name_to_handle_at(AT_FDCWD, FILENAME, fhp, &mount_id, 0) < 0) { pr_fail(stderr, "%s: name_to_handle_at: failed to get file handle: errno=%d (%s)\n", name, errno, strerror(errno)); free(fhp); break; } mount_fd = -2; for (i = 0; i < mounts; i++) { if (mount_info[i].mount_id == mount_id) { mount_fd = open(mount_info[i].mount_path, O_RDONLY); break; } } if (mount_fd == -2) { pr_fail(stderr, "%s: cannot find mount id %d\n", name, mount_id); free(fhp); break; } if (mount_fd < 0) { pr_fail(stderr, "%s: failed to open mount path '%s': errno=%d (%s)\n", name, mount_info[i].mount_path, errno, strerror(errno)); free(fhp); break; } if ((fd = open_by_handle_at(mount_fd, fhp, O_RDONLY)) < 0) { /* We don't abort if EPERM occurs, that's not a test failure */ if (errno != EPERM) { pr_fail(stderr, "%s: open_by_handle_at: failed to open: errno=%d (%s)\n", name, errno, strerror(errno)); (void)close(mount_fd); free(fhp); break; } } else { (void)close(fd); } (void)close(mount_fd); free(fhp); } while (opt_do_run && (!max_ops || *counter < max_ops)); free_mount_info(mounts); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-readahead.c0000664000175000017500000001317512702231255015643 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_READAHEAD) #include #include #include #include #include #include #include #include #define BUF_ALIGNMENT (4096) #define BUF_SIZE (512) #define MAX_OFFSETS (16) static uint64_t opt_readahead_bytes = DEFAULT_READAHEAD_BYTES; static bool set_readahead_bytes = false; void stress_set_readahead_bytes(const char *optarg) { set_readahead_bytes = true; opt_readahead_bytes = get_uint64_byte(optarg); check_range("hdd-bytes", opt_readahead_bytes, MIN_HDD_BYTES, MAX_HDD_BYTES); } int do_readahead( const char *name, const int fd, off_t *offsets, const uint64_t readahead_bytes) { int i; for (i = 0; i < MAX_OFFSETS; i++) { offsets[i] = (mwc64() % (readahead_bytes - BUF_SIZE)) & ~511; if (readahead(fd, offsets[i], BUF_SIZE) < 0) { pr_fail_err(name, "ftruncate"); return -1; } } return 0; } /* * stress_readahead * stress file system cache via readahead calls */ int stress_readahead( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *buf = NULL; uint64_t readahead_bytes, i; uint64_t misreads = 0; uint64_t baddata = 0; const pid_t pid = getpid(); int ret, rc = EXIT_FAILURE; char filename[PATH_MAX]; int flags = O_CREAT | O_RDWR | O_TRUNC; int fd; struct stat statbuf; if (!set_readahead_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_readahead_bytes = MAX_HDD_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_readahead_bytes = MIN_HDD_BYTES; } if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; ret = posix_memalign((void **)&buf, BUF_ALIGNMENT, BUF_SIZE); if (ret || !buf) { rc = exit_status(errno); pr_err(stderr, "%s: cannot allocate buffer\n", name); (void)stress_temp_dir_rm(name, pid, instance); return rc; } (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, flags, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto finish; } if (ftruncate(fd, (off_t)0) < 0) { rc = exit_status(errno); pr_fail_err(name, "ftruncate"); goto close_finish; } (void)unlink(filename); #if (defined(POSIX_FADV_SEQ) || defined(POSIX_FADV_RANDOM) || \ defined(POSIX_FADV_NOREUSE) || defined(POSIX_FADV_WILLNEED) || \ defined(POSIX_FADV_DONTNEED)) && !defined(__gnu_hurd__) if (posix_fadvise(fd, 0, opt_readahead_bytes, POSIX_FADV_DONTNEED) < 0) { pr_fail_err(name, "posix_fadvise"); goto close_finish; } #endif /* Sequential Write */ for (i = 0; i < opt_readahead_bytes; i += BUF_SIZE) { ssize_t ret; size_t j; off_t o = i / BUF_SIZE; seq_wr_retry: if (!opt_do_run) { pr_inf(stderr, "%s: test expired during test setup " "(writing of data file)\n", name); rc = EXIT_SUCCESS; goto close_finish; } for (j = 0; j < BUF_SIZE; j++) buf[j] = (o + j) & 0xff; ret = pwrite(fd, buf, BUF_SIZE, i); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto seq_wr_retry; if (errno == ENOSPC) break; if (errno) { pr_fail_err(name, "pwrite"); goto close_finish; } continue; } } if (fstat(fd, &statbuf) < 0) { pr_fail_err(name, "fstat"); goto close_finish; } /* Round to write size to get no partial reads */ readahead_bytes = (uint64_t)statbuf.st_size - (statbuf.st_size % BUF_SIZE); do { off_t offsets[MAX_OFFSETS]; if (do_readahead(name, fd, offsets, readahead_bytes) < 0) goto close_finish; for (i = 0; i < MAX_OFFSETS; i++) { rnd_rd_retry: if (!opt_do_run || (max_ops && *counter >= max_ops)) break; ret = pread(fd, buf, BUF_SIZE, offsets[i]); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto rnd_rd_retry; if (errno) { pr_fail_err(name, "read"); goto close_finish; } continue; } if (ret != BUF_SIZE) misreads++; if (opt_flags & OPT_FLAGS_VERIFY) { size_t j; off_t o = offsets[i] / BUF_SIZE; for (j = 0; j < BUF_SIZE; j++) { uint8_t v = (o + j) & 0xff; if (buf[j] != v) baddata++; } if (baddata) { pr_fail(stderr, "error in data between %ju and %ju\n", (intmax_t)offsets[i], (intmax_t)offsets[i] + BUF_SIZE - 1); } } (*counter)++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; close_finish: (void)close(fd); finish: free(buf); (void)stress_temp_dir_rm(name, pid, instance); if (misreads) pr_dbg(stderr, "%s: %" PRIu64 " incomplete random reads\n", name, misreads); return rc; } #endif stress-ng-0.05.23/stress-aio-linux.c0000664000175000017500000001133312702231255015644 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_AIO_LINUX) #include #include #include #include #include #include #include #include #include #include #define BUFFER_SZ (4096) static uint32_t opt_aio_linux_requests = DEFAULT_AIO_LINUX_REQUESTS; static bool set_aio_linux_requests = false; void stress_set_aio_linux_requests(const char *optarg) { uint32_t aio_linux_requests; set_aio_linux_requests = true; aio_linux_requests = get_unsigned_long(optarg); check_range("aiol-requests", aio_linux_requests, MIN_AIO_LINUX_REQUESTS, MAX_AIO_LINUX_REQUESTS); opt_aio_linux_requests = aio_linux_requests; } /* * aio_linux_fill_buffer() * fill buffer with some known pattern */ static inline void aio_linux_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] = (uint8_t)(request + i); } /* * stress_aio_linux * stress asynchronous I/O using the linux specific aio ABI */ int stress_aio_linux( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd, ret, rc = EXIT_FAILURE; char filename[PATH_MAX]; const pid_t pid = getpid(); io_context_t ctx = 0; if (!set_aio_linux_requests) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_aio_linux_requests = MAX_AIO_REQUESTS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_aio_linux_requests = MIN_AIO_REQUESTS; } if ((opt_aio_linux_requests < MIN_AIO_REQUESTS) || (opt_aio_linux_requests > MAX_AIO_REQUESTS)) { pr_err(stderr, "%s: iol_requests out of range", name); return EXIT_FAILURE; } if (io_setup(opt_aio_linux_requests, &ctx) < 0) { pr_fail_err(name, "io_setup"); return EXIT_FAILURE; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto finish; } (void)unlink(filename); do { struct iocb cb[opt_aio_linux_requests]; struct iocb *cbs[opt_aio_linux_requests]; struct io_event events[opt_aio_linux_requests]; uint8_t buffers[opt_aio_linux_requests][BUFFER_SZ]; uint32_t i; int ret; long n; for (i = 0; i < opt_aio_linux_requests; i++) aio_linux_fill_buffer(i, buffers[i], BUFFER_SZ); memset(cb, 0, sizeof(cb)); for (i = 0; i < opt_aio_linux_requests; i++) { cb[i].aio_fildes = fd; cb[i].aio_lio_opcode = IO_CMD_PWRITE; cb[i].u.c.buf = buffers[i]; cb[i].u.c.offset = mwc16() * BUFFER_SZ; cb[i].u.c.nbytes = BUFFER_SZ; cbs[i] = &cb[i]; } ret = io_submit(ctx, (long)opt_aio_linux_requests, cbs); if (ret < 0) { if (errno == EAGAIN) continue; pr_fail_err(name, "io_submit"); break; } n = opt_aio_linux_requests; do { struct timespec timeout, *timeout_ptr; if (clock_gettime(CLOCK_REALTIME, &timeout) < 0) { timeout_ptr = NULL; } else { timeout.tv_nsec += 1000000; if (timeout.tv_nsec > 1000000000) { timeout.tv_nsec -= 1000000000; timeout.tv_sec++; } timeout_ptr = &timeout; } ret = io_getevents(ctx, 1, n, events, timeout_ptr); if (ret < 0) { if ((errno == EINTR) && (opt_do_run)) continue; pr_fail_err(name, "io_getevents"); break; } else { n -= ret; } } while ((n > 0) && opt_do_run); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; (void)close(fd); finish: (void)io_destroy(ctx); (void)stress_temp_dir_rm(name, pid, instance); return rc; } #endif stress-ng-0.05.23/stress-tee.c0000664000175000017500000001071112702231255014513 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_TEE) #include #include #include #include #include #include #include #include #include #include #include #define TEE_IO_SIZE (65536) /* * stress_tee_spawn() * spawn off tee I/O processes */ static pid_t stress_tee_spawn( const char *name, void (*func)(int fds[2]), int fds[2]) { pid_t pid; if (pipe(fds) < 0) { pr_err(stderr, "%s: pipe failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; (void)close(fds[0]); (void)close(fds[1]); pr_err(stderr, "%s: fork failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); func(fds); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); return pid; } /* * stress_tee_pipe_write() * write data down a pipe */ static void stress_tee_pipe_write(int fds[2]) { char buffer[TEE_IO_SIZE]; (void)close(fds[0]); memset(buffer, 0, sizeof(buffer)); while (opt_do_run) { ssize_t ret; ret = write(fds[1], buffer, sizeof(buffer)); if (ret < 0) { if (errno != EAGAIN) break; } } (void)close(fds[1]); } /* * stress_tee_pipe_read() * read data from a pipe */ static void stress_tee_pipe_read(int fds[2]) { char buffer[TEE_IO_SIZE]; (void)close(fds[1]); while (opt_do_run) { ssize_t ret; ret = read(fds[0], buffer, sizeof(buffer)); if (ret < 0) if (errno != EAGAIN) break; } (void)close(fds[1]); } /* * stress_tee() * stress the Linux tee syscall */ int stress_tee( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { ssize_t len, slen; int fd, pipe_in[2], pipe_out[2]; pid_t pids[2]; int ret = EXIT_FAILURE, status; (void)instance; fd = open("/dev/null", O_WRONLY); if (fd < 0) { pr_err(stderr, "%s: open /dev/null failed: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } pids[0] = stress_tee_spawn(name, stress_tee_pipe_write, pipe_in); if (pids[0] < 0) { close(fd); return EXIT_FAILURE; } (void)close(pipe_in[1]); pids[1] = stress_tee_spawn(name, stress_tee_pipe_read, pipe_out); if (pids[0] < 0) goto tidy_child1; (void)close(pipe_out[0]); do { len = tee(pipe_in[0], pipe_out[1], INT_MAX, 0 & SPLICE_F_NONBLOCK); if (len < 0) { if (errno == EAGAIN) continue; if (errno == EINTR) break; pr_err(stderr, "%s: tee failed: errno=%d (%s)\n", name, errno, strerror(errno)); goto tidy_child2; } else { if (len == 0) break; } while (len > 0) { slen = splice(pipe_in[0], NULL, fd, NULL, len, SPLICE_F_MOVE); if (errno == EINTR) break; if (slen < 0) { pr_err(stderr, "%s: splice failed: errno=%d (%s)\n", name, errno, strerror(errno)); goto tidy_child2; } len -= slen; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); ret = EXIT_SUCCESS; tidy_child2: (void)close(pipe_out[1]); (void)kill(pids[1], SIGKILL); (void)waitpid(pids[1], &status, 0); tidy_child1: (void)close(pipe_in[0]); (void)kill(pids[0], SIGKILL); (void)waitpid(pids[0], &status, 0); (void)close(fd); return ret; } #endif stress-ng-0.05.23/stress-lockbus.c0000664000175000017500000000523512702231255015405 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_LOCKBUS) #include #include #include #include #include #include #include #define BUFFER_SIZE (1024 * 1024 * 16) #define CHUNK_SIZE (64) #define LOCK_AND_INC(ptr, inc) \ asm volatile("lock addb %1,%0" : "+m" (*ptr) : "ir" (inc)); \ ptr++; #define LOCK_AND_INCx8(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) \ LOCK_AND_INC(ptr, inc) /* * stress_lockbus() * stress memory with lock and increment */ int stress_lockbus( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint8_t *buffer; int flags = MAP_ANONYMOUS | MAP_SHARED; (void)instance; #if defined(MAP_POPULATE) flags |= MAP_POPULATE; #endif buffer = mmap(NULL, BUFFER_SIZE, PROT_READ | PROT_WRITE, flags, -1, 0); if (buffer == MAP_FAILED) { int rc = exit_status(errno); pr_err(stderr, "%s: mmap failed\n", name); return rc; } do { uint8_t *ptr = buffer + (mwc32() % (BUFFER_SIZE - CHUNK_SIZE)); const uint8_t inc = 1; LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); LOCK_AND_INCx8(ptr, inc); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)munmap(buffer, BUFFER_SIZE); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/out-of-memory.c0000664000175000017500000000505612702231255015142 0ustar kingking/* * Copyright (C) 2013-2016 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, const 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"; redo_wr1: n = write(fd, str, strlen(str)); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_wr1; if (errno) pr_fail_dbg(name, "can't set oom_score_adj"); } (void)close(fd); 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"; redo_wr2: n = write(fd, str, strlen(str)); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_wr2; if (errno) pr_fail_dbg(name, "can't set oom_adj"); } (void)close(fd); } return; } #else void set_oom_adjustment(const char *name, const bool killable) { (void)name; (void)killable; } #endif stress-ng-0.05.23/stress-sem.c0000664000175000017500000001147112702231255014526 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SEMAPHORE_POSIX) #include #include #include #include #include #include #include #include #include #include static uint64_t opt_semaphore_posix_procs = DEFAULT_SEMAPHORE_PROCS; static bool set_semaphore_posix_procs = false; void stress_set_semaphore_posix_procs(const char *optarg) { set_semaphore_posix_procs = true; 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.sem, 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() * destroy a POSIX semaphore */ void stress_semaphore_posix_destroy(void) { if (shared->sem_posix.init) { if (sem_destroy(&shared->sem_posix.sem) < 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; struct timespec timeout; if (clock_gettime(CLOCK_REALTIME, &timeout) < 0) { pr_fail_dbg(name, "clock_gettime"); return; } timeout.tv_sec++; for (i = 0; i < 1000; i++) { if (sem_timedwait(&shared->sem_posix.sem, &timeout) < 0) { if (errno == ETIMEDOUT) goto timed_out; if (errno != EINTR) pr_fail_dbg(name, "sem_wait"); break; } (*counter)++; if (sem_post(&shared->sem_posix.sem) < 0) { pr_fail_dbg(name, "sem_post"); break; } timed_out: if (!opt_do_run) break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); } /* * semaphore_posix_spawn() * spawn a process */ static pid_t semaphore_posix_spawn( const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); semaphore_posix_thrash(name, max_ops, counter); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); 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 (!set_semaphore_posix_procs) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_semaphore_posix_procs = MAX_SEMAPHORE_PROCS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_semaphore_posix_procs = MIN_SEMAPHORE_PROCS; } 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 (!opt_do_run || pids[i] < 0) goto reap; } /* Wait for termination */ while (opt_do_run && (!max_ops || *counter < max_ops)) usleep(100000); reap: for (i = 0; i < opt_semaphore_posix_procs; i++) { if (pids[i] > 0) (void)kill(pids[i], SIGKILL); } for (i = 0; i < opt_semaphore_posix_procs; i++) { if (pids[i] > 0) { int status; (void)waitpid(pids[i], &status, 0); } } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-chmod.c0000664000175000017500000001152212702231255015031 0ustar kingking/* * Copyright (C) 2013-2016 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 const 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_IRUSR | S_IRWXU) < 0) { if (errno != EEXIST) { rc = exit_status(errno); pr_fail_err(name, "mkdir"); return rc; } } (void)stress_temp_filename(filename, sizeof(filename), name, ppid, 0, 0); if (instance == 0) { if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "creat"); goto tidy; } } else { /* Other instances must try to open the file */ for (;;) { if ((fd = open(filename, O_RDWR, S_IRUSR | S_IWUSR)) > - 1) break; (void)usleep(100000); if (++retries >= 100) { pr_err(stderr, "%s: chmod: file %s took %d retries to open and gave up(instance %" PRIu32 ")\n", name, filename, retries, instance); goto tidy; } /* Timed out, then give up */ if (!opt_do_run) { rc = EXIT_SUCCESS; goto tidy; } } } 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: if (fd >= 0) { (void)fchmod(fd, 0666); (void)close(fd); } (void)unlink(filename); (void)rmdir(dirname); return rc; } stress-ng-0.05.23/stress-procfs.c0000664000175000017500000001114212702231255015231 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_PROCFS) #include #include #include #include #include #include #include #include #include #include #define PROC_BUF_SZ (4096) #define MAX_READ_THREADS (4) static volatile bool keep_running; static sigset_t set; /* * stress_proc_read() * read a proc file */ static inline void stress_proc_read(const char *path) { int fd; ssize_t i = 0; char buffer[PROC_BUF_SZ]; if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) return; /* * Multiple randomly sized reads */ while (i < (4096 * PROC_BUF_SZ)) { ssize_t ret, sz = 1 + (mwc32() % sizeof(buffer)); redo: if (!opt_do_run) break; ret = read(fd, buffer, sz); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; break; } if (ret < sz) break; i += sz; } (void)close(fd); } /* * stress_proc_read_thread * keep exercising a procfs entry until * controlling thread triggers an exit */ static void *stress_proc_read_thread(void *ctxt) { static void *nowt = NULL; uint8_t stack[SIGSTKSZ]; stack_t ss; /* * 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 totally unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_fail_err("pthread", "sigaltstack"); return &nowt; } while (keep_running && opt_do_run) stress_proc_read((char *)ctxt); return &nowt; } /* * stress_proc_read_threads() * create a bunch of threads to thrash read a proc entry */ static void stress_proc_read_threads(char *path) { size_t i; pthread_t pthreads[MAX_READ_THREADS]; int ret[MAX_READ_THREADS]; memset(ret, 0, sizeof(ret)); keep_running = true; for (i = 0; i < MAX_READ_THREADS; i++) { ret[i] = pthread_create(&pthreads[i], NULL, stress_proc_read_thread, path); } for (i = 0; i < 8; i++) { if (!opt_do_run) break; stress_proc_read(path); } keep_running = false; for (i = 0; i < MAX_READ_THREADS; i++) { if (ret[i] == 0) pthread_join(pthreads[i], NULL); } } /* * 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_threads(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; sigfillset(&set); 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.05.23/stress-poll.c0000664000175000017500000001224512702231255014710 0ustar kingking/* * Copyright (C) 2013-2016 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(const char *name, const int fd, const int n) { char buf[POLL_BUF]; ssize_t ret; redo: if (!opt_do_run) return -1; ret = read(fd, buf, sizeof(buf)); if (opt_flags & OPT_FLAGS_VERIFY) { if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; pr_fail(stderr, "%s: pipe read error detected\n", name); return ret; } if (ret > 0) { ssize_t i; for (i = 0; i < ret; i++) { if (buf[i] != '0' + n) { pr_fail(stderr, "%s: pipe read error, " "expecting different data on " "pipe\n", name); 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_fail_dbg(name, "pipe"); while (--i >= 0) { (void)close(pipefds[i][0]); (void)close(pipefds[i][1]); } return EXIT_FAILURE; } } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); ret = EXIT_FAILURE; goto tidy; } else if (pid == 0) { /* Child writer */ setpgid(0, pgrp); stress_parent_died_alarm(); 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 = (mwc32() >> 8) % MAX_PIPES; memset(buf, '0' + i, sizeof(buf)); ret = write(pipefds[i][1], buf, sizeof(buf)); if (ret < (ssize_t)sizeof(buf)) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_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; setpgid(pid, pgrp); 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, "%s: poll failed with error: %d (%s)\n", name, errno, strerror(errno)); } if (ret > 0) { for (i = 0; i < MAX_PIPES; i++) { if (fds[i].revents == POLLIN) { if (pipe_read(name, fds[i].fd, i) < 0) break; } } (*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, "%s: select failed with error: %d (%s)\n", name, errno, strerror(errno)); } if (ret > 0) { for (i = 0; i < MAX_PIPES; i++) { if (FD_ISSET(pipefds[i][0], &rfds)) { if (pipe_read(name, 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.05.23/stress-sysinfo.c0000664000175000017500000001001712702231255015427 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #if defined(__linux__) #include #include #endif #include #include #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; struct statvfs statvfs_buf; int i, ret; #if defined(__linux__) struct sysinfo sysinfo_buf; struct statfs statfs_buf; #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(); /* Linux statfs variant */ for (i = 0; i < n_mounts; i++) { int fd; 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 && errno != EACCES) { pr_fail(stderr, "%s: statfs on %s " "failed: errno=%d (%s)\n", name, mnts[i], errno, strerror(errno)); } } fd = open(mnts[i], O_RDONLY | O_DIRECTORY); if (fd < 0) continue; ret = fstatfs(fd, &statfs_buf); (void)close(fd); if ((ret < 0) && (errno == ENOENT)) continue; if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { if (errno != ENOSYS && errno != EOVERFLOW && errno != EACCES) { pr_fail(stderr, "%s: fstatfs on %s " "failed: errno=%d (%s)\n", name, mnts[i], errno, strerror(errno)); } } } #endif check_do_run(); /* POSIX.1-2001 statfs variant */ for (i = 0; i < n_mounts; i++) { check_do_run(); if (!mnts[i]) continue; ret = statvfs(mnts[i], &statvfs_buf); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { if (errno != ENOSYS && errno != EOVERFLOW && errno != EACCES) { pr_fail(stderr, "%s: statvfs on %s " "failed: errno=%d (%s)\n", name, mnts[i], errno, strerror(errno)); } } } check_do_run(); 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.05.23/stress-shm.c0000664000175000017500000002255512702231255014536 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SHM_POSIX) #include #include #include #include #include #include #include #include #include #include #include #include #define SHM_NAME_LEN 128 typedef struct { int index; char shm_name[SHM_NAME_LEN]; } shm_msg_t; static size_t opt_shm_posix_bytes = DEFAULT_SHM_POSIX_BYTES; static size_t opt_shm_posix_objects = DEFAULT_SHM_POSIX_OBJECTS; static bool set_shm_posix_bytes = false; static bool set_shm_posix_objects = false; void stress_set_shm_posix_bytes(const char *optarg) { set_shm_posix_bytes = true; opt_shm_posix_bytes = (size_t)get_uint64_byte(optarg); check_range("shm-bytes", opt_shm_posix_bytes, MIN_SHM_POSIX_BYTES, MAX_SHM_POSIX_BYTES); } void stress_set_shm_posix_objects(const char *optarg) { opt_shm_posix_objects = true; opt_shm_posix_objects = (size_t)get_uint64_byte(optarg); check_range("shm-segments", opt_shm_posix_objects, MIN_SHM_POSIX_OBJECTS, MAX_SHM_POSIX_OBJECTS); } /* * stress_shm_posix_check() * simple check if shared memory is sane */ static int stress_shm_posix_check( uint8_t *buf, const size_t sz, const size_t page_size) { uint8_t *ptr, *end = buf + sz; uint8_t val; memset(buf, 0xa5, sz); for (val = 0, ptr = buf; ptr < end; ptr += page_size, val++) { *ptr = val; } for (val = 0, ptr = buf; ptr < end; ptr += page_size, val++) { if (*ptr != val) return -1; } return 0; } /* * stress_shm_posix_child() * stress out the shm allocations. This can be killed by * the out of memory killer, so we need to keep the parent * informed of the allocated shared memory ids so these can * be reaped cleanly if this process gets prematurely killed. */ static int stress_shm_posix_child( const int fd, uint64_t *const counter, const uint64_t max_ops, const char *name, size_t sz) { void *addrs[MAX_SHM_POSIX_OBJECTS]; char shm_names[MAX_SHM_POSIX_OBJECTS][SHM_NAME_LEN]; shm_msg_t msg; int i; int rc = EXIT_SUCCESS; bool ok = true; pid_t pid = getpid(); uint64_t id = 0; const size_t page_size = stress_get_pagesize(); memset(addrs, 0, sizeof(addrs)); memset(shm_names, 0, sizeof(shm_names)); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { for (i = 0; ok && (i < (ssize_t)opt_shm_posix_objects); i++) { int shm_fd; void *addr; char *shm_name = shm_names[i]; shm_name[0] = '\0'; if (!opt_do_run) goto reap; snprintf(shm_name, SHM_NAME_LEN, "/stress-ng-%u-%" PRIx64 "-%" PRIx32, pid, id, mwc32()); shm_fd = shm_open(shm_name, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); if (shm_fd < 0) { ok = false; pr_fail(stderr, "%s: shm_open failed: errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto reap; } /* Inform parent of the new shm name */ msg.index = i; shm_name[SHM_NAME_LEN - 1] = '\0'; strncpy(msg.shm_name, shm_name, SHM_NAME_LEN); if (write(fd, &msg, sizeof(msg)) < 0) { pr_err(stderr, "%s: write failed: errno=%d: (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; (void)close(shm_fd); goto reap; } addr = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, shm_fd, 0); if (addr == MAP_FAILED) { ok = false; pr_fail(stderr, "%s: mmap failed, giving up: errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; (void)close(shm_fd); goto reap; } addrs[i] = addr; (void)close(shm_fd); 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_posix_check(addr, sz, page_size) < 0) { ok = false; pr_fail(stderr, "%s: memory check failed\n", name); rc = EXIT_FAILURE; goto reap; } id++; (*counter)++; } reap: for (i = 0; ok && (i < (ssize_t)opt_shm_posix_objects); i++) { char *shm_name = shm_names[i]; if (addrs[i]) (void)munmap(addrs[i], sz); if (*shm_name) { if (shm_unlink(shm_name) < 0) { pr_fail(stderr, "%s: shm_unlink " "failed: errno=%d (%s)\n", name, errno, strerror(errno)); } } /* Inform parent shm ID is now free */ msg.index = i; msg.shm_name[SHM_NAME_LEN - 1] = '\0'; strncpy(msg.shm_name, shm_name, SHM_NAME_LEN - 1); if (write(fd, &msg, sizeof(msg)) < 0) { pr_dbg(stderr, "%s: write failed: errno=%d: (%s)\n", name, errno, strerror(errno)); ok = false; } addrs[i] = NULL; *shm_name = '\0'; } } while (ok && opt_do_run && (!max_ops || *counter < max_ops)); /* Inform parent of end of run */ msg.index = -1; strncpy(msg.shm_name, "", SHM_NAME_LEN); if (write(fd, &msg, sizeof(msg)) < 0) { pr_err(stderr, "%s: write failed: errno=%d: (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } return rc; } /* * stress_shm_posix() * stress SYSTEM V shared memory */ int stress_shm_posix( 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 orig_sz, sz; int pipefds[2]; int rc = EXIT_SUCCESS; ssize_t i; pid_t pid; bool retry = true; uint32_t restarts = 0; if (!set_shm_posix_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_shm_posix_bytes = MAX_SHM_POSIX_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_shm_posix_bytes = MIN_SHM_POSIX_BYTES; } if (!set_shm_posix_objects) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_shm_posix_objects = MAX_SHM_POSIX_OBJECTS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_shm_posix_objects = MIN_SHM_POSIX_OBJECTS; } orig_sz = sz = opt_shm_posix_bytes & ~(page_size - 1); while (opt_do_run && retry) { if (pipe(pipefds) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } fork_again: pid = fork(); if (pid < 0) { /* Can't fork, retry? */ if (errno == EAGAIN) goto fork_again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)close(pipefds[0]); (void)close(pipefds[1]); /* Nope, give up! */ return EXIT_FAILURE; } else if (pid > 0) { /* Parent */ int status; char shm_names[MAX_SHM_POSIX_OBJECTS][SHM_NAME_LEN]; setpgid(pid, pgrp); (void)close(pipefds[1]); memset(shm_names, 0, sizeof(shm_names)); while (opt_do_run) { ssize_t n; shm_msg_t msg; char *shm_name; /* * Blocking read on child shm ID info * pipe. We break out if pipe breaks * on child death, or child tells us * off its demise. */ n = read(pipefds[0], &msg, sizeof(msg)); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "read"); break; } pr_fail_dbg(name, "zero byte read"); break; } if ((msg.index < 0) || (msg.index >= MAX_SHM_POSIX_OBJECTS)) { retry = false; break; } shm_name = shm_names[msg.index]; shm_name[SHM_NAME_LEN - 1] = '\0'; strncpy(shm_name, msg.shm_name, SHM_NAME_LEN - 1); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); if (WIFSIGNALED(status)) { if ((WTERMSIG(status) == SIGKILL) || (WTERMSIG(status) == SIGKILL)) { pr_dbg(stderr, "%s: assuming killed by OOM killer, " "restarting again (instance %d)\n", name, instance); restarts++; } } (void)close(pipefds[1]); /* * The child may have been killed by the OOM killer or * some other way, so it may have left the shared * memory segment around. At this point the child * has died, so we should be able to remove the * shared memory segment. */ for (i = 0; i < (ssize_t)opt_shm_posix_objects; i++) { char *shm_name = shm_names[i]; if (*shm_name) (void)shm_unlink(shm_name); } } else if (pid == 0) { /* Child, stress memory */ setpgid(0, pgrp); stress_parent_died_alarm(); (void)close(pipefds[0]); rc = stress_shm_posix_child(pipefds[1], counter, max_ops, name, sz); (void)close(pipefds[1]); _exit(rc); } } if (orig_sz != sz) pr_dbg(stderr, "%s: reduced shared memory size from " "%zu to %zu bytes\n", name, orig_sz, sz); if (restarts) { pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 "\n", name, restarts); } return rc; } #endif stress-ng-0.05.23/stress-sigfpe.c0000664000175000017500000000405412702231255015216 0ustar kingking/* * Copyright (C) 2013-2016 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 MLOCKED 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 (;;) { int ret; if (stress_sighandler(name, SIGFPE, stress_fpehandler, NULL) < 0) 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.05.23/limit.c0000664000175000017500000000422712702231255013540 0ustar kingking/* * Copyright (C) 2014-2016 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" 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.05.23/stress-eventfd.c0000664000175000017500000000765412702231255015405 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_EVENTFD) #include #include #include #include #include #include #include #include #include #include /* * 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, rc; (void)instance; fd1 = eventfd(0, 0); if (fd1 < 0) { rc = exit_status(errno); pr_fail_dbg(name, "eventfd"); return rc; } fd2 = eventfd(0, 0); if (fd2 < 0) { rc = exit_status(errno); pr_fail_dbg(name, "eventfd"); (void)close(fd1); return rc; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); (void)close(fd1); (void)close(fd2); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); while (opt_do_run) { uint64_t val; ssize_t ret; for (;;) { if (!opt_do_run) goto exit_child; ret = read(fd1, &val, sizeof(val)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_dbg(name, "child read"); goto exit_child; } if (ret < (ssize_t)sizeof(val)) { pr_fail_dbg(name, "child short read"); goto exit_child; } break; } val = 1; for (;;) { if (!opt_do_run) goto exit_child; ret = write(fd2, &val, sizeof(val)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_dbg(name, "child write"); goto exit_child; } if (ret < (ssize_t)sizeof(val)) { pr_fail_dbg(name, "child short write"); goto exit_child; } break; } } exit_child: (void)close(fd1); (void)close(fd2); exit(EXIT_SUCCESS); } else { int status; do { uint64_t val = 1; int ret; for (;;) { if (!opt_do_run) goto exit_parent; ret = write(fd1, &val, sizeof(val)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_dbg(name, "parent write"); goto exit_parent; } if (ret < (ssize_t)sizeof(val)) { pr_fail_dbg(name, "parent short write"); goto exit_parent; } break; } for (;;) { if (!opt_do_run) goto exit_parent; ret = read(fd2, &val, sizeof(val)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_dbg(name, "parent read"); goto exit_parent; } if (ret < (ssize_t)sizeof(val)) { pr_fail_dbg(name, "parent short read"); goto exit_parent; } break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); exit_parent: (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); (void)close(fd1); (void)close(fd2); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-mincore.c0000664000175000017500000000504512702231255015376 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MINCORE) #include #include #include #include #include #include #include #include #include #include #include #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)(mwc64() & 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.05.23/ignite-cpu.c0000664000175000017500000001015112702231255014457 0ustar kingking/* * Copyright (C) 2016 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" typedef struct { const char *path; /* Path of /sys control */ const char *default_setting; /* Default maximizing setting to use */ size_t default_setting_len; /* Length of default setting */ char *setting; /* Original setting to restore it */ size_t setting_len; /* Length of setting */ bool ignore; /* true to ignore using this */ } settings_t; static pid_t pid; static bool enabled; #define SETTING(path, default_setting) \ { path, default_setting, 0, NULL, 0, false } settings_t settings[] = { #if defined(__linux__) && defined(STRESS_X86) /* x86 Intel P-State maximizing settings */ SETTING("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "100"), SETTING("/sys/devices/system/cpu/intel_pstate/no_turbo", "0"), #endif SETTING(NULL, NULL) }; /* * ignite_cpu_start() * crank up the CPUs, start a child process to continually * set the most demanding CPU settings */ void ignite_cpu_start(void) { size_t i, n = 0; if (enabled) return; pid = -1; for (i = 0; settings[i].path; i++) { char buf[4096]; int ret; size_t len; settings[i].ignore = true; ret = system_read(settings[i].path, buf, sizeof(buf)); if (ret < 0) continue; len = strlen(buf); if (len == 0) continue; settings[i].default_setting_len = strlen(settings[i].default_setting); /* If we can't update the setting, skip it */ ret = system_write(settings[i].path, settings[i].default_setting, settings[i].default_setting_len); if (ret < 0) { pr_dbg(stderr, "ignite-cpu: cannot set %s to %s, " "errno=%d (%s)\n", settings[i].path, settings[i].default_setting, -ret, strerror(-ret)); continue; } settings[i].setting = calloc(1, len + 1); if (!settings[i].setting) continue; strncpy(settings[i].setting, buf, len); settings[i].setting_len = len; settings[i].ignore = false; n++; } if (n == 0) return; enabled = true; pid = fork(); if (pid < 0) { pr_dbg(stderr, "failed to start ignite cpu daemon, " "errno=%d (%s)\n", errno, strerror(errno)); return; } else if (pid == 0) { /* Child */ setpgid(0, pgrp); stress_parent_died_alarm(); for (;;) { for (i = 0; settings[i].path; i++) { if (settings[i].ignore) continue; (void)system_write(settings[i].path, settings[i].default_setting, settings[i].default_setting_len); } sleep(1); } } else { /* Parent */ setpgid(pid, pgrp); } } /* * ignite_cpu_stop() * stop updating settings and restore to original settings */ void ignite_cpu_stop(void) { size_t i; int status; if (pid > -1) { (void)kill(pid, SIGTERM); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } for (i = 0; settings[i].path; i++) { if (settings[i].ignore) continue; (void)system_write(settings[i].path, settings[i].setting, settings[i].setting_len); free(settings[i].setting); settings[i].setting = NULL; settings[i].ignore = true; } enabled = false; } stress-ng-0.05.23/stress-clock.c0000664000175000017500000001325012702231255015032 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #include #if defined(STRESS_CLOCK) typedef struct { int id; /* Clock ID */ char *name; /* Clock name */ } clock_info_t; #define CLOCK_INFO(x) { x, #x } static const clock_info_t clocks[] = { #ifdef CLOCK_REALTIME CLOCK_INFO(CLOCK_REALTIME), #endif #ifdef CLOCK_REALTIME_COARSE CLOCK_INFO(CLOCK_REALTIME_COARSE), #endif #ifdef CLOCK_MONOTONIC CLOCK_INFO(CLOCK_MONOTONIC), #endif #ifdef CLOCK_MONOTONIC_RAW CLOCK_INFO(CLOCK_MONOTONIC_RAW), #endif #ifdef CLOCK_BOOTTIME CLOCK_INFO(CLOCK_BOOTTIME), #endif #ifdef CLOCK_PROCESS_CPUTIME_ID CLOCK_INFO(CLOCK_PROCESS_CPUTIME_ID), #endif #ifdef CLOCK_THREAD_CPUTIME_ID CLOCK_INFO(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 #if _POSIX_C_SOURCE >= 199309L && defined(__linux__) static const int timers[] = { #ifdef CLOCK_REALTIME CLOCK_REALTIME, #endif #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC #endif }; #endif /* * stress_clock_name() * clock id to name */ static char *stress_clock_name(int id) { size_t i; for (i = 0; i < SIZEOF_ARRAY(clocks); i++) { if (clocks[i].id == id) return clocks[i].name; } return "(unknown clock)"; } /* * 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; 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].id, &t); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: clock_getres failed for " "timer '%s', errno=%d (%s)\n", name, clocks[i].name, errno, strerror(errno)); ret = clock_gettime(clocks[i].id, &t); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: clock_gettime failed for " "timer '%s', errno=%d (%s)\n", name, clocks[i].name, 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 '%s', " "errno=%d (%s)\n", name, stress_clock_name(clocks_nanosleep[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) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: timer_create failed for timer '%s', " "errno=%d (%s)\n", name, stress_clock_name(timers[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) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: timer_settime failed for timer '%s', " "errno=%d (%s)\n", name, stress_clock_name(timers[i]), errno, strerror(errno)); goto timer_delete; } do { ret = timer_gettime(timer_id, &its); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: timer_gettime failed for timer '%s', " "errno=%d (%s)\n", name, stress_clock_name(timers[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) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: timer_delete failed for timer '%s', " "errno=%d (%s)\n", name, stress_clock_name(timers[i]), errno, strerror(errno)); break; } } #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/test-libcrypt.c0000664000175000017500000000262512702231255015227 0ustar kingking/* * Copyright (C) 2013-2016 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 #define _XOPEN_SOURCE 600 #include #include int main(void) { const char passwd[] = "somerandomtext"; const char salt[] = "examplesalt"; char *crypted; #if defined (__linux__) struct crypt_data data; memset(&data, 0, sizeof(data)); crypted = crypt_r(passwd, salt, &data); #else crypted = crypt(passwd, salt); #endif return 0; } stress-ng-0.05.23/mounts.c0000664000175000017500000000447712702231255013756 0ustar kingking/* * Copyright (C) 2013-2016 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 */ static void mount_add( char *mnts[], const int max, int *n, const char *name) { char *mnt; if (*n >= max) return; mnt = strdup(name); if (!mnt) return; mnts[*n] = mnt; (*n)++; } /* * 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) { 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.05.23/stress-crypt.c0000664000175000017500000000531712702231255015105 0ustar kingking/* * Copyright (C) 2013-2016 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 #define _XOPEN_SOURCE 600 #include "stress-ng.h" #if defined(STRESS_CRYPT) #include #include #include #include #if defined (__linux__) #include #endif /* * stress_crypt_id() * crypt a password with given seed and id */ static int stress_crypt_id( const char *name, const char id, const char *method, const char *passwd, char *salt) { salt[1] = id; char *crypted; #if defined (__linux__) struct crypt_data data; memset(&data, 0, sizeof(data)); crypted = crypt_r(passwd, salt, &data); #else crypted = crypt(passwd, salt); #endif if (!crypted) { pr_fail(stderr, "%s: cannot encrypt with %s", name, method); return -1; } return 0; } /* * stress_crypt() * stress libc crypt */ int stress_crypt( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { (void)instance; do { static const char seedchars[] = "./0123456789ABCDEFGHIJKLMNOPQRST" "UVWXYZabcdefghijklmnopqrstuvwxyz"; char passwd[16]; char salt[] = "$x$........"; uint64_t seed[2]; size_t i; seed[0] = mwc64(); seed[1] = mwc64(); for (i = 0; i < 8; i++) salt[i + 3] = seedchars[(seed[i / 5] >> (i % 5) * 6) & 0x3f]; for (i = 0; i < sizeof(passwd) - 1; i++) passwd[i] = seedchars[mwc32() % sizeof(seedchars)]; passwd[i] = '\0'; if (stress_crypt_id(name, '1', "MD5", passwd, salt) < 0) break; #if NEED_GLIBC(2,7,0) if (stress_crypt_id(name, '5', "SHA-256", passwd, salt) < 0) break; if (stress_crypt_id(name, '6', "SHA-512", passwd, salt) < 0) break; #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/time.c0000664000175000017500000000563112702231255013360 0ustar kingking/* * Copyright (C) 2013-2016 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" #define SECONDS_IN_MINUTE (60.0) #define SECONDS_IN_HOUR (60.0 * SECONDS_IN_MINUTE) #define SECONDS_IN_DAY (24.0 * SECONDS_IN_HOUR) #define SECONDS_IN_YEAR (365.2425 * SECONDS_IN_DAY) /* Approx, for Gregorian calendar */ /* * time_now() * time in seconds as a double */ double time_now(void) { struct timeval now; gettimeofday(&now, NULL); return timeval_to_double(&now); } /* * format_time() * format a unit of time into human readable format */ static inline void format_time( bool last, /* Last unit to format */ const double secs_in_units, /* Seconds in the specific time unit */ const char *units, /* Unit of time */ char **ptr, /* Destination string ptr */ double *duration, /* Duration left in seconds */ size_t *len) /* Length of string left at ptr */ { unsigned long val = (unsigned long)(*duration / secs_in_units); if (last || val > 0) { int ret; if (last) ret = snprintf(*ptr, *len, "%.2f %ss", *duration, units); else ret = snprintf(*ptr, *len, "%lu %s%s, ", val, units, (val > 1) ? "s" : ""); if (ret > 0) { *len -= ret; *ptr += ret; } } *duration -= secs_in_units * (double)val; } /* * duration_to_str * duration in seconds to a human readable string */ const char *duration_to_str(const double duration) { static char str[128]; char *ptr = str; size_t len = sizeof(str) - 1; double dur = duration; *str = '\0'; if (duration > 60.0) { strncpy(ptr, " (", len); ptr += 2; len -= 2; format_time(false, SECONDS_IN_YEAR, "year", &ptr, &dur, &len); format_time(false, SECONDS_IN_DAY, "day", &ptr, &dur, &len); format_time(false, SECONDS_IN_HOUR, "hour", &ptr, &dur, &len); format_time(false, SECONDS_IN_MINUTE, "min", &ptr, &dur, &len); format_time(true, 1, "sec", &ptr, &dur, &len); strncpy(ptr, ")", len); } return str; } stress-ng-0.05.23/Makefile0000664000175000017500000003011412702231255013710 0ustar kingking# # Copyright (C) 2013-2016 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.05.23 # # Codename "dastardly determined distressor" # CFLAGS += -Wall -Wextra -DVERSION='"$(VERSION)"' -O2 BINDIR=/usr/bin MANDIR=/usr/share/man/man1 # # Stressors # STRESS_SRC = \ stress-affinity.c \ stress-af-alg.c \ stress-aio.c \ stress-aio-linux.c \ stress-apparmor.c \ stress-bigheap.c \ stress-bind-mount.c \ stress-brk.c \ stress-bsearch.c \ stress-cache.c \ stress-cap.c \ stress-chdir.c \ stress-chmod.c \ stress-clock.c \ stress-clone.c \ stress-context.c \ stress-copy-file.c \ stress-cpu.c \ stress-cpu-online.c \ stress-crypt.c \ stress-daemon.c \ stress-dentry.c \ stress-dir.c \ stress-dup.c \ stress-epoll.c \ stress-eventfd.c \ stress-exec.c \ stress-fallocate.c \ stress-fault.c \ stress-fcntl.c \ stress-fiemap.c \ stress-fifo.c \ stress-filename.c \ stress-flock.c \ stress-fork.c \ stress-fp-error.c \ stress-fstat.c \ stress-futex.c \ stress-get.c \ stress-getrandom.c \ stress-getdent.c \ stress-handle.c \ stress-hdd.c \ stress-heapsort.c \ stress-hsearch.c \ stress-icache.c \ stress-inotify.c \ stress-iosync.c \ stress-itimer.c \ stress-kcmp.c \ stress-key.c \ stress-kill.c \ stress-klog.c \ stress-lease.c \ stress-lsearch.c \ stress-link.c \ stress-lockbus.c \ stress-lockf.c \ stress-longjmp.c \ stress-malloc.c \ stress-matrix.c \ stress-membarrier.c \ stress-memcpy.c \ stress-memfd.c \ stress-mergesort.c \ stress-mincore.c \ stress-mknod.c \ stress-mlock.c \ stress-mmap.c \ stress-mmapfork.c \ stress-mmapmany.c \ stress-mremap.c \ stress-msg.c \ stress-mq.c \ stress-nice.c \ stress-noop.c \ stress-null.c \ stress-numa.c \ stress-oom-pipe.c \ stress-open.c \ stress-personality.c \ stress-pipe.c \ stress-poll.c \ stress-procfs.c \ stress-pthread.c \ stress-ptrace.c \ stress-quota.c \ stress-qsort.c \ stress-rdrand.c \ stress-readahead.c \ stress-remap-file-pages.c \ stress-rename.c \ stress-rlimit.c \ stress-seek.c \ stress-seccomp.c \ stress-sem.c \ stress-sem-sysv.c \ stress-sendfile.c \ stress-shm.c \ stress-shm-sysv.c \ stress-sigfd.c \ stress-sigfpe.c \ stress-sigpending.c \ stress-sigsegv.c \ stress-sigsuspend.c \ stress-sigq.c \ stress-sleep.c \ stress-socket.c \ stress-socket-fd.c \ stress-socketpair.c \ stress-spawn.c \ stress-splice.c \ stress-stack.c \ stress-str.c \ stress-stream.c \ stress-switch.c \ stress-sync-file.c \ stress-sysinfo.c \ stress-sysfs.c \ stress-tee.c \ stress-timer.c \ stress-timerfd.c \ stress-tsc.c \ stress-tsearch.c \ stress-udp.c \ stress-udp-flood.c \ stress-unshare.c \ stress-urandom.c \ stress-userfaultfd.c \ stress-utime.c \ stress-vecmath.c \ stress-vm.c \ stress-vm-rw.c \ stress-vm-splice.c \ stress-wait.c \ stress-wcstr.c \ stress-xattr.c \ stress-yield.c \ stress-zero.c \ stress-zlib.c \ stress-zombie.c \ # # Stress core # CORE_SRC = \ cache.c \ helper.c \ ignite-cpu.c \ io-priority.c \ limit.c \ log.c \ madvise.c \ mincore.c \ mlock.c \ mounts.c \ mwc.c \ net.c \ out-of-memory.c \ parse-opts.c \ perf.c \ sched.c \ thermal-zone.c \ time.c \ stress-ng.c SRC = $(STRESS_SRC) $(CORE_SRC) OBJS = $(SRC:.c=.o) APPARMOR_PARSER=/sbin/apparmor_parser LIB_APPARMOR := -lapparmor LIB_BSD := -lbsd LIB_Z := -lz LIB_CRYPT := -lcrypt LIB_RT := -lrt LIB_PTHREAD := -lpthread LIB_AIO = -laio HAVE_NOT=HAVE_APPARMOR=0 HAVE_KEYUTILS_H=0 HAVE_XATTR_H=0 HAVE_LIB_BSD=0 \ HAVE_LIB_Z=0 HAVE_LIB_CRYPT=0 HAVE_LIB_RT=0 HAVE_LIB_PTHREAD=0 \ HAVE_FLOAT_DECIMAL=0 HAVE_SECCOMP_H=0 HAVE_LIB_AIO=0 HAVE_SYS_CAP_H=0 # # Do build time config only if cmd is "make" and no goals given # ifeq ($(MAKECMDGOALS),) # # A bit recursive, 2nd time around HAVE_APPARMOR is # defined so we don't call ourselves over and over # ifndef $(HAVE_APPARMOR) HAVE_APPARMOR = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_apparmor) ifeq ($(HAVE_APPARMOR),1) OBJS += apparmor-data.o CFLAGS += -DHAVE_APPARMOR LDFLAGS += $(LIB_APPARMOR) endif endif ifndef $(HAVE_KEYUTILS_H) HAVE_KEYUTILS_H = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_keyutils_h) ifeq ($(HAVE_KEYUTILS_H),1) CFLAGS += -DHAVE_KEYUTILS_H endif endif ifndef $(HAVE_XATTR_H) HAVE_XATTR_H = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_xattr_h) ifeq ($(HAVE_XATTR_H),1) CFLAGS += -DHAVE_XATTR_H endif endif ifndef $(HAVE_LIB_BSD) HAVE_LIB_BSD = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_bsd) ifeq ($(HAVE_LIB_BSD),1) CFLAGS += -DHAVE_LIB_BSD LDFLAGS += $(LIB_BSD) endif endif ifndef $(HAVE_LIB_Z) HAVE_LIB_Z = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_z) ifeq ($(HAVE_LIB_Z),1) CFLAGS += -DHAVE_LIB_Z LDFLAGS += $(LIB_Z) endif endif ifndef $(HAVE_LIB_CRYPT) HAVE_LIB_CRYPT = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_crypt) ifeq ($(HAVE_LIB_CRYPT),1) CFLAGS += -DHAVE_LIB_CRYPT LDFLAGS += $(LIB_CRYPT) endif endif ifndef $(HAVE_LIB_RT) HAVE_LIB_RT = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_rt) ifeq ($(HAVE_LIB_RT),1) CFLAGS += -DHAVE_LIB_RT LDFLAGS += $(LIB_RT) endif endif ifndef $(HAVE_LIB_PTHREAD) HAVE_LIB_PTHREAD = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_pthread) ifeq ($(HAVE_LIB_PTHREAD),1) CFLAGS += -DHAVE_LIB_PTHREAD LDFLAGS += $(LIB_PTHREAD) endif endif ifndef $(HAVE_FLOAT_DECIMAL) HAVE_FLOAT_DECIMAL = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_float_decimal) ifeq ($(HAVE_FLOAT_DECIMAL),1) CFLAGS += -DHAVE_FLOAT_DECIMAL endif endif ifndef $(HAVE_SECCOMP_H) HAVE_SECCOMP_H = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_seccomp_h) ifeq ($(HAVE_SECCOMP_H),1) CFLAGS += -DHAVE_SECCOMP_H endif endif ifndef $(HAVE_LIB_AIO) HAVE_LIB_AIO = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_lib_aio) ifeq ($(HAVE_LIB_AIO),1) CFLAGS += -DHAVE_LIB_AIO LDFLAGS += $(LIB_AIO) endif endif ifndef $(HAVE_SYS_CAP_H) HAVE_SYS_CAP_H = $(shell $(MAKE) --no-print-directory $(HAVE_NOT) have_sys_cap_h) ifeq ($(HAVE_SYS_CAP_H),1) CFLAGS += -DHAVE_SYS_CAP_H endif endif endif .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 $(LDFLAGS) -o $@ # # check if we can build against AppArmor # have_apparmor: @$(CC) $(CPPFLAGS) test-apparmor.c $(LIB_APPARMOR) -o test-apparmor 2> /dev/null || true @if [ -e test-apparmor ]; then \ if [ -x $(APPARMOR_PARSER) ]; then \ echo 1 ;\ else \ echo 0 ;\ fi \ else \ echo 0 ;\ fi @rm -f test-apparmor # # check if we have keyutils.h # have_keyutils_h: @echo "#include " > test-key.c @echo "#include " >> test-key.c @$(CC) $(CPPFLAGS) -c -o test-key.o test-key.c 2> /dev/null || true @if [ -e test-key.o ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-key.c test-key.o # # check if we have xattr.h # have_xattr_h: @echo "#include " > test-xattr.c @echo "#include " >> test-xattr.c @$(CC) $(CPPFLAGS) -c -o test-xattr.o test-xattr.c 2> /dev/null || true @if [ -e test-xattr.o ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-xattr.c test-xattr.o # # check if we can build against libbsd # have_lib_bsd: @$(CC) $(CPPFLAGS) test-libbsd.c $(LIB_BSD) -o test-libbsd 2> /dev/null || true @if [ -e test-libbsd ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-libbsd # # check if we can build against libz # have_lib_z: @$(CC) $(CPPFLAGS) test-libz.c $(LIB_Z) -o test-libz 2> /dev/null || true @if [ -e test-libz ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-libz # # check if we can build against libcrypt # have_lib_crypt: @$(CC) $(CPPFLAGS) test-libcrypt.c $(LIB_CRYPT) -o test-libcrypt 2> /dev/null || true @if [ -e test-libcrypt ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-libcrypt # # check if we can build against librt # have_lib_rt: @$(CC) $(CPPFLAGS) test-librt.c $(LIB_RT) -o test-librt 2> /dev/null || true @if [ -e test-librt ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-librt # # check if we can build against libpthread # have_lib_pthread: @$(CC) $(CPPFLAGS) test-libpthread.c $(LIB_PTHREAD) -o test-libpthread 2> /dev/null || true @if [ -e test-libpthread ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-libpthread # # check if compiler supports floating point decimal format # have_float_decimal: @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 \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-decimal.c test-decimal.o # # check if we have seccomp.h # have_seccomp_h: @echo "#include " > test-seccomp.c @$(CC) $(CPPFLAGS) -c -o test-seccomp.o test-seccomp.c 2> /dev/null || true @if [ -e test-seccomp.o ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-seccomp.c test-seccomp.o # # check if we can build against libaio # have_lib_aio: @$(CC) $(CPPFLAGS) test-libaio.c $(LIB_AIO) -o test-libaio 2> /dev/null || true @if [ -e test-libaio ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-libaio # # generate apparmor data using minimal core utils tools from apparmor # parser output # apparmor-data.o: usr.bin.pulseaudio.eg $(APPARMOR_PARSER) -Q usr.bin.pulseaudio.eg -o apparmor-data.bin echo "#include " > apparmor-data.c echo "char apparmor_data[]= { " >> apparmor-data.c od -tx1 -An -v < apparmor-data.bin | \ sed 's/[0-9a-f][0-9a-f]/0x&,/g' | \ sed '$$ s/.$$//' >> apparmor-data.c echo "};" >> apparmor-data.c echo "const size_t apparmor_data_len = sizeof(apparmor_data);" >> apparmor-data.c $(CC) -c apparmor-data.c -o apparmor-data.o @rm -rf apparmor-data.c # # check if we have sys/capability.h # have_sys_cap_h: @$(CC) $(CPPFLAGS) test-cap.c -o test-cap 2> /dev/null || true @if [ -e test-cap ]; then \ echo 1 ;\ else \ echo 0 ;\ fi @rm -f test-cap # # extract the PER_* personality enums # personality.h: @$(CPP) personality.c | grep -e "PER_[A-Z0-9]* =.*," | cut -d "=" -f 1 \ | sed "s/.$$/,/" > personality.h stress-personality.c: personality.h 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 stress-str.o: stress-str.c @echo $(CC) $(CFLAGS) -fno-builtin -c -o $@ $< @$(CC) $(CFLAGS) -fno-builtin -c -o $@ $< stress-wcstr.o: stress-wcstr.c @echo $(CC) $(CFLAGS) -fno-builtin -c -o $@ $< @$(CC) $(CFLAGS) -fno-builtin -c -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 personality.c \ COPYING syscalls.txt mascot README README.Android \ test-apparmor.c test-libbsd.c test-libz.c \ test-libcrypt.c test-librt.c test-libpthread.c \ test-libaio.c test-cap.c usr.bin.pulseaudio.eg \ 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 rm -f personality.h 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.05.23/stress-aio.c0000664000175000017500000001535012702231255014512 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_AIO) #include #include #include #include #include #include #include #include #include #include #define BUFFER_SZ (16) static int opt_aio_requests = DEFAULT_AIO_REQUESTS; static bool set_aio_requests = false; static volatile bool do_accounting = true; /* 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) { uint64_t aio_requests; set_aio_requests = true; aio_requests = get_uint64(optarg); check_range("aio-requests", aio_requests, MIN_AIO_REQUESTS, MAX_AIO_REQUESTS); opt_aio_requests = (int)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] = (uint8_t)(request + i); } /* * aio_signal_handler() * handle an async I/O signal */ static void MLOCKED 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 (do_accounting && io_req) io_req->count++; } /* * aio_issue_cancel() * cancel an in-progress async I/O request */ static void aio_issue_cancel(const char *name, 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, "%s: async I/O request %d not cancelled\n", name, io_req->request); break; default: pr_err(stderr, "%s: %d error: %d %s\n", name, io_req->request, errno, strerror(errno)); } } /* * issue_aio_request() * construct an AIO request and action it */ static int issue_aio_request( const char *name, const int fd, const off_t offset, io_req_t *const io_req, const int request, int (*aio_func)(struct aiocb *aiocbp) ) { while (opt_do_run) { 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) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_err(stderr, "%s: failed to issue aio request: %d (%s)\n", name, errno, strerror(errno)); } return ret; } /* Given up */ return 1; } /* * 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 ret, fd, rc = EXIT_FAILURE; io_req_t *io_reqs; struct sigaction sa, sa_old; int i; uint64_t total = 0; char filename[PATH_MAX]; const pid_t pid = getpid(); size_t io_req_sz; if (!set_aio_requests) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_aio_requests = MAX_AIO_REQUESTS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_aio_requests = MIN_AIO_REQUESTS; } io_req_sz = (size_t)opt_aio_requests * sizeof(io_req_t); if ((io_reqs = alloca(io_req_sz)) == NULL) { pr_err(stderr, "%s: cannot allocate io request structures\n", name); return EXIT_NO_RESOURCE; } memset(io_reqs, 0, io_req_sz); ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_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, &sa_old) < 0) pr_fail_err(name, "sigaction"); /* Kick off requests */ for (i = 0; i < opt_aio_requests; i++) { aio_fill_buffer(i, io_reqs[i].buffer, BUFFER_SZ); ret = issue_aio_request(name, fd, (off_t)i * BUFFER_SZ, &io_reqs[i], i, aio_write); if (ret < 0) goto cancel; if (ret > 0) { rc = EXIT_SUCCESS; goto cancel; } } do { usleep(250000); /* wait until a signal occurs */ for (i = 0; opt_do_run && (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(name, fd, (off_t)i * BUFFER_SZ, &io_reqs[i], i, (mwc32() & 0x8) ? aio_read : aio_write) < 0) goto cancel; break; case EINPROGRESS: break; default: /* Something went wrong */ pr_fail_errno(name, "aio_error", io_reqs[i].status); goto cancel; } } } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; cancel: /* Stop accounting */ do_accounting = false; /* Cancel pending AIO requests */ for (i = 0; i < opt_aio_requests; i++) { aio_issue_cancel(name, &io_reqs[i]); total += io_reqs[i].count; } (void)close(fd); finish: pr_dbg(stderr, "%s: total of %" PRIu64 " async I/O signals caught (instance %d)\n", name, total, instance); (void)stress_temp_dir_rm(name, pid, instance); return rc; } #endif stress-ng-0.05.23/stress-daemon.c0000664000175000017500000000562112702231255015205 0ustar kingking/* * Copyright (C) 2013-2016 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" /* * daemons() * fork off a child and let the parent die */ static void daemons(const int fd) { int fds[3]; if (setsid() < 0) goto err; (void)close(0); (void)close(1); (void)close(2); if ((fds[0] = open("/dev/null", O_RDWR)) < 0) goto err; if ((fds[1] = dup(0)) < 0) goto err0; if ((fds[2] = dup(0)) < 0) goto err1; for (;;) { pid_t pid; pid = fork(); if (pid < 0) { goto err; } else if (pid == 0) { /* Child */ char buf[1] = { 0xff }; ssize_t sz; if (chdir("/") < 0) goto err; (void)umask(0); sz = write(fd, buf, sizeof(buf)); if (sz != sizeof(buf)) goto err; } else { /* Parent, will be reaped by init */ return; } } (void)close(fds[2]); err1: (void)close(fds[1]); err0: (void)close(fds[0]); err: (void)close(fd); } /* * stress_daemon() * stress by multiple daemonizing forks */ int stress_daemon( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fds[2]; pid_t pid; (void)instance; if (pipe(fds) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { pr_fail_dbg(name, "fork"); (void)close(fds[0]); (void)close(fds[1]); return EXIT_FAILURE; } else if (pid == 0) { /* Children */ (void)close(fds[0]); daemons(fds[1]); (void)close(fds[1]); } else { /* Parent */ (void)close(fds[1]); do { ssize_t n; char buf[1]; n = read(fds[0], buf, sizeof(buf)); if (n < 0) { (void)close(fds[0]); if (errno != EINTR) { pr_dbg(stderr, "read failed: errno=%d (%s)\n", errno, strerror(errno)); } break; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } stress-ng-0.05.23/test-libaio.c0000664000175000017500000000234012702231255014630 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include /* The following functions from librt are used by stress-ng */ static void *aio_funcs[] = { io_setup, io_destroy, io_submit, io_getevents }; int main(void) { return 0; } stress-ng-0.05.23/stress-ng.10000664000175000017500000027734212702231255014277 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 "March 12, 2016" .\" 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 - 38) .nr SQ ((\n[.l] - \n[.i]) / 1n - 35) .SH NAME stress\-ng \- a tool to load and stress a computer system .sp 1 .SH SYNOPSIS .B stress\-ng [\fIOPTION \fR[\fIARG\fR]] ... .sp 1 .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 processors available as defined by sysconf(_SC_NPROCESSORS_CONF). .SH OPTIONS .PP .B General stress\-ng control options: .TP .B \-\-aggressive enables more file, cache and memory aggressive options. This may slow tests down, increase latencies and reduce the number of bogo ops as well as changing the balance of user time vs system time used depending on the type of stressor being used. .TP .B \-a N, \-\-all N start N instances of each stressor. If N is less than zero, then the number of CPUs online is used for the number of instances. If N is zero, then the number of CPUs in the system is used. .TP .B \-b N, \-\-backoff N wait N microseconds between the start of each stress worker process. This allows one to ramp up the stress tests over time. .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, device, io, interrupt, filesystem, memory, network, os, pipe, 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 \-n, \-\-dry\-run parse options, but do not run stress tests. A no-op. .TP .B \-h, \-\-help show help. .TP .B \-\-ignite\-cpu alter kernel controls to try and maximize the CPU. This requires root privilege to alter various /sys interface controls. Currently this only works for Intel P-State enabled x86 systems on Linux. .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 (highest 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 \-\-log\-brief by default stress\-ng will report the name of the program, the message type and the process id as a prefix to all output. The \-\-log\-brief option will output messages without these fields to produce a less verbose output. .TP .B \-\-log\-file filename write messages to the specified log file. .TP .B \-\-maximize overrides the default stressor settings and instead sets these to the maximum settings allowed. These defaults can always be overridden by the per stressor settings options if required. .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 \-\-minimize overrides the default stressor settings and instead sets these to the minimum settings allowed. These defaults can always be overridden by the per stressor settings options if required. .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 \-\-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 \-\-pathological enable stressors that are known to hang systems. Some stressors can quickly consume resources in such a way that they can rapidly hang a system before the kernel can OOM kill them. These stressors are not enabled by default, this option enables them, but you probably don't want to do this. You have been warned. .TP .B \-\-perf measure processor and system activity using perf events. Linux only and caveat emptor, according to perf_event_open(2): "Always double-check your results! Various generalized events have had wrong values." .TP .B \-q, \-\-quiet do not show any output. .TP .B \-r N, \-\-random N start N random stress workers. If N is 0, then the number of configured processors is used for N. .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 \-\-sequential N sequentially run all the stressors one by one for a default of 60 seconds. The number of instances of each individual stressors to be started is N. If N is less than zero, then the number of CPUs online is used for the number of instances. If N is zero, then the number of CPUs in the system is used. Use the \-\-timeout option to specify the duration to run each stressor. .TP .B \-\-syslog log output (except for verbose \-v messages) to the syslog. .TP .B \-\-temp\-path path specify a path for stress\-ng temporary directories and temporary files; the default path is the current working directory. This path must have read and write access for the stress-ng stress processes. .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 \-\-timer\-slack N adjust the per process timer slack to N nanoseconds (Linux only). Increasing the timer slack allows the kernel to coalesce timer events by adding some fuzzinesss to timer expiration times and hence reduce wakeups. Conversely, decreasing the timer slack will increase wakeups. A value of 0 for the timer-slack will set the system default of 50,000 nanoseconds. .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 \-\-tz collect temperatures from the available thermal zones on the machine (Linux only). Some devices may have one or more thermal zones, where as others may have none. .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 \-x, \-\-exclude list specify a list of one or more stressors to exclude (that is, do not run them). This is useful to exclude specific stressors when one selects many stressors to run using the \-\-class option, \-\-sequential, \-\-all and \-\-random options. Example, run the cpu class stressors concurrently and exclude the numa and search stressors: .IP stress\-ng \-\-class cpu \-\-all 1 \-x numa,bsearch,hsearch,lsearch .TP .B \-Y, \-\-yaml filename output gathered statistics to a YAML formatted file named 'filename'. .br .sp 2 .PP .B Stressor specific options: .TP .B \-\-affinity N start N workers 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 workers after N bogo affinity operations (only on Linux). .TP .B \-\-affinity\-rand switch CPU affinity randomly rather than the default of sequentially. .TP .B \-\-af\-alg N start N workers that exercise the AF_ALG socket domain by hashing various sized random messages using SHA1, SHA224, SHA256, SHA384, SHA512, MD4, MD5, RMD128, RMD160, RMD256, RMD320, WP256, WP384, WP512, TGR128, TGR160 and TGR192 hashes. (Linux only). .TP .B \-\-af\-alg\-ops N stop af\-alg workers after N AF_ALG messages are hashed. .TP .B \-\-aio N start N workers that issue multiple small asynchronous I/O writes and reads on a relatively small temporary file using the POSIX aio interface. 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 worker process will handle 16 concurrent I/O requests. .TP .B \-\-aio\-ops N stop POSIX asynchronous I/O workers after N bogo asynchronous I/O requests. .TP .B \-\-aio\-requests N specify the number of POSIX asynchronous I/O requests each worker should issue, the default is 16; 1 to 4096 are allowed. .TP .B \-\-aiol N start N workers that issue multiple 4K random asynchronous I/O writes using the Linux aio system calls io_setup(2), io_submit(2), io_getevents(2) and io_destroy(2). By default, each worker process will handle 16 concurrent I/O requests. .TP .B \-\-aiol\-ops N stop Linux asynchronous I/O workers after N bogo asynchronous I/O requests. .TP .B \-\-aiol\-requests N specify the number of Linux asynchronous I/O requests each worker should issue, the default is 16; 1 to 4096 are allowed. .TP .B \-\-apparmor N start N workers that exercise various parts of the AppArmor interface. Currently one needs root permission to run this particular test. This test is only available on Linux systems with AppArmor support. .TP .B \-\-apparmor-ops stop the AppArmor workers after N bogo operations. .TP .B \-B N, \-\-bigheap N start N workers that grow their heaps by reallocating memory. If the out of memory killer (OOM) on Linux kills the worker or the allocation fails then the allocating process starts all over again. Note that the OOM adjustment for the worker is set so that the OOM killer will treat these workers as the first candidate processes to kill. .TP .B \-\-bigheap\-ops N stop the big heap workers 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 \-\-bind\-mount N start N workers that repeatedly bind mount / to / inside a user namespace. This can consume resources rapidly, forcing out of memory situations. Do not use this stressor unless you want to risk hanging your machine. .TP .B \-\-bind\-mount\-ops N stop after N bind mount bogo operations. .TP .B \-\-brk N start N workers 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 workers 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 workers 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 worker 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 workers 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\-level N specify level of cache to exercise (1=L1 cache, 2=L2 cache, 3=L3/LLC cache (the default)). If the cache hierarchy cannot be determined, built-in defaults will apply. .TP .B \-\-cache\-no\-affinity do not change processor affinity when .B \-\-cache is in effect. .TP .B \-\-cache\-ops N stop cache thrash workers after N bogo cache thrash operations. .TP .B \-\-cache\-prefetch force read prefetch on next read address on architectures that support prefetching. .TP .B \-\-cache\-ways N specify the number of cache ways to exercise. This allows a subset of the overall cache size to be exercised. .TP .B \-\-cap N start N workers that read per process capabililties via calls to capget(2) (Linux only). .TP .B \-\-cap\-ops N stop after N cap bogo operations. .TP .B \-\-chdir N start N workers that change directory between 8192 directories using chdir(2). .TP .B \-\-chdir\-ops N stop after N chdir bogo operations. .TP .B \-\-chmod N start N workers 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 \-\-clock N start N workers 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 workers after N bogo operations. .TP .B \-\-clone N start N workers that create clones (via the clone(2) system call). This will rapidly try to create a default of 8192 clones that immediately die and wait in a zombie state until they are reaped. Once the maximum number of clones is reached (or clone fails because one has reached the maximum allowed) the oldest clone thread is reaped and a new clone is then created in a first-in first-out manner, and then repeated. A random clone flag is selected for each clone to try to exercise different clone operarions. The clone stressor is a Linux only option. .TP .B \-\-clone\-ops N stop clone stress workers after N bogo clone operations. .TP .B \-\-clone\-max N try to create as many as N clone threads. This may not be reached if the system limit is less than N. .TP .B \-\-context N start N workers that run three threads that use swapcontext(3) to implement the thread-to-thread context switching. This exercises rapid process context saving and restoring and is bandwidth limited by register and memory save and restore rates. .TP .B \-\-context\-ops N stop N context workers after N bogo context switches. In this stressor, 1 bogo op is equivalent to 1000 swapcontext calls. .TP .B \-\-copy\-file N start N stressors that copy a file using the Linux copy_file_range(2) system call. 2MB chunks of data are copyied from random locations from one file to random locations to a destination file. By default, the files are 256 MB in size. Data is sync'd to the filesystem after each copy_file_range(2) call. .TP .B \-\-copy\-file\-ops N stop after N copy_file_range() calls. .TP .B \-\-copy\-file\-bytes N copy file size, the default is 256 MB. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-c N, \-\-cpu N start N workers 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 workers after N bogo operations. .TP .B \-l P, \-\-cpu\-load P load CPU with P percent loading for the CPU stress workers. 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\-load\-slice S note \- this option is only useful when \-\-cpu\-load is less than 100%. The CPU load is broken into multiple busy and idle cycles. Use this option to specify the duration of a busy time slice. A negative value for S specifies the number of iterations to run before idling the CPU (e.g. -30 invokes 30 iterations of a CPU stress loop). A zero value selects a random busy time between 0 and 0.5 seconds. A positive value for S specifies the number of milliseconds to run before idling the CPU (e.g. 100 keeps the CPU busy for 0.1 seconds). Specifying small values for S lends to small time slices and smoother scheduling. Setting \-\-cpu\-load as a relatively low value and \-\-cpu\-load\-slice to be large will cycle the CPU between long idle and busy cycles and exercise different CPU frequencies. The thermal range of the CPU is also cycled, so this is a good mechanism to exercise the scheduler, frequency scaling and passive/active thermal cooling mechanisms. .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} callfunc T{ recursively call 8 argument C function to a depth of 1024 calls and unwind 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} crc16 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} dither T{ Floyd–Steinberg dithering of a 1024 \(mu 768 random image from 8 bits down to 1 bit of depth. 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} parity T{ compute parity using various methods from the Standford Bit Twiddling Hacks. Methods employed are: the na\[:i]ve way, the na\[:i]ve way with the Brian Kernigan bit counting optimisation, the multiply way, the parallel way, and the lookup table ways (2 variations). 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} queens T{ compute all the solutions of the classic 8 queens problem for board sizes 1..12 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 .sp 1 and has period of around 2 \[ua] 60 T} rand48 T{ 16384 iterations of drand48(3) and lrand48(3) 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} union T{ perform integer arithmetic on a mix of bit fields in a C union. This exercises how well the compiler and CPU can perform integer bit field loads and stores. 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 \-\-cpu\-online N start N workers that put randomly selected CPUs offline and online. This Linux only stressor requires root privilege to perform this action. .TP .B \-\-cpu\-online\-ops N stop after offline/online operations. .TP .B \-\-crypt N start N workers that encrypt a 16 character random password using crypt(3). The password is encrypted using MD5, SHA-256 and SHA-512 encryption methods. .TP .B \-\-crypt\-ops N stop after N bogo encryption operations. .TP .B \-\-daemon N start N workers that each create a daemon that dies immediately after creating another daemon and so on. This effectively works through the process table with short lived processes that do not have a parent and are waited for by init. This puts pressure on init to do rapid child reaping. The daemon processes perform the usual mix of calls to turn into typical UNIX daemons, so this artificially mimics very heavy daemon system stress. .TP .B \-\-daemon\-ops N stop daemon workers after N daemons have been created. .TP .B \-D N, \-\-dentry N start N workers 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 workers after N bogo dentry operations. .TP .B \-\-dentry\-order [ forward | reverse | stride | random ] specify unlink order of dentries, can be one of forward, reverse, stride or random. By default, dentries are unlinked in random order. The forward order will unlink them from first to last, reverse order will unlink them from last to first, stride order will unlink them by stepping around order in a quasi-random pattern and random order will randomly select one of forward, reverse or stride orders. .TP .B \-\-dentries N create N dentries per dentry thrashing loop, default is 2048. .TP .B \-\-dir N start N workers that create and remove directories using mkdir and rmdir. .TP .B \-\-dir\-ops N stop directory thrash workers after N bogo directory operations. .TP .B \-\-dup N start N workers 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 workers after N bogo open operations. .TP .B \-\-epoll N start N workers that perform various related socket stress activity using epoll_wait(2) 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 specify 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 workers 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 \-\-exec N start N workers continually forking children that exec stress-ng and then exit almost immediately. .TP .B \-\-exec\-ops N stop exec stress workers after N bogo operations. .TP .B \-\-exec\-max P create P child processes that exec stress-ng 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 process table using high values for \-\-exec\-max and \-\-exec. .TP .B \-F N, \-\-fallocate N start N workers continually fallocating (preallocating file space) and ftuncating (file truncating) temporary files. If the file is larger than the free space, fallocate will produce an ENOSPC error which is ignored by this stressor. .TP .B \-\-fallocate\-bytes N allocated file size, 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 \-\-fallocate\-ops N stop fallocate stress workers after N bogo fallocate operations. .TP .B \-\-fault N start N workers that generates minor and major page faults. .TP .B \-\-fault\-ops N stop the page fault workers after N bogo page fault operations. .TP .B \-\-fcntl N start N workers that perform fcntl(2) calls with various commands. The exercised commands (if available) are: F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG and F_SETSIG. .TP .B \-\-fcntl\-ops N stop the fcntl workers after N bogo fcntl operations. .TP .B \-\-fiemap N start N workers that each create a file with many randomly changing extents and has 4 child processes per worker that gather the extent information using the FS_IOC_FIEMAP ioctl(2). .TP .B \-\-fiemap\-ops N stop after N fiemap bogo operations. .TP .B \-\-fiemap\-size N specify the size of the fiemap'd file in bytes. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. Larger files will contain more extents, causing more stress when gathering extent information. .TP .B \-\-fifo N start N workers that exercise a named pipe by 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 workers that read the named pipe using simple blocking reads. .TP .B \-\-filename N start N workers that exercise file creation using various length filenames containing a range of allower filename characters. This will try to see if it can exceed the file system allowed filename length was well as test various filename lengths between 1 and the maximum allowed by the file system. .TP .B \-\-filename-ops N stop filename workers after N bogo filename tests. .TP .B \-\-filename-opts opt use characters in the filename based on option 'opt'. Valid options are: .TS expand; lB lBw(\n[SZ]n) l l. Option Description probe T{ default option, probe the file system for valid allowed characters in a file name and use these T} posix T{ use characters as specifed by The Open Group Base Specifications Issue 7, POSIX.1-2008, 3.278 Portable Filename Character Set T} ext T{ use characters allowed by the ext2, ext3, ext4 file systems, namely any 8 bit character apart from NUL and / T} .TE .TP .B \-\-flock N start N workers locking on a single file. .TP .B \-\-flock\-ops N stop flock stress workers after N bogo flock operations. .TP .B \-f N, \-\-fork N start N workers continually forking children that immediately exit. .TP .B \-\-fork\-ops N stop fork stress workers after N bogo operations. .TP .B \-\-fork\-max P create P child 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 \-\-fp\-error N start N workers that generate floating point exceptions. Computations are performed to force and check for the FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW and FE_UNDERFLOW exceptions. EDOM and ERANGE errors are also checked. .TP .B \-\-fp\-error\-ops N stop after N bogo floating point exceptions. .TP .B \-\-fstat N start N workers fstat'ing files in a directory (default is /dev). .TP .B \-\-fstat\-ops N stop fstat stress workers 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 workers that rapidly exercise the futex system call. Each worker 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 workers after N bogo successful futex wait operations. .TP .B \-\-get N start N workers that call all the get*(2) system calls. .TP .B \-\-get\-ops N stop get workers after N bogo get operations. .TP .B \-\-getdent N start N workers that recursively read directories /proc, /dev/, /tmp, /sys and /run using getdents and getdents64 (Linux only). .TP .B \-\-getdent\-ops N stop getdent workers after N bogo getdent bogo operations. .TP .B \-\-getrandom N start N workers that get 8192 random bytes from the /dev/urandom pool using the getrandom(2) system call (Linux only). .TP .B \-\-getrandom\-ops N stop getrandom workers after N bogo get operations. .TP .B \-\-handle N start N workers that exercise the name_to_handle_at(2) and open_by_handle_at(2) system calls. (Linux only). .TP .B \-\-handle\-ops N stop after N handle bogo operations. .TP .B \-d N, \-\-hdd N start N workers continually writing, reading 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 (using the O_DSYNC open flag). This is equivalent to each write(2) being followed by a call to fdatasync(2). See also the fdatasync option. T} fadv\-dontneed T{ advise kernel to expect the data will not be accessed in the near future. T} fadv\-noreuse T{ advise kernel to expect the data to be accessed only once. T} fadv\-normal T{ advise kernel there are no explicit access pattern for the data. This is the default advice assumption. T} fadv\-rnd T{ advise kernel to expect random access patterns for the data. T} fadv\-seq T{ advise kernel to expect sequential access patterns for the data. T} fadv\-willneed T{ advise kernel to expect the data to be accessed in the near future. T} fsync T{ flush all modified in-core data after each write to the output device using an explicit fsync(2) call. T} fdatasync T{ similar to fsync, but do not flush the modified metadata unless metadata is required for later data reads to be handled correctly. This uses an explicit fdatasync(2) call. T} iovec T{ use readv/writev multiple buffer I/Os rather than read/write. Instead of 1 read/write operation, the buffer is broken into an iovec of 16 buffers. 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 (using the O_SYNC open flag). This is equivalent to a each write(2) being followed by a call to fsync(2). See also the fsync option. 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 randomly. 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} syncfs T{ write all buffered modifications of file metadata and data on the filesystem that contains the hdd worker files. T} utimes T{ force update of file timestamp which may increase metadata writes. T} wr\-rnd T{ write data randomly. The wr\-seq option cannot be used at the same time. T} wr\-seq T{ write data sequentially. This is the default if no write modes are specified. T} .TE .RE .PP 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 workers after N bogo operations. .TP .B \-\-hdd\-write\-size N specify size of each write in bytes. Size can be from 1 byte to 4MB. .TP .B \-\-heapsort N start N workers that sort 32 bit integers using the BSD heapsort. .TP .B \-\-heapsort\-ops N stop heapsort stress workers after N bogo heapsorts. .TP .B \-\-heapsort\-size N specify number of 32 bit integers to sort, default is 262144 (256 \(mu 1024). .TP .B \-\-hsearch N start N workers 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 workers 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 \-\-icache N start N workers that stress the instruction cache by forcing instruction cache reloads. This is achieved by modifying an instruction cache line, causing the processor to reload it when we call a function in inside it. Currently only verified and enabled for Intel x86 CPUs. .TP .B \-\-icache\-ops N stop the icache workers after N bogo icache operations are completed. .TP .B \-\-inotify N start N workers 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 workers after N inotify bogo operations. .TP .B \-i N, \-\-io N start N workers 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 workers after N bogo operations. .TP .B \-\-itimer N start N workers that exercise the system interval timers. This sets up an ITIMER_PROF itimer that generates a SIGPROF signal. The default frequency for the itimer is 1 MHz, however, the Linux kernel will set this to be no more that the jiffy setting, hence high frequency SIGPROF signals are not normally possible. A busy loop spins on getitimer(2) calls to consume CPU and hence decrement the itimer based on amount of time spent in CPU and system time. .TP .B \-\-itimer\-ops N stop itimer stress workers after N bogo itimer SIGPROF signals. .TP .B \-\-itimer\-freq F run itimer at F Hz; range from 1 to 1000000 Hz. Normally the highest frequency is limited by the number of jiffy ticks per second, so running above 1000 Hz is difficult to attain in practice. .TP .B \-\-kcmp N start N workers that use kcmp(2) to compare parent and child processes to determine if they share kernel resources (Linux only). .TP .B \-\-kcmp\-ops N stop kcmp workers after N bogo kcmp operations. .TP .B \-\-key N start N workers that create and manipulate keys using add_key(2) and ketctl(2). As many keys are created as the per user limit allows and then the following keyctl commands are exercised on each key: KEYCTL_SET_TIMEOUT, KEYCTL_DESCRIBE, KEYCTL_UPDATE, KEYCTL_READ, KEYCTL_CLEAR and KEYCTL_INVALIDATE. .TP .B \-\-key\-ops N stop key workers after N bogo key operations. .TP .B \-\-kill N start N workers 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 workers after N bogo kill operations. .TP .B \-\-klog N start N workers exercising the kernel syslog(2) system call. This will attempt to read the kernel log with various sized read buffers. Linux only. .TP .B \-\-klog\-ops N stop klog workers after N syslog operations. .TP .B \-\-lease N start N workers 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 workers after N bogo operations. .TP .B \-\-lease\-breakers N start N lease breaker child processes per lease worker. 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 workers creating and removing hardlinks. .TP .B \-\-link\-ops N stop link stress workers after N bogo operations. .TP .B \-\-lockbus N start N workers that rapidly lock and increment 64 bytes of randomly chosen memory from a 16MB mmap'd region (Intel x86 CPUs only). This will cause cacheline misses and stalling of CPUs. .TP .B \-\-lockbus-ops N stop lockbus workers after N bogo operations. .TP .B \-\-lockf N start N workers that randomly lock and unlock regions of a file using the POSIX lockf(3) locking mechanism. Each worker creates a 64K file and attempts to hold a maximum of 1024 concurrent locks with a child process that also tries to hold 1024 concurrent locks. Old locks are unlocked in a first-in, first-out basis. .TP .B \-\-lockf\-ops N stop lockf workers 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 workers increases and should increase locking contention. .TP .B \-\-longjmp N start N workers that exercise setjmp(3)/longjmp(3) by rapid looping on longjmp calls. .TP .B \-\-longjmp-ops N stop longjmp stress workers after N bogo longjmp operations (1 bogo op is 1000 longjmp calls). .TP .B \-\-lsearch N start N workers 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 workers after N bogo lsearch operations are completed. .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 \-\-malloc N start N workers 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 worker 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 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 successful malloc(3), calloc(3) or realloc(3). .TP .B \-\-malloc\-thresh N specify the threshold where malloc uses mmap(2) instead of sbrk(2) to allocate more memory. This is only available on systems that provide the GNU C mallopt(3) tuning function. .TP .B \-\-matrix N start N workers that perform various matrix operations on floating point values. By default, this will exercise all the matrix stress methods one by one. One can specify a specific matrix stress method with the \-\-matrix\-method option. .TP .B \-\-matrix\-ops N stop matrix stress workers after N bogo operations. .TP .B \-\-matrix\-method method specify a matrix stress method. Available matrix stress methods are described as follows: .TS expand; lB2 lBw(\n[SZ]n) l l. Method Description all T{ iterate over all the below matrix stress methods T} add T{ add two N \(mu N matrices T} copy T{ copy one N \(mu N matrix to another T} div T{ divide an N \(mu N matrix by a scalar T} hadamard T{ Hadamard product of two N \(mu N matrices T} frobenius T{ Frobenius product of two N \(mu N matrices T} mean T{ arithmetic mean of two N \(mu N matrices T} mult T{ multiply an N \(mu N matrix by a scalar T} prod T{ product of two N \(mu N matrices T} sub T{ subtract one N \(mu N matrix from another N \(mu N matrix T} trans T{ transpose an N \(mu N matrix T} .TE .TP .B \-\-matrix\-size N specify the N \(mu N size of the matrices. Smaller values result in a floating point compute throughput bound stressor, where as large values result in a cache and/or memory bandwidth bound stressor. .TP .B \-\-membarrier N start N workers that exercise the membarrier system call (Linux only). .TP .B \-\-membarrier\-ops N stop membarrier stress workers after N bogo membarrier operations. .TP .B \-\-memcpy N start N workers 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 workers after N bogo memcpy operations. .TP .B \-\-memfd N start N workers that create 256 allocations of 1024 pages using memfd_create(2) and ftruncate(2) for allocation and mmap(2) to map the allocation into the process address space. (Linux only). .TP .B \-\-memfd-ops N stop after N memfd-create(2) bogo operations. .TP .B -\-mergesort N start N workers that sort 32 bit integers using the BSD mergesort. .TP .B \-\-mergesort\-ops N stop mergesort stress workers after N bogo mergesorts. .TP .B \-\-mergesort\-size N specify number of 32 bit integers to sort, default is 262144 (256 \(mu 1024). .TP .B \-\-mincore N start N workers 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 \-\-mknod N start N workers that create and remove fifos, empty files and named sockets using mknod and unlink. .TP .B \-\-mknod\-ops N stop directory thrash workers after N bogo mknod operations. .TP .B \-\-mlock N start N workers that lock and unlock memory mapped pages using mlock(2), munlock(2), mlockall(2) and munlockall(2). This is achieved by the mapping of three contiguous pages and then locking the second page, hence ensuring non-contiguous pages are locked . This is then repeated until the maximum allowed mlocks or a maximum of 262144 mappings are made. Next, all future mappings are mlocked and the worker attempts to map 262144 pages, then all pages are munlocked and the pages are unmapped. .TP .B \-\-mlock\-ops N stop after N mlock bogo operations. .TP .B \-\-mmap N start N workers 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 workers 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 worker, 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 \-\-mmapfork N start N workers that each fork off 32 child processes, each of which tries to allocate some of the free memory left in the system (and trying to avoid any swapping). The child processes then hint that the allocation will be needed with madvise(2) and then memset it to zero and hint that it is no longer needed with madvise before exiting. This produces significant amounts of VM activity, a lot of cache misses and with minimal swapping. .TP .B \-\-mmapfork-ops N stop after N mmapfork bogo operations. .TP .B \-\-mmapmany N start N workers that attempt to create the maximum allowed per-process memory mappings. This is achieved by mapping 3 contiguous pages and then unmapping the middle page hence splitting the mapping into two. This is then repeated until the maximum allowed mappings or a maximum of 262144 mappings are made. .TP .B \-\-mmapmany\-ops N stop after N mmapmany bogo operations. .TP .B \-\-mremap N start N workers 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 worker is only available for Linux. .TP .B \-\-mremap\-ops N stop mremap stress workers after N bogo operations. .TP .B \-\-mremap\-bytes N initially allocate N bytes per remap stress worker, 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 workers 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 \-\-null N start N workers writing to /dev/null. .TP .B \-\-null\-ops N stop null stress workers after N /dev/null bogo write operations. .TP .B \-\-numa N start N workers that migrate stressors and a 4MB memory mapped buffer around all the available NUMA nodes. This uses migrate_pages(2) to move the stressors and mbind(2) and move_pages(2) to move the pages of the mapped buffer. After each move, the buffer is written to force activity over the bus which results cache misses. This test will only run on hardware with NUMA enabled and more than 1 NUMA node. .TP .B \-\-numa\-ops N stop NUMA stress workers after N bogo NUMA operations. .TP .B \-\-oom\-pipe N start N workers that create as many pipes as allowed and exercise expanding and shrinking the pipes from the largest pipe size down to a page size. Data is written into the pipes and read out again to fill the pipe buffers. With the \-\-aggressive mode enabled the data is not read out when the pipes are shrunk, causing the kernel to OOM processes aggressively. Running many instances of this stressor will force kernel to OOM processes due to the many large pipe buffer allocations. .TP .B \-\-oom\-pipe\-ops N stop after N bogo pipe expand/shrink operations. .TP .B \-o N, \-\-open N start N workers 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 workers after N bogo open operations. .TP .B \-\-personality N start N workers that attempt to set personality and get all the available personality types (process execution domain types) via the personality(2) system call. (Linux only). .TP .B \-\-personality\-ops N stop personality stress workers after N bogo personality operations. .TP .B \-p N, \-\-pipe N start N workers that perform large pipe writes and reads to exercise pipe I/O. This exercises memory write and reads as well as context switching. Each worker has two processes, a reader and a writer. .TP .B \-\-pipe\-ops N stop pipe stress workers after N bogo pipe write operations. .TP .B \-\-pipe\-data\-size N specifies the size in bytes of each write to the pipe (range from 4 bytes to 4096 bytes). Setting a small data size will cause more writes to be buffered in the pipe, hence reducing the context switch rate between the pipe writer and pipe reader processes. Default size is the page size. .TP .B \-\-pipe\-size N specifies the size of the pipe in bytes (for systems that support the F_SETPIPE_SZ fcntl() command). Setting a small pipe size will cause the pipe to fill and block more frequently, hence increasing the context switch rate between the pipe writer and the pipe reader processes. Default size is 512 bytes. .TP .B \-P N, \-\-poll N start N workers 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 workers after N bogo poll operations. .TP .B \-\-procfs N start N workers 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 1024 pthreads per 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 \-\-ptrace N start N workers that fork and trace system calls of a child process using ptrace(2). .TP .B \-\-ptrace\-ops N stop ptracer workers after N bogo system calls are traced. .TP .B \-Q, \-\-qsort N start N workers that sort 32 bit integers using qsort. .TP .B \-\-qsort\-ops N stop qsort stress workers 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 \-\-quota N start N workers that exercise the Q_GETQUOTA, Q_GETFMT, Q_GETINFO, Q_GETSTATS and Q_SYNC quotactl(2) commands on all the available mounted block based file systems. .TP .B \-\-\quota\-ops N stop quota stress workers after N bogo quotactl operations. .TP .B \-\-rdrand N start N workers that read the Intel hardware random number generator (Intel Ivybridge processors upwards). .TP .B \-\-rdrand\-ops N stop rdrand stress workers after N bogo rdrand operations (1 bogo op = 2048 random bits successfully read). .TP .B \-\-readahead N start N workers that randomly seeks and performs 512 byte read/write I/O operations on a file with readahead. The default file size is 1 GB. Readaheads and reads are batched into 16 readaheads and then 16 reads. .TP .B \-\-readahead\-bytes N set the size of readahead file, 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 \-\-readahead\-ops N stop readahead stress workers after N bogo read operations. .TP .B \-\-remap N start N workers that map 512 pages and re-order these pages using the deprecated system call remap_file_pages(2). Several page re-orderings are exercised: forward, reverse, random and many pages to 1 page. .TP .B \-\-remap\-ops N stop after N remapping bogo operations. .TP .B \-R N, \-\-rename N start N workers that each create a file and then repeatedly rename it. .TP .B \-\-rename\-ops N stop rename stress workers after N bogo rename operations. .TP .B \-\-rlimit N start N workers that exceed CPU and file size resource imits, generating SIGXCPU and SIGXFSZ signals. .TP .B \-\-rlimit\-ops N stop after N bogo resource limited SIGXCPU and SIGXFSZ signals have been caught. .TP .B \-\-seccomp N start N workers that exercise Secure Computing system call filtering. Each worker creates child processes that write a short message to /dev/null and then exits. 2% of the child processes have a seccomp filter that disallows the write system call and hence it is killed by seccomp with a SIGSYS. Note that this stressor can generate many audit log messages each time the child is killed. .TP .B \-\-seccomp-ops N stop seccomp stress workers after N seccomp filter tests. .TP .B \-\-seek N start N workers 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 workers after N bogo seek operations. .TP .B \-\-seek\-punch punch randomly located 8K holes into the file to cause more extents to force a more demanding seek stressor, (Linux only). .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 workers after N bogo semaphore operations. .TP .B \-\-sem\-procs N start N child workers 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 workers 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 workers 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 workers 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 \-\-shm N start N workers that open and allocate shared memory objects using the POSIX shared memory interfaces. By default, the test will repeatedly create and destroy 32 shared memory objects, each of which is 8MB in size. .TP .B \-\-shm\-ops N stop after N POSIX shared memory create and destroy bogo operations are complete. .TP .B \-\-shm\-bytes N specify the size of the POSIX shared memory objects 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\-objs N specify the number of shared memory objects to be created. .TP .B \-\-shm\-sysv N start N workers 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 workers that generate SIGRT 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 when all CPUs are fully loaded. .TP .B \-\-sigfd\-ops stop sigfd workers after N bogo SIGUSR1 signals are sent. .TP .B \-\-sigfpe N start N workers that rapidly cause division by zero SIGFPE faults. .TP .B \-\-sigfpe\-ops N stop sigfpe stress workers after N bogo SIGFPE faults. .TP .B \-\-sigpending N start N workers that check if SIGUSR1 signals are pending. This stressor masks SIGUSR1, generates a SIGUSR1 signal and uses sigpending(2) to see if the signal is pending. Then it unmasks the signal and checks if the signal is no longer pending. .TP .B \-\-signpending-ops N stop sigpending stress workers after N bogo sigpending pending/unpending checks. .TP .B \-\-sigsegv N start N workers that rapidly create and catch segmentation faults. .TP .B \-\-sigsegv\-ops N stop sigsegv stress workers after N bogo segmentation faults. .TP .B \-\-sigsuspend N start N workers that each spawn off 4 child processes that wait for a SIGUSR1 signal from the parent using sigsuspend(2). The parent sends SIGUSR1 signals to each child in rapid succession. Each sigsuspend wakeup is counted as one bogo operation. .TP .B \-\-sigsuspend-ops N stop sigsuspend stress workers after N bogo sigsuspend wakeups. .TP .B \-\-sigq N start N workers 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 workers after N bogo signal send operations. .TP .B \-\-sleep N start N workers that spawn off multiple threads that each perform multiple sleeps of ranges 1us to 0.1s. This creates multiple context switches and timer interrupts. .TP .B \-\-sleep\-ops N stop after N sleep bogo operations. .TP .B \-\-sleep\-max P start P threads per worker. The default is 1024, the maximum allowed is 30000. .TP .B \-S N, \-\-sock N start N workers 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 specify the domain to use, the default is ipv4. Currently ipv4, ipv6 and unix are supported. .TP .B \-\-sock\-nodelay This disables the TCP Nagle algorithm, so data segments are always sent as soon as possible. This stops data from being buffered before being transmitted, hence resulting in poorer network utilisation and more context switches between the sender and receiver. .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 workers after N bogo operations. .TP .B \-\-sock\-opts [ send | sendmsg | sendmmsg ] by default, messages are sent using send(2). This option allows one to specify the sending method using send(2), sendmsg(2) or sendmmsg(2). Note that sendmmsg is only available for Linux systems that support this system call. .TP .B \-\-sockfd N start N workers that pass file descriptors over a UNIX domain socket using the CMSG(3) ancillary data mechanism. For each worker, pair of client/server processes are created, the server opens as many file descriptors on /dev/null as possible and passing these over the socket to a client that reads these from the CMSG data and immediately closes the files. .TP .B \-\-sockfd\-ops N stop sockfd stress workers after N bogo operations. .TP .B \-\-sockpair N start N workers that perform socket pair I/O read/writes. This involves a pair of client/server processes performing randomly sized socket I/O operations. .TP .B \-\-sockpair\-ops N stop socket pair stress workers after N bogo operations. .TP .B \-\-spawn N start N workers continually spawn children using posix_spawn(3) that exec stress-ng and then exit almost immediately. .TP .B \-\-spawn\-ops N stop spawn stress workers after N bogo spawns. .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 workers that rapidly cause and catch stack overflows by use of alloca(3). .TP .B \-\-stack\-full the default action is to touch the lowest page on each stack allocation. This option touches all the pages by filling the new stack allocation with zeros which forces physical pages to be allocated and hence is more aggressive. .TP .B \-\-stack\-ops N stop stack stress workers after N bogo stack overflows. .TP .B \-\-str N start N workers that exercise various libc string functions on random strings. .TP .B \-\-str-method strfunc select a specific libc string function to stress. Available string functions to stress are: all, index, rindex, strcasecmp, strcat, strchr, strcoll, strcmp, strcpy, strlen, strncasecmp, strncat, strncmp, strrchr and strxfrm. See string(3) for more information on these string functions. The 'all' method is the default and will exercise all the string methods. .TP .B \-\-str-ops N stop after N bogo string operations. .TP .B \-\-stream N start N workers exercising a memory bandwidth stressor loosely based on the STREAM "Sustainable Memory Bandwidth in High Performance Computers" benchmarking tool by John D. McCalpin, Ph.D. This stressor allocates buffers that are at least 4 times the size of the CPU L2 cache and continually performs rounds of following computations on large arrays of double precision floating point numbers: .TS expand; lB2 lBw(\n[SQ]n) l l. Operation Description copy T{ c[i] = a[i] T} scale T{ b[i] = scalar * c[i] T} add T{ c[i] = a[i] + b[i] T} triad T{ a[i] = b[i] + (c[i] * scalar) T} .TE .RS .PP Since this is loosely based on a variant of the STREAM benchmark code, DO NOT submit results based on this as it is intended to in stress-ng just to stress memory and compute and NOT intended for STREAM accurate tuned or non-tuned benchmarking whatsoever. Use the official STREAM benchmarking tool if you desire accurate and standardised STREAM benchmarks. .RE .TP .B \-\-stream\-ops N stop after N stream bogo operations, where a bogo operation is one round of copy, scale, add and triad operations. .TP .B \-\-stream\-l3\-size N Specify the CPU Level 3 cache size in bytes. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. If the L3 cache size is not provided, then stress-ng will attempt to determine the cache size, and failing this, will default the size to 4MB. .TP .B \-s N, \-\-switch N start N workers that send messages via pipe to a child to force context switching. .TP .B \-\-switch\-ops N stop context switching workers after N bogo operations. .TP .B \-\-symlink N start N workers creating and removing symbolic links. .TP .B \-\-symlink\-ops N stop symlink stress workers after N bogo operations. .TP .B \-\-sync\-file N start N workers that perform a range of data syncs across a file using sync_file_range(2). Three mixes of syncs are performed, from start to the end of the file, from end of the file to the start, and a random mix. A random selection of valid sync types are used, covering the SYNC_FILE_RANGE_WAIT_BEFORE, SYNC_FILE_RANGE_WRITE and SYNC_FILE_RANGE_WAIT_AFTER flag bits. .TP .B \-\-sync\-file\-ops N stop sync\-file workers after N bogo sync operations. .TP .B \-\-sync\-file\-bytes N specify the size of the file to be sync'd. One can specify the size in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. .TP .B \-\-sysinfo N start N workers 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 workers after N bogo operations. .TP .B \-\-sysfs N start N workers that recursively read files from /sys (Linux only). This may cause specific kernel drivers to emit messages into the kernel log. .TP .B \-\-sys\-ops N stop sysfs 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 \-\-tee N move data from a writer process to a reader process through pipes and to /dev/null without any copying between kernel address space and user address space using tee(2). This is only available for Linux. .TP .B \-\-tee-ops N stop after N bogo tee operations. .TP .B \-T N, \-\-timer N start N workers creating timer events at a default rate of 1 MHz (Linux only); this can create a many thousands of timer clock interrupts. Each timer event is caught by a signal handler and counted as a bogo timer op. .TP .B \-\-timer\-ops N stop timer stress workers after N bogo timer events (Linux only). .TP .B \-\-timer\-freq F run timers at F Hz; range from 1 to 1000000000 Hz (Linux only). By selecting an appropriate frequency stress\-ng can generate hundreds of thousands of interrupts per second. .TP .B \-\-timer\-rand select a timer frequency based around the timer frequency +/- 12.5% random jitter. This tries to force more variability in the timer interval to make the scheduling less predictable. .TP .B \-\-timerfd N start N workers creating timerfd events at a default rate of 1 MHz (Linux only); this can create a many thousands of timer clock events. Timer events are waited for on the timer file descriptor using select(2) and then read and counted as a bogo timerfd op. .TP .B \-\-timerfd\-ops N stop timerfd stress workers after N bogo timerfd events (Linux only). .TP .B \-\-timerfd\-freq F run timers at F Hz; range from 1 to 1000000000 Hz (Linux only). By selecting an appropriate frequency stress\-ng can generate hundreds of thousands of interrupts per second. .TP .B \-\-timerfd\-rand select a timerfd frequency based around the timer frequency +/- 12.5% random jitter. This tries to force more variability in the timer interval to make the scheduling less predictable. .TP .B \-\-tsc N start N workers that read the Time Stamp Counter (TSC) 256 times per loop iteration (bogo operation). Available only on Intel x86 platforms. .TP .B \-\-tsc\-ops N stop the tsc workers after N bogo operations are completed. .TP .B \-\-tsearch N start N workers 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 workers 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 workers 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 specify the domain to use, the default is ipv4. Currently ipv4, ipv6 and unix are supported. .TP .B \-\-udp\-lite use the UDP-Lite (RFC 3828) protocol (only for ipv4 and ipv4 domains). .TP .B \-\-udp\-ops N stop udp stress workers after N bogo operations. .TP .B \-\-udp\-port P start at port P. For N udp worker processes, ports P to P - 1 are used. By default, ports 7000 upwards are used. .TP .B \-\-udp\-flood N start N workers that attempt to flood the host with UDP packets to random ports. The IP address of the packets are currently not spoofed. This is only available on systems that support AF_PACKET. .TP .B \-\-udp\-flood\-domain D specify the domain to use, the default is ipv4. Currently ipv4 and ipv6 are supported. .TP .B \-\-udp\-flood\-ops N stop udp-flood stress workers after N bogo operations. .TP .B \-\-unshare N start N workers that each fork off 32 child processes, each of which exercises the unshare(2) system call by disassociating parts of the process execution context. (Linux only). .TP .B \-\-unshare\-ops N stop after N bogo unshare operations. .TP .B \-u N, \-\-urandom N start N workers reading /dev/urandom (Linux only). This will load the kernel random number source. .TP .B \-\-urandom\-ops N stop urandom stress workers after N urandom bogo read operations (Linux only). .TP .B \-\-userfaultfd N start N workers that generate write page faults on a small anonymously mapped memory region and handle these faults using the user space fault handling via the userfaultfd mechanism. This will generate a large quanity of major page faults and also context switches during the handling of the page faults. (Linux only). .TP .B \-\-userfaultfd-ops N stop userfaultfd stress workers after N page faults. .TP .B \-\-userfaultfd-bytes N mmap N bytes per userfaultfd worker to page fault on, 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 \-\-utime N start N workers 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 workers 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 workers 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 \(mu 8 bits, 8 \(mu 16 bits, 4 \(mu 32 bits, 2 \(mu 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 \-\-vfork N start N workers continually vforking children that immediately exit. .TP .B \-\-vfork\-ops N stop vfork stress workers 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 workers 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 worker, 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 workers 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 do not 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 workers 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 workers 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 workers 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; lBw(10n)2 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 patterns. 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 over 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} rowhammer T{ try to force memory corruption using the rowhammer memory stressor. This fetches two 32 bit integers from memory and forces a cache flush on the two addresses multiple times. This has been known to force bit flipping on some hardware, especially with lower frequency memory refresh cycles. 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 worker, 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 \-\-wcs N start N workers that exercise various libc wide character string functions on random strings. .TP .B \-\-wcs-method wcsfunc select a specific libc wide character string function to stress. Available string functions to stress are: all, wcscasecmp, wcscat, wcschr, wcscoll, wcscmp, wcscpy, wcslen, wcsncasecmp, wcsncat, wcsncmp, wcsrchr and wcsxfrm. The 'all' method is the default and will exercise all the string methods. .TP .B \-\-wcs-ops N stop after N bogo wide character string operations. .TP .B \-\-xattr N start N workers that create, update and delete batches of extended attributes on a file. .TP .B \-\-xattr\-ops N stop after N bogo extended attribute operations. .TP .B \-y N, \-\-yield N start N workers that call sched_yield(2). This stressor ensures that at least 2 child processes per CPU exercice shield_yield(2) no matter how many workers are specified, thus always ensuring rapid context switching. .TP .B \-\-yield\-ops N stop yield stress workers after N sched_yield(2) bogo operations. .TP .B \-\-zero N start N workers reading /dev/zero. .TP .B \-\-zero\-ops N stop zero stress workers after N /dev/zero bogo read operations. .TP .B \-\-zlib N start N workers compressing and decompressing random data using zlib. Each worker has two processes, one that compresses random data and pipes it to another process that decompresses the data. This stressor exercises CPU, cache and memory. .TP .B \-\-zlib\-ops N stop after N bogo compression operations, each bogo compression operation is a compression of 64K of random data at the highest compression level. .TP .B \-\-zombie N start N workers that create zombie processes. This will rapidly try to create a default of 8192 child processes that immediately die and wait in a zombie state until they are reaped. Once the maximum number of processes is reached (or fork fails because one has reached the maximum allowed number of children) the oldest child is reaped and a new process is then created in a first-in first-out manner, and then repeated. .TP .B \-\-zombie\-ops N stop zombie stress workers after N bogo zombie operations. .TP .B \-\-zombie\-max N try to create as many as N zombie processes. This may not be reached if the system limit is less than N. .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 summarise 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. .LP stress\-ng \-\-all 0 \-\-maximize \-\-aggressive .IP run all the stressors (1 instance of each per CPU) simultaneously, maximize the settings (memory sizes, file allocations, etc.) and select the most demanding/aggressive options. .LP stress\-ng \-\-random 32 \-x numa,hdd,key .IP run 32 randomly selected stressors and exclude the numa, hdd and key stressors .LP stress\-ng \-\-sequential 4 \-\-class vm \-\-exclude bigheap,brk,stack .IP run 4 instances of the VM stressors one after each other, excluding the bigheap, brk and stack stressors .SH EXIT STATUS .TS cBw(10) lBx c l. Status Description 0 T{ Success. T} 1 T{ Error; incorrect user options or a fatal resource issue in the stress-ng stressor harness (for example, out of memory). T} 2 T{ One or more stressors failed. T} 3 T{ One or more stressors failed to initialise because of lack of resources, for example ENOMEM (no memory) and ENOSPC (no space on file system). T} .TE .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 perf (1), .BR pthreads (7), .BR qsort (3), .BR sched_yield (2), .BR sched_setaffinity (2), .BR stress (1), .BR splice (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 . Thanks also for contributions from Christian Ehrhardt, James Hunt, Tim Gardner and Luca Pizzamiglio. .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-2016 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.05.23/stress-flock.c0000664000175000017500000000534412702231255015042 0ustar kingking/* * Copyright (C) 2013-2016 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_fail_err(name, "mkdir"); return exit_status(errno); } } /* * 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) { int rc = exit_status(errno); if ((errno == ENOENT) && opt_do_run) { /* Race, sometimes we need to retry */ goto retry; } /* Not sure why this fails.. report and abort */ pr_fail_err(name, "open"); (void)rmdir(dirname); return rc; } 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.05.23/test-apparmor.c0000664000175000017500000000311412702231255015212 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include #include int main(void) { int ret; aa_kernel_interface *kern_if; ret = aa_is_enabled(); if (ret < 0) return ret; ret = aa_kernel_interface_new(&kern_if, NULL, NULL); if (ret < 0) return ret; ret = aa_kernel_interface_load_policy(kern_if, NULL, 0); if (ret < 0) return ret; ret = aa_kernel_interface_replace_policy(kern_if, NULL, 0); if (ret < 0) return ret; ret = aa_kernel_interface_remove_policy(kern_if, "dummy"); if (ret < 0) return ret; aa_kernel_interface_unref(kern_if); return ret; } stress-ng-0.05.23/stress-epoll.c0000664000175000017500000003252312702231255015056 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_EPOLL) #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 #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(DOMAIN_ALL, "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 MLOCKED 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 MLOCKED void handle_socket_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * epoll_spawn() * spawn a process */ static pid_t 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; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); func(child, counter, instance, max_ops, name, ppid); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); 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) { while (opt_do_run) { 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_fail_err(name, "accept"); return -1; } /* * Add non-blocking fd to epoll event list */ if (epoll_set_fd_nonblock(fd) < 0) { pr_fail_err(name, "setting socket to non-blocking"); (void)close(fd); return -1; } if (epoll_ctl_add(efd, fd) < 0) { pr_fail_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 sigevent sev; struct itimerspec timer; struct sockaddr *addr = NULL; if (stress_sighandler(name, SIGRTMIN, epoll_timer_handler, NULL) < 0) return -1; do { char buf[4096]; int fd, saved_errno; 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_fail_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_fail_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_fail_err(name, "timer_settime"); (void)close(fd); return -1; } stress_set_sockaddr(name, instance, ppid, opt_epoll_domain, port, &addr, &addr_len); errno = 0; ret = connect(fd, addr, addr_len); saved_errno = errno; /* No longer need timer */ if (timer_delete(epoll_timerid) < 0) { pr_fail_err(name, "timer_delete"); (void)close(fd); return -1; } if (ret < 0) { switch (saved_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, saved_errno, strerror(saved_errno)); break; } (void)close(fd); usleep(100000); /* Twiddle fingers for a moment */ retries++; if (retries > 1000) { /* Sigh, give up.. */ errno = saved_errno; pr_fail_dbg(name, "too many connects"); return -1; } goto retry; } memset(buf, 'A' + (*counter % 26), sizeof(buf)); if (send(fd, buf, sizeof(buf), 0) < 0) { (void)close(fd); pr_fail_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 (addr && (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 epoll_event *events = NULL; struct sockaddr *addr = NULL; socklen_t addr_len = 0; if (stress_sighandler(name, SIGALRM, handle_socket_sigalrm, NULL) < 0) { rc = EXIT_FAILURE; goto die; } if ((sfd = socket(opt_epoll_domain, SOCK_STREAM, 0)) < 0) { pr_fail_err(name, "socket"); rc = EXIT_FAILURE; goto die; } if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_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_fail_err(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (epoll_set_fd_nonblock(sfd) < 0) { pr_fail_err(name, "setting socket to non-blocking"); rc = EXIT_FAILURE; goto die_close; } if (listen(sfd, SOMAXCONN) < 0) { pr_fail_err(name, "listen"); rc = EXIT_FAILURE; goto die_close; } if ((efd = epoll_create1(0)) < 0) { pr_fail_err(name, "epoll_create1"); rc = EXIT_FAILURE; goto die_close; } if (epoll_ctl_add(efd, sfd) < 0) { pr_fail_err(name, "epoll ctl add"); rc = EXIT_FAILURE; goto die_close; } if ((events = calloc(MAX_EPOLL_EVENTS, sizeof(struct epoll_event))) == NULL) { pr_fail_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_fail_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 incoming 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 (addr && (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_fail_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_fail_dbg(name, "waitpid"); } } } return rc; } #endif stress-ng-0.05.23/stress-apparmor.c0000664000175000017500000003350212702231255015562 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #include #include #include #include #include #if defined(STRESS_APPARMOR) #include #endif #define APPARMOR_BUF_SZ (4096) typedef int (*apparmor_func)(const char *name, const uint64_t max_ops, uint64_t *counter); #if defined(STRESS_APPARMOR) static volatile bool apparmor_run = true; static char *apparmor_path = NULL; extern char apparmor_data[]; extern const size_t apparmor_data_len; #endif /* * stress_apparmor_supported() * check if AppArmor is supported */ int stress_apparmor_supported(void) { #if defined(STRESS_APPARMOR) int fd; char path[PATH_MAX]; /* Initial sanity checks for AppArmor */ if (!aa_is_enabled()) { pr_inf(stderr, "apparmor stressor will be skipped, " "AppArmor is not enabled\n"); return -1; } if (aa_find_mountpoint(&apparmor_path) < 0) { pr_inf(stderr, "apparmor stressor will be skipped, " "cannot get AppArmor path, errno=%d (%s)\n", errno, strerror(errno)); return -1; } /* ..and see if profiles are accessible */ snprintf(path, sizeof(path), "%s/%s", apparmor_path, "profiles"); if ((fd = open(path, O_RDONLY)) < 0) { switch (errno) { case EACCES: pr_inf(stderr, "apparmor stressor will be skipped, " "stress-ng needs to be run with root " "privilege to access AppArmor /sys files.\n"); break; case ENOENT: pr_inf(stderr, "apparmor stressor will be skipped, " "AppArmor /sys files do not exist\n"); break; default: pr_inf(stderr, "apparmor stressor will be skipped, " "cannot access AppArmor /sys files: " "errno=%d (%s)\n", errno, strerror(errno)); break; } return -1; } (void)close(fd); return 0; #else pr_inf(stderr, "apparmor was not built in, missing apparmor development headers\n"); return -1; #endif } #if defined(STRESS_APPARMOR) /* * stress_lease_handler() * lease signal handler */ static void MLOCKED stress_apparmor_handler(int dummy) { (void)dummy; apparmor_run = false; } /* * stress_apparmor_read() * read a proc file */ static void stress_apparmor_read(const char *path) { int fd; ssize_t i = 0; char buffer[APPARMOR_BUF_SZ]; if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) return; /* * Multiple randomly sized reads */ while (apparmor_run && (i < (4096 * APPARMOR_BUF_SZ))) { ssize_t ret, sz = 1 + (mwc32() % sizeof(buffer)); redo: if (!opt_do_run) break; ret = read(fd, buffer, sz); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; break; } if (ret < sz) break; i += sz; } (void)close(fd); } /* * stress_apparmor_dir() * read directory */ static void stress_apparmor_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_apparmor_dir(name, recurse, depth + 1); } break; case DT_REG: snprintf(name, sizeof(name), "%s/%s", path, d->d_name); stress_apparmor_read(name); break; default: break; } } (void)closedir(dp); } /* * apparmor_spawn() * spawn a process */ static pid_t apparmor_spawn( const char *name, const uint64_t max_ops, uint64_t *counter, apparmor_func func) { pid_t pid; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { int ret; if (stress_sighandler(name, SIGALRM, stress_apparmor_handler, NULL) < 0) exit(EXIT_FAILURE); setpgid(0, pgrp); stress_parent_died_alarm(); ret = func(name, max_ops, counter); exit(ret); } setpgid(pid, pgrp); return pid; } /* * apparmor_stress_profiles() * hammer profile reading */ static int apparmor_stress_profiles( const char *name, const uint64_t max_ops, uint64_t *counter) { char path[PATH_MAX]; (void)name; snprintf(path, sizeof(path), "%s/%s", apparmor_path, "profiles"); do { stress_apparmor_read(path); (*counter)++; } while (apparmor_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } /* * apparmor_stress_features() * hammer features reading */ static int apparmor_stress_features( const char *name, const uint64_t max_ops, uint64_t *counter) { char path[PATH_MAX]; (void)name; snprintf(path, sizeof(path), "%s/%s", apparmor_path, "features"); do { stress_apparmor_dir(path, true, 0); (*counter)++; } while (apparmor_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } /* * apparmor_stress_kernel_interface() * load/replace/unload stressing */ static int apparmor_stress_kernel_interface( const char *name, const uint64_t max_ops, uint64_t *counter) { int rc = EXIT_SUCCESS; aa_kernel_interface *kern_if; /* * Try and create a lot of contention and load */ do { int ret = aa_kernel_interface_new(&kern_if, NULL, NULL); if (ret < 0) { pr_fail(stderr, "%s: aa_kernel_interface_new() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; break; } /* * Loading a policy may fail if another stressor has already loaded * the same policy, so we may get EEXIST */ ret = aa_kernel_interface_load_policy(kern_if, apparmor_data, apparmor_data_len); if (ret < 0) { if (errno != EEXIST) { pr_fail(stderr, "%s: aa_kernel_interface_load_policy() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } } /* * Replacing should always be atomic and not fail when competing against * other stressors if I understand the interface correctly. */ ret = aa_kernel_interface_replace_policy(kern_if, apparmor_data, apparmor_data_len); if (ret < 0) { aa_kernel_interface_unref(kern_if); pr_fail(stderr, "%s: aa_kernel_interface_replace_policy() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } /* * Removal may fail if another stressor has already removed the * policy, so we may get ENOENT */ ret = aa_kernel_interface_remove_policy(kern_if, "/usr/bin/pulseaudio-eg"); if (ret < 0) { if (errno != ENOENT) { pr_fail(stderr, "%s: aa_kernel_interface_remove_policy() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } } aa_kernel_interface_unref(kern_if); (*counter)++; } while (opt_do_run && apparmor_run && (!max_ops || *counter < max_ops)); return rc; } /* * apparmor_corrupt_flip_bits_random() * bit flip random bits in data */ static inline void apparmor_corrupt_flip_bits_random( char *copy, const size_t len) { uint32_t i; const uint32_t n = mwc32() % 17; for (i = 0; i < n; i++) { uint32_t rnd = mwc32(); copy[rnd % len] ^= (1 << ((rnd >> 16) & 7)); } } /* * apparmor_corrupt_flip_seq() * sequentially flip bits */ static inline void apparmor_corrupt_flip_seq( char *copy, const size_t len) { static size_t p = 0; if (p > (len * sizeof(char))) p = 0; copy[p / sizeof(char)] ^= (1 << (p & 7)); p++; } /* * apparmor_corrupt_clr_seq() * sequentially clear bits */ static inline void apparmor_corrupt_clr_seq( char *copy, const size_t len) { static size_t p = 0; if (p > (len * sizeof(char))) p = 0; copy[p / sizeof(char)] &= ~(1 << (p & 7)); p++; } /* * apparmor_corrupt_set_seq() * sequentially set bits */ static inline void apparmor_corrupt_set_seq( char *copy, const size_t len) { static size_t p = 0; if (p > (len * sizeof(char))) p = 0; copy[p / sizeof(char)] |= (1 << (p & 7)); p++; } /* * apparmor_corrupt_flip_byte_random() * ramndomly flip entire bytes */ static inline void apparmor_corrupt_flip_byte_random( char *copy, const size_t len) { copy[mwc32() % len] ^= 0xff; } /* * apparmor_corrupt_clr_bits_random() * randomly clear bits */ static inline void apparmor_corrupt_clr_bits_random( char *copy, const size_t len) { uint32_t i; const uint32_t n = mwc32() % 17; for (i = 0; i < n; i++) { uint32_t rnd = mwc32(); copy[rnd % len] &= ~(1 << ((rnd >> 16) & 7)); } } /* * apparmor_corrupt_set_bits_random() * randomly set bits */ static inline void apparmor_corrupt_set_bits_random( char *copy, const size_t len) { uint32_t i; const uint32_t n = mwc32() % 17; for (i = 0; i < n; i++) { uint32_t rnd = mwc32(); copy[rnd % len] |= (1 << ((rnd >> 16) & 7)); } } /* * apparmor_corrupt_clr_byte_random() * randomly clear an entire byte */ static inline void apparmor_corrupt_clr_byte_random( char *copy, const size_t len) { copy[mwc32() % len] = 0; } /* * apparmor_corrupt_set_byte_random() * randomly set an entire byte */ static inline void apparmor_corrupt_set_byte_random( char *copy, const size_t len) { copy[mwc32() % len] = 0xff; } /* * apparmor_corrupt_flip_bits_random_burst * randomly flip a burst of contiguous bits */ static inline void apparmor_corrupt_flip_bits_random_burst( char *copy, const size_t len) { uint32_t i; size_t p = (size_t)mwc32() % (len * sizeof(char)); for (i = 0; i < 32; i++) { if (p > (len * sizeof(char))) p = 0; copy[p / sizeof(char)] ^= (1 << (p & 7)); p++; } } /* * apparmor_stress_corruption() * corrupt data and see if we can oops the loader * parser. */ static int apparmor_stress_corruption( const char *name, const uint64_t max_ops, uint64_t *counter) { char copy[apparmor_data_len]; int rc = EXIT_SUCCESS; aa_kernel_interface *kern_if; /* * Lets feed AppArmor with some bit corrupted data... */ do { int ret; memcpy(copy, apparmor_data, apparmor_data_len); /* * Apply various corruption methods */ switch ((*counter) % 10) { case 0: apparmor_corrupt_flip_seq(copy, apparmor_data_len); break; case 1: apparmor_corrupt_clr_seq(copy, apparmor_data_len); break; case 2: apparmor_corrupt_set_seq(copy, apparmor_data_len); break; case 3: apparmor_corrupt_flip_bits_random(copy, apparmor_data_len); break; case 4: apparmor_corrupt_flip_byte_random(copy, apparmor_data_len); break; case 5: apparmor_corrupt_clr_bits_random(copy, apparmor_data_len); break; case 6: apparmor_corrupt_set_bits_random(copy, apparmor_data_len); break; case 7: apparmor_corrupt_clr_byte_random(copy, apparmor_data_len); break; case 8: apparmor_corrupt_set_byte_random(copy, apparmor_data_len); break; case 9: apparmor_corrupt_flip_bits_random_burst(copy, apparmor_data_len); break; default: /* Should not happen */ break; } ret = aa_kernel_interface_new(&kern_if, NULL, NULL); if (ret < 0) { pr_fail(stderr, "%s: aa_kernel_interface_new() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } /* * Expect EPROTO failures */ ret = aa_kernel_interface_replace_policy(kern_if, copy, apparmor_data_len); if (ret < 0) { if ((errno != EPROTO) && (errno != EPROTONOSUPPORT)) { pr_fail(stderr, "%s: aa_kernel_interface_replace_policy() failed, " "errno=%d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; } } aa_kernel_interface_unref(kern_if); (*counter)++; } while (opt_do_run && apparmor_run && (!max_ops || *counter < max_ops)); return rc; } static const apparmor_func apparmor_funcs[] = { apparmor_stress_profiles, apparmor_stress_features, apparmor_stress_kernel_interface, apparmor_stress_corruption, }; /* * stress_apparmor() * stress AppArmor */ int stress_apparmor( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t n = SIZEOF_ARRAY(apparmor_funcs); const size_t counters_sz = n * sizeof(uint64_t); pid_t pids[n]; size_t i; uint64_t *counters, tmp_counter = 0, ops; (void)instance; counters = mmap(NULL, counters_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (counters == MAP_FAILED) { pr_err(stderr, "%s: mmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); exit(EXIT_FAILURE); } memset(counters, 0, counters_sz); if ((max_ops > 0) && (max_ops < n)) ops = n; else ops = max_ops / n; for (i = 0; i < n; i++) { pids[i] = apparmor_spawn(name, ops, &counters[i], apparmor_funcs[i]); } do { (void)select(0, NULL, NULL, NULL, NULL); for (i = 0; i < n; i++) tmp_counter += counters[i]; } while (opt_do_run && (!max_ops || tmp_counter < max_ops)); for (i = 0; i < n; i++) { int status; if (pids[i] >= 0) { (void)kill(pids[i], SIGALRM); (void)waitpid(pids[i], &status, 0); *counter += counters[i]; } } munmap(counters, counters_sz); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-noop.c0000664000175000017500000000262312702231255014714 0ustar kingking/* * Copyright (C) 2013-2016 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.05.23/stress-mknod.c0000664000175000017500000000624712702231255015057 0ustar kingking/* * Copyright (C) 2013-2016 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 const int modes[] = { #if defined(S_IFIFO) S_IFIFO, /* FIFO */ #endif #if defined(S_IFREG) S_IFREG, /* Regular file */ #endif #if defined(S_IFSOCK) S_IFSOCK /* named socket */ #endif }; /* * stress_mknod_tidy() * remove all files */ static void stress_mknod_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)unlink(path); } } /* * stress_mknod * stress mknod creates */ int stress_mknod( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); const size_t num_nodes = SIZEOF_ARRAY(modes); int ret; if (num_nodes == 0) { pr_inf(stderr, "%s: aborting, no valid mknod modes.\n", name); return EXIT_FAILURE; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); do { uint64_t i, n = DEFAULT_DIRS; for (i = 0; i < n; i++) { char path[PATH_MAX]; uint64_t gray_code = (i >> 1) ^ i; int mode = modes[mwc32() % num_nodes]; (void)stress_temp_filename(path, sizeof(path), name, pid, instance, gray_code); if (mknod(path, mode | S_IRUSR | S_IWUSR, 0) < 0) { if ((errno == ENOSPC) || (errno == ENOMEM)) continue; /* Try again */ pr_fail_err(name, "mknod"); n = i; break; } if (!opt_do_run || (max_ops && *counter >= max_ops)) goto abort; (*counter)++; } stress_mknod_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 " nodes\n", name, DEFAULT_DIRS); stress_mknod_tidy(DEFAULT_DIRS, name, pid, instance); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-icache.c0000664000175000017500000000554512702231255015163 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_ICACHE) #if defined(__GNUC__) && NEED_GNUC(4,6,0) #define SECTION(s) __attribute__((__section__(# s))) #define ALIGNED(a) __attribute__((aligned(a))) #endif /* * stress_icache_func() * page aligned in its own section so we can change the * code mapping and make it modifyable to force I-cache * refreshes by modifying the code */ static void SECTION(stress_icache_callee) ALIGNED(4096) stress_icache_func(void) { return; } /* * stress_icache() * stress instruction cache load misses * * I-cache load misses can be observed using: * perf stat -e L1-icache-load-misses stress-ng --icache 0 -t 1 */ int SECTION(stress_icache_caller) stress_icache( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { volatile uint8_t *addr = (uint8_t *)stress_icache_func; (void)instance; if (mprotect((uint8_t *)addr, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { pr_err(stderr, "%s: PROT_WRITE mprotect failed: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } do { register uint8_t val; register int i = 1024; while (--i) { /* * Modifying executable code on x86 will * call a I-cache reload when we execute * the modfied ops. */ val = *addr; *addr ^= ~0; *addr = val; stress_icache_func(); #if defined(__GNUC__) __clear_cache((char *)addr, (char *)addr + 64); #endif } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); if (mprotect((uint8_t *)addr, 4096, PROT_READ | PROT_EXEC) < 0) { pr_err(stderr, "%s: mprotect failed: errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-pipe.c0000664000175000017500000001207512702231255014700 0ustar kingking/* * Copyright (C) 2013-2016 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(F_SETPIPE_SZ) static size_t opt_pipe_size = 0; #endif static size_t opt_pipe_data_size = 512; #define PIPE_STOP "PS!" #if defined(F_SETPIPE_SZ) /* * stress_set_pipe_size() * set pipe size in bytes */ void stress_set_pipe_size(const char *optarg) { opt_pipe_size = (size_t)get_uint64_byte(optarg); check_range("pipe-size", opt_pipe_size, 4, 1024 * 1024); } #endif /* * stress_set_pipe_size() * set pipe data write size in bytes */ void stress_set_pipe_data_size(const char *optarg) { opt_pipe_data_size = (size_t)get_uint64_byte(optarg); check_range("pipe-data_size", opt_pipe_data_size, 4, stress_get_pagesize()); } /* * 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; } #if defined(F_SETPIPE_SZ) /* * pipe_change_size() * see if we can change the pipe size */ static void pipe_change_size(const char *name, const int fd) { if (!opt_pipe_size) return; #if !(defined(__linux__) && NEED_GLIBC(2,9,0)) if (opt_pipe_size < stress_get_pagesize()) return; #endif if (fcntl(fd, F_SETPIPE_SZ, opt_pipe_size) < 0) { pr_err(stderr, "%s: cannot set pipe size, keeping " "default pipe size, errno=%d (%s)\n", name, errno, strerror(errno)); } } #endif /* * 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 defined(__linux__) && NEED_GLIBC(2,9,0) if (pipe2(pipefds, O_DIRECT) < 0) { pr_fail_dbg(name, "pipe2"); return EXIT_FAILURE; } #else if (pipe(pipefds) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } #endif #if defined(F_SETPIPE_SZ) pipe_change_size(name, pipefds[0]); pipe_change_size(name, pipefds[1]); #endif again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; (void)close(pipefds[0]); (void)close(pipefds[1]); pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { int val = 0; setpgid(0, pgrp); stress_parent_died_alarm(); (void)close(pipefds[1]); while (opt_do_run) { char buf[opt_pipe_data_size]; ssize_t n; n = read(pipefds[0], buf, opt_pipe_data_size); if (n <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "read"); break; } pr_fail_dbg(name, "zero byte read"); break; } if (!strcmp(buf, PIPE_STOP)) break; if ((opt_flags & OPT_FLAGS_VERIFY) && pipe_memchk(buf, val++, (size_t)n)) { pr_fail(stderr, "%s: pipe read error detected, " "failed to read expected data\n", name); } } (void)close(pipefds[0]); exit(EXIT_SUCCESS); } else { char buf[opt_pipe_data_size]; int val = 0, status; /* Parent */ setpgid(pid, pgrp); (void)close(pipefds[0]); do { ssize_t ret; pipe_memset(buf, val++, opt_pipe_data_size); ret = write(pipefds[1], buf, opt_pipe_data_size); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "write"); break; } continue; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); strncpy(buf, PIPE_STOP, opt_pipe_data_size); if (write(pipefds[1], buf, sizeof(buf)) <= 0) { if (errno != EPIPE) pr_fail_dbg(name, "termination write"); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); (void)close(pipefds[1]); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-timer.c0000664000175000017500000001100612702231255015054 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_TIMER) #include #include #include #include #include static volatile uint64_t timer_counter = 0; static timer_t timerid; static uint64_t opt_timer_freq = DEFAULT_TIMER_FREQ; static uint64_t overruns = 0; static bool set_timer_freq = false; static double rate_ns; static double start; /* * stress_set_timer_freq() * set timer frequency from given option */ void stress_set_timer_freq(const char *optarg) { set_timer_freq = true; opt_timer_freq = get_uint64(optarg); check_range("timer-freq", opt_timer_freq, MIN_TIMER_FREQ, MAX_TIMER_FREQ); } /* * stress_timer_set() * set timer, ensure it is never zero */ void stress_timer_set(struct itimerspec *timer) { double rate; if (opt_flags & OPT_FLAGS_TIMER_RAND) { /* Mix in some random variation */ double r = ((double)(mwc32() % 10000) - 5000.0) / 40000.0; rate = rate_ns + (rate_ns * r); } else { rate = rate_ns; } timer->it_value.tv_sec = (long long int)rate / 1000000000; timer->it_value.tv_nsec = (long long int)rate % 1000000000; if (timer->it_value.tv_sec == 0 && timer->it_value.tv_nsec < 1) timer->it_value.tv_nsec = 1; timer->it_interval.tv_sec = timer->it_value.tv_sec; timer->it_interval.tv_nsec = timer->it_value.tv_nsec; } /* * stress_timer_handler() * catch timer signal and cancel if no more runs flagged */ static void MLOCKED stress_timer_handler(int sig) { struct itimerspec timer; sigset_t mask; (void)sig; timer_counter++; if (sigpending(&mask) == 0) if (sigismember(&mask, SIGINT)) goto cancel; /* High freq timer, check periodically for timeout */ if ((timer_counter & 65535) == 0) if ((time_now() - start) > (double)opt_timeout) goto cancel; if (opt_do_run) { int ret = timer_getoverrun(timerid); if (ret > 0) overruns += ret; stress_timer_set(&timer); return; } cancel: opt_do_run = false; /* Cancel timer if we detect no more runs */ memset(&timer, 0, sizeof(timer)); (void)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 sigevent sev; struct itimerspec timer; sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigprocmask(SIG_SETMASK, &mask, NULL); start = time_now(); if (!set_timer_freq) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_timer_freq = MAX_TIMER_FREQ; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_timer_freq = MIN_TIMER_FREQ; } rate_ns = opt_timer_freq ? 1000000000 / opt_timer_freq : 1000000000; if (stress_sighandler(name, SIGRTMIN, stress_timer_handler, NULL) < 0) 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_fail_err(name, "timer_create"); return EXIT_FAILURE; } stress_timer_set(&timer); if (timer_settime(timerid, 0, &timer, NULL) < 0) { pr_fail_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_fail_err(name, "timer_delete"); return EXIT_FAILURE; } pr_dbg(stderr, "%s: %" PRIu64 " timer overruns (instance %" PRIu32 ")\n", name, overruns, instance); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-open.c0000664000175000017500000000356212702231255014705 0ustar kingking/* * Copyright (C) 2013-2016 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_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]; const size_t max_fd = stress_get_file_limit(); size_t i; (void)instance; (void)name; do { for (i = 0; i < max_fd; i++) { fds[i] = open("/dev/zero", O_RDONLY); if (fds[i] < 0) break; if (!opt_do_run) break; (*counter)++; } for (i = 0; i < max_fd; 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.05.23/mwc.c0000664000175000017500000000315412702231255013206 0ustar kingking/* * Copyright (C) 2013-2016 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_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)mwc32(); } stress-ng-0.05.23/stress-seek.c0000664000175000017500000001055412702231255014672 0ustar kingking/* * Copyright (C) 2013-2016 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; static bool set_seek_size = false; void stress_set_seek_size(const char *optarg) { set_seek_size = true; 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 len; const pid_t pid = getpid(); int ret, fd, rc = EXIT_FAILURE; char filename[PATH_MAX]; uint8_t buf[512]; #if defined(OPT_SEEK_PUNCH) bool punch_hole = true; #endif if (!set_seek_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_seek_size = MAX_SEEK_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_seek_size = MIN_SEEK_SIZE; } len = opt_seek_size - sizeof(buf); ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); stress_strnrnd((char *)buf, sizeof(buf)); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto finish; } (void)unlink(filename); /* Generate file with hole at the end */ if (lseek(fd, (off_t)len, SEEK_SET) < 0) { rc = exit_status(errno); pr_fail_err(name, "lseek"); goto close_finish; } if (write(fd, buf, sizeof(buf)) < 0) { rc = exit_status(errno); pr_fail_err(name, "write"); goto close_finish; } do { off_t offset; uint8_t tmp[512]; ssize_t ret; offset = mwc64() % len; if (lseek(fd, (off_t)offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek"); goto close_finish; } re_write: if (!opt_do_run) break; ret = write(fd, buf, sizeof(buf)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto re_write; if (errno) { pr_fail_err(name, "write"); goto close_finish; } } offset = mwc64() % len; if (lseek(fd, (off_t)offset, SEEK_SET) < 0) { pr_fail_err(name, "lseek SEEK_SET"); goto close_finish; } re_read: if (!opt_do_run) break; ret = read(fd, tmp, sizeof(tmp)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto re_read; if (errno) { pr_fail_err(name, "read"); goto close_finish; } } if ((ret != sizeof(tmp)) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: incorrect read size, expecting 512 bytes", name); } #if defined(SEEK_HOLE) if (lseek(fd, 0, SEEK_HOLE) < 0) { if (errno != EINVAL) pr_fail_err(name, "lseek SEEK_HOLE"); } #endif #if defined(SEEK_DATA) if (lseek(fd, 0, SEEK_DATA) < 0) { if (errno != EINVAL) pr_fail_err(name, "lseek SEEK_DATA"); } #endif #if defined(OPT_SEEK_PUNCH) if (!punch_hole) continue; offset = mwc64() % len; if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, 8192) < 0) { if (errno == EOPNOTSUPP) punch_hole = false; } #endif (*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.05.23/stress-oom-pipe.c0000664000175000017500000001446512702231255015475 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_OOM_PIPE) #include #include #include #include #include #include #include #include #include #include static int page_size; /* * check_max_pipe_size() * check if the given pipe size is allowed */ static int check_max_pipe_size(const int sz) { int fds[2]; if (sz < page_size) return -1; if (pipe(fds) < 0) return -1; if (fcntl(fds[0], F_SETPIPE_SZ, sz) < 0) return -1; (void)close(fds[0]); (void)close(fds[1]); return 0; } /* * probe_max_pipe_size() * determine the maximim allowed pipe size */ static int probe_max_pipe_size(void) { int i, ret, prev_sz, sz, min, max; char buf[64]; /* * Try and find maximum pipe size directly */ ret = system_read("/proc/sys/fs/pipe-max-size", buf, sizeof(buf)); if (ret > 0) { if (sscanf(buf, "%d", &sz) == 1) if (!check_max_pipe_size(sz)) return sz; } /* * Need to find size by binary chop probing */ min = page_size; max = INT_MAX; prev_sz = 0; for (i = 0; i < 64; i++) { sz = min + (max - min) / 2; if (prev_sz == sz) return sz; prev_sz = sz; if (check_max_pipe_size(sz) == 0) { min = sz; } else { max = sz; } } return sz; } /* * pipe_empty() * read data from read end of pipe */ static void pipe_empty(const int fd, const int max) { int i; for (i = 0; i < max; i += page_size) { ssize_t ret; char buffer[page_size]; ret = read(fd, buffer, sizeof(buffer)); if (ret < 0) return; } } /* * pipe_fill() * write data to fill write end of pipe */ static void pipe_fill(const int fd, const int max) { int i; char buffer[page_size]; memset(buffer, 'X', sizeof(buffer)); for (i = 0; i < max; i += page_size) { ssize_t ret; ret = write(fd, buffer, sizeof(buffer)); if (ret < (ssize_t)sizeof(buffer)) return; } } /* * stress_oom_pipe_expander * */ static int stress_oom_pipe_expander( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const int max_pipe_size, const int max_pipes) { pid_t pid; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_err(stderr, "%s: fork failed: errno=%d (%s)\n", name, errno, strerror(errno)); return -1; } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); stress_parent_died_alarm(); /* Patent, 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(WTERMSIG(status)), instance); /* If we got kill 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) { /* Child */ int fds[max_pipes * 2], *fd, i, pipes_open = 0; const bool aggressive = (opt_flags & OPT_FLAGS_AGGRESSIVE); setpgid(0, pgrp); set_oom_adjustment(name, true); for (i = 0; i < max_pipes * 2; i++) fds[i] = -1; for (i = 0; i < max_pipes; i++) { int *fd = fds + (2 * i); if (pipe(fd) < 0) { fd[0] = -1; fd[1] = -1; } else { if (fcntl(fd[0], F_SETFL, O_NONBLOCK) < 0) { pr_fail(stderr, "%s: fcntl O_NONBLOCK failed, " "errno = %d (%s)\n", name, errno, strerror(errno)); goto clean; } if (fcntl(fd[1], F_SETFL, O_NONBLOCK) < 0) { pr_fail(stderr, "%s: fcntl O_NONBLOCK failed, " "errno = %d (%s)\n", name, errno, strerror(errno)); goto clean; } pipes_open++; } } if (!pipes_open) { pr_dbg(stderr, "%s: failed to open any pipes, aborted\n", name); exit(EXIT_NO_RESOURCE); } do { /* Set to maximum size */ for (i = 0, fd = fds; i < max_pipes * 2; i++, fd++) { int max_size = max_pipe_size; if (*fd < 0) continue; if (fcntl(*fd, F_SETPIPE_SZ, max_size) < 0) max_size = page_size; pipe_fill(fd[1], max_size); if (!aggressive) pipe_empty(fd[0], max_size); } /* Set to minimum size */ for (i = 0, fd = fds; i < max_pipes * 2; i++, fd++) { if (*fd < 0) continue; (void)fcntl(*fd, F_SETPIPE_SZ, page_size); pipe_fill(fd[1], max_pipe_size); if (!aggressive) pipe_empty(fd[0], page_size); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* And close the pipes */ clean: for (i = 0, fd = fds; i < max_pipes * 2; i++, fd++) { if (*fd >= 0) (void)close(*fd); } exit(EXIT_SUCCESS); } return 0; } /* * stress_oom_pipe * stress pipe memory allocation */ int stress_oom_pipe( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t max_fd = stress_get_file_limit(); const size_t max_pipes = max_fd / 2; int max_pipe_size; page_size = stress_get_pagesize(); max_pipe_size = probe_max_pipe_size() & ~(page_size - 1); return stress_oom_pipe_expander( counter, instance, max_ops, name, max_pipe_size, max_pipes); } #endif stress-ng-0.05.23/stress-vm-rw.c0000664000175000017500000002004012702231255015002 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_VM_RW) #include #include #include #include #include #include #include #include #include #include #define STACK_SIZE (64 * 1024) typedef struct { const char *name; uint64_t *counter; uint64_t max_ops; size_t page_size; size_t sz; pid_t pid; int pipe_wr[2]; int pipe_rd[2]; } context_t; 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; static bool set_vm_rw_bytes = false; void stress_set_vm_rw_bytes(const char *optarg) { set_vm_rw_bytes = true; 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); } int stress_vm_child(void *arg) { context_t *ctxt = (context_t *)arg; uint8_t *buf; int ret = EXIT_SUCCESS; addr_msg_t msg_rd, msg_wr; setpgid(0, pgrp); stress_parent_died_alarm(); /* Close unwanted ends */ (void)close(ctxt->pipe_wr[0]); (void)close(ctxt->pipe_rd[1]); buf = mmap(NULL, ctxt->sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (buf == MAP_FAILED) { ret = exit_status(errno); pr_fail_dbg(ctxt->name, "mmap"); goto cleanup; } while (opt_do_run) { uint8_t *ptr, *end = buf + ctxt->sz; int ret; memset(&msg_wr, 0, sizeof(msg_wr)); msg_wr.addr = buf; msg_wr.val = 0; /* Send address of buffer to parent */ redo_wr1: ret = write(ctxt->pipe_wr[1], &msg_wr, sizeof(msg_wr)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_wr1; if (errno != EBADF) pr_fail_dbg(ctxt->name, "write"); break; } redo_rd1: /* Wait for parent to populate data */ ret = read(ctxt->pipe_rd[0], &msg_rd, sizeof(msg_rd)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_rd1; pr_fail_dbg(ctxt->name, "read"); break; } if (ret == 0) break; if (ret != sizeof(msg_rd)) { pr_fail_dbg(ctxt->name, "read"); break; } if (opt_flags & OPT_FLAGS_VERIFY) { /* Check memory altered by parent is sane */ for (ptr = buf; ptr < end; ptr += ctxt->page_size) { if (*ptr != msg_rd.val) { pr_fail(stderr, "%s: memory at %p: %d vs %d\n", ctxt->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(ctxt->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", ctxt->name, errno, strerror(errno)); } (void)close(ctxt->pipe_wr[1]); (void)close(ctxt->pipe_rd[0]); (void)munmap(buf, ctxt->sz); return ret; } int stress_vm_parent(context_t *ctxt) { /* Parent */ int status; uint8_t val = 0; uint8_t *localbuf; addr_msg_t msg_rd, msg_wr; setpgid(ctxt->pid, pgrp); localbuf = mmap(NULL, ctxt->sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (localbuf == MAP_FAILED) { (void)close(ctxt->pipe_wr[0]); (void)close(ctxt->pipe_wr[1]); (void)close(ctxt->pipe_rd[0]); (void)close(ctxt->pipe_rd[1]); pr_fail_dbg(ctxt->name, "mmap"); return EXIT_FAILURE; } /* Close unwanted ends */ (void)close(ctxt->pipe_wr[1]); (void)close(ctxt->pipe_rd[0]); do { struct iovec local[1], remote[1]; uint8_t *ptr, *end = localbuf + ctxt->sz; int ret; /* Wait for address of child's buffer */ redo_rd2: if (!opt_do_run) break; ret = read(ctxt->pipe_wr[0], &msg_rd, sizeof(msg_rd)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_rd2; pr_fail_dbg(ctxt->name, "read"); break; } if (ret == 0) break; if (ret != sizeof(msg_rd)) { pr_fail_dbg(ctxt->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 = ctxt->sz; remote[0].iov_base = msg_rd.addr; remote[0].iov_len = ctxt->sz; if (process_vm_readv(ctxt->pid, local, 1, remote, 1, 0) < 0) { pr_fail_dbg(ctxt->name, "process_vm_readv"); break; } if (opt_flags & OPT_FLAGS_VERIFY) { /* Check data is sane */ for (ptr = localbuf; ptr < end; ptr += ctxt->page_size) { if (*ptr) { pr_fail(stderr, "%s: memory at %p: %d vs %d\n", ctxt->name, ptr, *ptr, msg_rd.val); goto fail; } *ptr = 0; } /* Set memory */ for (ptr = localbuf; ptr < end; ptr += ctxt->page_size) *ptr = val; } /* Write to child's memory */ msg_wr = msg_rd; local[0].iov_base = localbuf; local[0].iov_len = ctxt->sz; remote[0].iov_base = msg_rd.addr; remote[0].iov_len = ctxt->sz; if (process_vm_writev(ctxt->pid, local, 1, remote, 1, 0) < 0) { pr_fail_dbg(ctxt->name, "process_vm_writev"); break; } msg_wr.val = val; val++; redo_wr2: if (!opt_do_run) break; /* Inform child that memory has been changed */ ret = write(ctxt->pipe_rd[1], &msg_wr, sizeof(msg_wr)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo_wr2; if (errno != EBADF) pr_fail_dbg(ctxt->name, "write"); break; } (*ctxt->counter)++; } while (opt_do_run && (!ctxt->max_ops || *ctxt->counter < ctxt->max_ops)); fail: /* Tell child we're done */ msg_wr.addr = NULL; msg_wr.val = 0; if (write(ctxt->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", ctxt->name, errno, strerror(errno)); } (void)close(ctxt->pipe_wr[0]); (void)close(ctxt->pipe_rd[1]); (void)kill(ctxt->pid, SIGKILL); (void)waitpid(ctxt->pid, &status, 0); (void)munmap(localbuf, ctxt->sz); return EXIT_SUCCESS; } /* * 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) { context_t ctxt; uint8_t stack[64*1024]; const ssize_t stack_offset = stress_get_stack_direction(&ctxt) * (STACK_SIZE - 64); uint8_t *stack_top = stack + stack_offset; (void)instance; if (!set_vm_rw_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_vm_rw_bytes = MAX_VM_RW_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_vm_rw_bytes = MIN_VM_RW_BYTES; } ctxt.name = name; ctxt.page_size = stress_get_pagesize(); ctxt.sz = opt_vm_rw_bytes & ~(ctxt.page_size - 1); ctxt.counter = counter; ctxt.max_ops = max_ops; if (pipe(ctxt.pipe_wr) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } if (pipe(ctxt.pipe_rd) < 0) { (void)close(ctxt.pipe_wr[0]); (void)close(ctxt.pipe_wr[1]); pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } ctxt.pid = clone(stress_vm_child, stack_top, SIGCHLD | CLONE_VM, &ctxt); if (ctxt.pid < 0) { (void)close(ctxt.pipe_wr[0]); (void)close(ctxt.pipe_wr[1]); (void)close(ctxt.pipe_rd[0]); (void)close(ctxt.pipe_rd[1]); pr_fail_dbg(name, "clone"); return EXIT_FAILURE; } return stress_vm_parent(&ctxt); } #endif stress-ng-0.05.23/test-libbsd.c0000664000175000017500000000255412702231255014637 0ustar kingking/* * Copyright (C) 2016 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. * */ #include #include static int intcmp(const void *p1, const void *p2) { int *i1 = (int *)p1; int *i2 = (int *)p2; return *i1 - *i2; } int main(void) { int data[64]; memset(data, 0, sizeof(data)); heapsort(data, 64, sizeof(int), intcmp); mergesort(data, 64, sizeof(int), intcmp); return 0; } stress-ng-0.05.23/stress-cache.c0000664000175000017500000001074412702231255015007 0ustar kingking/* * Copyright (C) 2013-2016 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++) { \ if ((flag) & OPT_FLAGS_CACHE_PREFETCH) { \ __builtin_prefetch(&mem_cache[i + 1], 1, 1); \ } \ 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) { #if defined(__linux__) cpu_set_t mask; uint32_t cpu = 0; const uint32_t cpus = stress_get_processors_configured(); int pinned = false; #endif uint32_t total = 0; int ret = EXIT_SUCCESS; uint8_t *const mem_cache = shared->mem_cache; const uint64_t mem_cache_size = shared->mem_cache_size; if (instance == 0) pr_dbg(stderr, "%s: using cache buffer size of %" PRIu64 "K\n", name, mem_cache_size / 1024); do { uint64_t i = mwc64() % mem_cache_size; uint64_t r = mwc64(); register uint64_t 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; case OPT_FLAGS_CACHE_PREFETCH: CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH); break; case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FLUSH: CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FLUSH); break; case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FENCE: CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FENCE); break; case OPT_FLAGS_CACHE_PREFETCH | OPT_FLAGS_CACHE_FLUSH | OPT_FLAGS_CACHE_FENCE: CACHE_WRITE(OPT_FLAGS_CACHE_PREFETCH | 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; if (!opt_do_run) break; } } #if defined(__linux__) if ((opt_flags & OPT_FLAGS_CACHE_NOAFF) && !pinned) { int current; /* Pin to the current CPU */ current = sched_getcpu(); if (current < 0) return EXIT_FAILURE; cpu = (int32_t)current; } else { cpu = (opt_flags & OPT_FLAGS_AFFINITY_RAND) ? (mwc32() >> 4) : cpu + 1; cpu %= cpus; } if (!(opt_flags & OPT_FLAGS_CACHE_NOAFF) || !pinned) { CPU_ZERO(&mask); CPU_SET(cpu, &mask); sched_setaffinity(0, sizeof(mask), &mask); if ((opt_flags & OPT_FLAGS_CACHE_NOAFF)) { /* Don't continually set the affinity */ pinned = true; } } #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_dbg(stderr, "%s: total [%" PRIu32 "]\n", name, total); return ret; } stress-ng-0.05.23/stress-udp-flood.c0000664000175000017500000000533312702231255015633 0ustar kingking/* * Copyright (C) 2013-2016 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" #if defined(STRESS_UDP_FLOOD) static int opt_udp_flood_domain = AF_INET; /* * stress_set_udp_domain() * set the udp domain option */ int stress_set_udp_flood_domain(const char *name) { return stress_set_net_domain(DOMAIN_INET_ALL, "udp-flood-domain", name, &opt_udp_flood_domain); } /* * stress_udp_flood * UDP flood */ int stress_udp_flood( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd, rc = EXIT_SUCCESS, j = 0; pid_t pid = getpid(); int port = 1024; struct sockaddr *addr; socklen_t addr_len; const size_t sz_max = 23 + instance; size_t sz = 1; static const char data[64] = "0123456789ABCDEFGHIJKLMNOPQRSTUV" "WXYZabcdefghijklmnopqrstuvwxyz@!"; if ((fd = socket(opt_udp_flood_domain, SOCK_DGRAM, AF_PACKET)) < 0) { pr_fail_dbg(name, "socket"); return EXIT_FAILURE; } stress_set_sockaddr(name, instance, pid, opt_udp_flood_domain, port, &addr, &addr_len); do { char buf[sz]; stress_set_sockaddr_port(opt_udp_flood_domain, port, addr); memset(buf, data[j++ & 63], sz); if (sendto(fd, buf, sz, 0, addr, addr_len) > 0) (*counter)++; if (++port > 65535) port = 1024; if (++sz > sz_max) sz = 1; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); return rc; } #endif stress-ng-0.05.23/stress-sysfs.c0000664000175000017500000001237012702231255015110 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SYSFS) #include #include #include #include #include #include #include #include #include #include #define SYS_BUF_SZ (4096) #define MAX_READ_THREADS (4) static volatile bool keep_running; static sigset_t set; typedef struct ctxt { const char *name; const char *path; } ctxt_t; /* * stress_sys_read() * read a proc file */ static inline void stress_sys_read(const char *name, const char *path) { int fd; ssize_t i = 0; char buffer[SYS_BUF_SZ]; if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) return; /* * Multiple randomly sized reads */ while (i < (4096 * SYS_BUF_SZ)) { ssize_t ret, sz = 1 + (mwc32() % sizeof(buffer)); redo: if (!opt_do_run) break; ret = read(fd, buffer, sz); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; break; } if (ret < sz) break; i += sz; } (void)close(fd); /* file should be R_OK if we've just opened it */ if ((access(path, R_OK) < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: R_OK access failed on %s which " "could be opened, errno=%d (%s)\n", name, path, errno, strerror(errno)); } } /* * stress_sys_read_thread * keep exercising a sysfs entry until * controlling thread triggers an exit */ static void *stress_sys_read_thread(void *ctxt_ptr) { static void *nowt = NULL; uint8_t stack[SIGSTKSZ]; stack_t ss; ctxt_t *ctxt = (ctxt_t *)ctxt_ptr; /* * 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 totally unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_fail_err("pthread", "sigaltstack"); return &nowt; } while (keep_running && opt_do_run) stress_sys_read(ctxt->name, ctxt->path); return &nowt; } /* * stress_proc_sys_threads() * create a bunch of threads to thrash read a sys entry */ static void stress_sys_read_threads(const char *name, const char *path) { size_t i; pthread_t pthreads[MAX_READ_THREADS]; int ret[MAX_READ_THREADS]; ctxt_t ctxt; ctxt.name = name; ctxt.path = path; memset(ret, 0, sizeof(ret)); keep_running = true; for (i = 0; i < MAX_READ_THREADS; i++) { ret[i] = pthread_create(&pthreads[i], NULL, stress_sys_read_thread, &ctxt); } for (i = 0; i < 8; i++) { if (!opt_do_run) break; stress_sys_read(name, path); } keep_running = false; for (i = 0; i < MAX_READ_THREADS; i++) { if (ret[i] == 0) pthread_join(pthreads[i], NULL); } } /* * stress_sys_dir() * read directory */ static void stress_sys_dir( const char *name, const char *path, const bool recurse, const int depth, bool sys_read) { DIR *dp; struct dirent *d; if (!opt_do_run) return; /* Don't want to go too deep */ if (depth > 20) return; dp = opendir(path); if (dp == NULL) return; while ((d = readdir(dp)) != NULL) { char filename[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(filename, sizeof(filename), "%s/%s", path, d->d_name); stress_sys_dir(name, filename, recurse, depth + 1, sys_read); } break; case DT_REG: if (sys_read) { snprintf(filename, sizeof(filename), "%s/%s", path, d->d_name); stress_sys_read_threads(name, filename); } break; default: break; } } (void)closedir(dp); } /* * stress_sysfs * stress reading all of /sys */ int stress_sysfs( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { bool sys_read = true; (void)instance; if (geteuid() == 0) { pr_inf(stderr, "%s: running as root, just traversing /sys " "and not reading files.\n", name); sys_read = false; } do { stress_sys_dir(name, "/sys", true, 0, sys_read); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-affinity.c0000664000175000017500000000467012702231255015556 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_AFFINITY) #include #include #include #include #include /* * 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) { uint32_t cpu = instance; const uint32_t cpus = stress_get_processors_configured(); cpu_set_t mask; do { cpu = (opt_flags & OPT_FLAGS_AFFINITY_RAND) ? (mwc32() >> 4) : cpu + 1; cpu %= cpus; CPU_ZERO(&mask); CPU_SET(cpu, &mask); if (sched_setaffinity(0, sizeof(mask), &mask) < 0) { if (errno == EINVAL) { /* * We get this if CPU is offline'd, * and since that can be dynamically * set, we should just retry */ continue; } pr_fail(stderr, "%s: failed to move to CPU %" PRIu32 ", errno=%d (%s)\n", name, cpu, errno, strerror(errno)); #if defined(_POSIX_PRIORITY_SCHEDULING) sched_yield(); #endif } 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, "%s: failed to move to CPU %" PRIu32 "\n", name, cpu); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-utime.c0000664000175000017500000000551112702231255015063 0ustar kingking/* * Copyright (C) 2013-2016 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_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 ret, fd; const pid_t pid = getpid(); ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); if ((fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { ret = exit_status(errno); pr_err(stderr, "%s: open failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, instance); return ret; } do { struct timeval times[2], *t; if (gettimeofday(×[0], NULL) < 0) { t = NULL; } else { times[1] = times[0]; t = times; } if (utimes(filename, t) < 0) { pr_dbg(stderr, "%s: utimes failed: errno=%d: (%s)\n", name, errno, strerror(errno)); break; } #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.05.23/sched.c0000664000175000017500000001125512702231255013507 0ustar kingking/* * Copyright (C) 2013-2016 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__) /* * get_sched_name() * convert sched class to human readable string */ static const char *get_sched_name(const int32_t sched) { switch (sched) { #if defined(SCHED_IDLE) case SCHED_IDLE: return "idle"; #endif #if defined(SCHED_FIFO) case SCHED_FIFO: return "fifo"; #endif #if defined(SCHED_RR) case SCHED_RR: return "rr"; #endif #if defined(SCHED_OTHER) case SCHED_OTHER: return "other"; #endif #if defined(SCHED_BATCH) case SCHED_BATCH: return "batch"; #endif #if defined(SCHED_DEADLINE) case SCHED_DEADLINE: return "deadline"; #endif default: return "unknown"; } } #endif #if (defined(_POSIX_PRIORITY_SCHEDULING) || defined(__linux__)) && \ !defined(__OpenBSD__) /* * set_sched() * are sched settings valid, if so, set them */ void set_sched(const int32_t sched, const int32_t sched_priority) { #if defined(SCHED_FIFO) || defined(SCHED_RR) int min, max; #endif int rc; struct sched_param param; const char *name = get_sched_name(sched); memset(¶m, 0, sizeof(param)); switch (sched) { case UNDEFINED: /* No preference, don't set */ return; #if defined(SCHED_FIFO) || defined(SCHED_RR) #if defined(SCHED_FIFO) case SCHED_FIFO: #endif #if defined(SCHED_RR) case SCHED_RR: #endif min = sched_get_priority_min(sched); max = sched_get_priority_max(sched); param.sched_priority = sched_priority; if (param.sched_priority == UNDEFINED) { if (opt_flags & OPT_FLAGS_AGGRESSIVE) param.sched_priority = max; else param.sched_priority = (max - min) / 2; pr_inf(stderr, "priority not given, defaulting to %d\n", param.sched_priority); } if ((param.sched_priority < min) || (param.sched_priority > max)) { fprintf(stderr, "Scheduler priority level must be " "set between %d and %d\n", min, max); exit(EXIT_FAILURE); } pr_dbg(stderr, "setting scheduler class '%s', priority %d\n", name, param.sched_priority); break; #endif default: param.sched_priority = 0; if (sched_priority != UNDEFINED) pr_inf(stderr, "ignoring priority level for " "scheduler class '%s'\n", name); pr_dbg(stderr, "setting scheduler class '%s'\n", name); break; } rc = sched_setscheduler(getpid(), sched, ¶m); if (rc < 0) { fprintf(stderr, "Cannot set scheduler: errno=%d (%s)\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } #else void set_sched(const int32_t sched, const int32_t sched_priority) { (void)sched; (void)sched_priority; } #endif /* * get_opt_sched() * get scheduler policy */ int32_t 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 #ifdef SCHED_DEADLINE if (!strcmp("deadline", str)) return SCHED_DEADLINE; #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_DEADLINE " deadline" #endif #ifdef SCHED_IDLE " idle" #endif #ifdef SCHED_FIFO " fifo" #endif #ifdef SCHED_FIFO " rr" #endif "\n"); exit(EXIT_FAILURE); } stress-ng-0.05.23/thermal-zone.c0000664000175000017500000001143712702231255015030 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_THERMAL_ZONES) /* * tz_init() * gather all thermal zones */ int tz_init(tz_info_t **tz_info_list) { DIR *dir; struct dirent *entry; size_t i = 0; dir = opendir("/sys/class/thermal"); if (!dir) return 0; while ((entry = readdir(dir)) != NULL) { char path[PATH_MAX]; FILE *fp; tz_info_t *tz_info; /* Ignore non TZ interfaces */ if (strncmp(entry->d_name, "thermal_zone", 12)) continue; /* Ensure we don't overstep the max limit of TZs */ if (i >= STRESS_THERMAL_ZONES_MAX) break; if ((tz_info = calloc(1, sizeof(*tz_info))) == NULL) { pr_err(stderr, "Cannot allocate thermal information.\n"); closedir(dir); return -1; } snprintf(path, sizeof(path), "/sys/class/thermal/%s/type", entry->d_name); tz_info->path = strdup(entry->d_name); if (!tz_info->path) { free(tz_info); closedir(dir); return -1; } tz_info->type = NULL; if ((fp = fopen(path, "r")) != NULL) { char type[128]; if (fgets(type, sizeof(type), fp) != NULL) { type[strcspn(type, "\n")] = '\0'; tz_info->type = strdup(type); } (void)fclose(fp); } if (!tz_info->type) { free(tz_info->path); free(tz_info); closedir(dir); return -1; } tz_info->index = i++; tz_info->next = *tz_info_list; *tz_info_list = tz_info; } closedir(dir); return 0; } /* * tz_free() * free thermal zones */ void tz_free(tz_info_t **tz_info_list) { tz_info_t *tz_info = *tz_info_list; while (tz_info) { tz_info_t *next = tz_info->next; free(tz_info->path); free(tz_info->type); free(tz_info); tz_info = next; } } /* * tz_get_temperatures() * collect valid thermal_zones details */ int tz_get_temperatures(tz_info_t **tz_info_list, stress_tz_t *tz) { tz_info_t *tz_info; for (tz_info = *tz_info_list; tz_info; tz_info = tz_info->next) { char path[PATH_MAX]; FILE *fp; size_t i = tz_info->index; snprintf(path, sizeof(path), "/sys/class/thermal/%s/temp", tz_info->path); tz->tz_stat[i].temperature = 0; if ((fp = fopen(path, "r")) != NULL) { if (fscanf(fp, "%" SCNu64, &tz->tz_stat[i].temperature) != 1) { tz->tz_stat[i].temperature = 0; } fclose(fp); } } return 0; } /* * tz_dump() * dump thermal zone temperatures */ void tz_dump( FILE *yaml, const shared_t *shared, const stress_t stressors[], const proc_info_t procs[STRESS_MAX], const int32_t max_procs) { uint32_t i; bool no_tz_stats = true; pr_yaml(yaml, "thermal-zones:\n"); for (i = 0; i < STRESS_MAX; i++) { tz_info_t *tz_info; int32_t j; uint64_t total = 0; uint32_t count = 0; bool dumped_heading = false; for (tz_info = shared->tz_info; tz_info; tz_info = tz_info->next) { for (j = 0; j < procs[i].started_procs; j++) { uint64_t temp; int32_t n = (i * max_procs) + j; temp = shared->stats[n].tz.tz_stat[tz_info->index].temperature; /* Avoid crazy temperatures. e.g. > 250 C */ if (temp > 250000) temp = 0; total += temp; count++; } if (total) { double temp = ((double)total / count) / 1000.0; char *munged = munge_underscore((char *)stressors[i].name); if (!dumped_heading) { dumped_heading = true; pr_inf(stdout, "%s:\n", munged); pr_yaml(yaml, " - stressor: %s\n", munged); } pr_inf(stdout, "%20s %7.2f °C\n", tz_info->type, temp); pr_yaml(yaml, " %s: %7.2f\n", tz_info->type, temp); no_tz_stats = false; } } if (total) pr_yaml(yaml, "\n"); } if (no_tz_stats) pr_inf(stdout, "thermal zone temperatures not available\n"); } #endif stress-ng-0.05.23/stress-dir.c0000664000175000017500000000536512702231255014525 0ustar kingking/* * Copyright (C) 2013-2016 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(); int ret; ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); 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) { if ((errno != ENOSPC) && (errno != ENOMEM)) { pr_fail_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 ret; } stress-ng-0.05.23/stress-socket.c0000664000175000017500000002272412702231255015235 0ustar kingking/* * Copyright (C) 2013-2016 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__) #define SOCKET_NODELAY #endif #include #include #include #include #include #include #include #include #if defined(SOCKET_NODELAY) #include #endif #include #include #include #include #include #ifdef AF_INET6 #include #endif #ifdef AF_UNIX #include #endif #if defined(__linux__) #include #endif #include "stress-ng.h" #if defined(__linux__) && defined(__NR_sendmmsg) && NEED_GLIBC(2,14,0) #define HAVE_SENDMMSG #endif #define SOCKET_OPT_SEND 0x01 #define SOCKET_OPT_SENDMSG 0x02 #define SOCKET_OPT_SENDMMSG 0x03 #define MSGVEC_SIZE (4) typedef struct { const char *optname; int opt; } socket_opts_t; static int opt_socket_domain = AF_INET; static int opt_socket_port = DEFAULT_SOCKET_PORT; static int opt_socket_opts = SOCKET_OPT_SEND; static const socket_opts_t socket_opts[] = { { "send", SOCKET_OPT_SEND }, { "sendmsg", SOCKET_OPT_SENDMSG }, #if defined(HAVE_SENDMMSG) { "sendmmsg", SOCKET_OPT_SENDMMSG }, #endif { NULL, 0 } }; /* * stress_set_socket_opts() * parse --send-opts */ int stress_set_socket_opts(const char *optarg) { int i; for (i = 0; socket_opts[i].optname; i++) { if (!strcmp(optarg, socket_opts[i].optname)) { opt_socket_opts = socket_opts[i].opt; return 0; } } fprintf(stderr, "sock-opts option '%s' not known, options are:", optarg); for (i = 0; socket_opts[i].opt; i++) { fprintf(stderr, "%s %s", i == 0 ? "" : ",", socket_opts[i].optname); } fprintf(stderr, "\n"); return -1; } /* * stress_set_socket_port() * set port to use */ 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(DOMAIN_ALL, "sock-domain", name, &opt_socket_domain); } /* * stress_socket_client() * client reader */ static void stress_socket_client( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid) { struct sockaddr *addr; setpgid(0, pgrp); stress_parent_died_alarm(); do { char buf[SOCKET_BUF]; int fd; int retries = 0; socklen_t addr_len = 0; retry: if (!opt_do_run) { (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { pr_fail_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_fail_dbg(name, "connect"); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } goto retry; } do { ssize_t n = recv(fd, buf, sizeof(buf), 0); if (n == 0) break; if (n < 0) { if (errno != EINTR) pr_fail_dbg(name, "recv"); break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)shutdown(fd, SHUT_RDWR); (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); } /* * handle_socket_sigalrm() * catch SIGALRM * stress_socket_client() * client reader */ static void MLOCKED handle_socket_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_socket_server() * server writer */ static int stress_socket_server( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t pid, const pid_t ppid) { char buf[SOCKET_BUF]; int fd, status; int so_reuseaddr = 1; socklen_t addr_len = 0; struct sockaddr *addr; uint64_t msgs = 0; int rc = EXIT_SUCCESS; setpgid(pid, pgrp); if (stress_sighandler(name, SIGALRM, handle_socket_sigalrm, NULL) < 0) { rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { rc = exit_status(errno); pr_fail_dbg(name, "socket"); goto die; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_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) { rc = exit_status(errno); pr_fail_dbg(name, "bind"); goto die_close; } if (listen(fd, 10) < 0) { pr_fail_dbg(name, "listen"); rc = EXIT_FAILURE; goto die_close; } do { int sfd = accept(fd, (struct sockaddr *)NULL, NULL); if (sfd >= 0) { size_t i, j; struct sockaddr addr; socklen_t len; int sndbuf; struct msghdr msg; struct iovec vec[sizeof(buf)/16]; #if defined(HAVE_SENDMMSG) struct mmsghdr msgvec[MSGVEC_SIZE]; unsigned int msg_len = 0; #endif #if defined(SOCKET_NODELAY) int one = 1; #endif len = sizeof(addr); if (getsockname(fd, &addr, &len) < 0) { pr_fail_dbg(name, "getsockname"); (void)close(sfd); break; } len = sizeof(sndbuf); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) { pr_fail_dbg(name, "getsockopt"); (void)close(sfd); break; } #if defined(SOCKET_NODELAY) if (opt_flags & OPT_FLAGS_SOCKET_NODELAY) { if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) { pr_inf(stderr, "%s: setsockopt TCP_NODELAY " "failed and disabled, errno=%d (%s)\n", name, errno, strerror(errno)); opt_flags &= ~OPT_FLAGS_SOCKET_NODELAY; } } #endif memset(buf, 'A' + (*counter % 26), sizeof(buf)); switch (opt_socket_opts) { case SOCKET_OPT_SEND: for (i = 16; i < sizeof(buf); i += 16) { ssize_t ret = send(sfd, buf, i, 0); if (ret < 0) { if (errno != EINTR) pr_fail_dbg(name, "send"); break; } else msgs++; } break; case SOCKET_OPT_SENDMSG: for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; } memset(&msg, 0, sizeof(msg)); msg.msg_iov = vec; msg.msg_iovlen = j; if (sendmsg(sfd, &msg, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmsg"); } else msgs += j; break; #if defined(HAVE_SENDMMSG) case SOCKET_OPT_SENDMMSG: memset(msgvec, 0, sizeof(msgvec)); for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; msg_len += i; } for (i = 0; i < MSGVEC_SIZE; i++) { msgvec[i].msg_hdr.msg_iov = vec; msgvec[i].msg_hdr.msg_iovlen = j; } if (sendmmsg(sfd, msgvec, MSGVEC_SIZE, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmmsg"); } else msgs += (MSGVEC_SIZE * j); break; #endif default: /* Should never happen */ pr_err(stderr, "%s: bad option %d\n", name, opt_socket_opts); (void)close(sfd); goto die_close; } if (getpeername(sfd, &addr, &len) < 0) { pr_fail_dbg(name, "getpeername"); } (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); } pr_dbg(stderr, "%s: %" PRIu64 " messages sent\n", name, msgs); return rc; } /* * 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(); pr_dbg(stderr, "%s: process [%d] using socket port %d\n", name, getpid(), opt_socket_port + instance); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { stress_socket_client(counter, instance, max_ops, name, ppid); exit(EXIT_SUCCESS); } else { return stress_socket_server(counter, instance, max_ops, name, pid, ppid); } } stress-ng-0.05.23/syscalls.txt0000664000175000017500000001453712702231255014661 0ustar kingkingSyscall Stressor accept sock accept4 access sysfs acct [ need privilege, ignore for now ] add_key key adjtimex get (modes = 0 only) alarm generic run duration timers bind sock brk bigheap, brk capget cap capset [ need privilege, ignore for now ] chdir chdir chmod chmod chown chroot clock_adjtime clock_getres clock clock_gettime clock clock_nanosleep clock clock_settime [ need privilege, ignore for now ] clone clone close dentry connect sock creat chmod dup dup dup2 dup dup3 endmntent sysinfo epoll_create epoll_create1 epoll epoll_ctl epoll epoll_ctl_add epoll epoll_pwait epoll_wait epoll eventfd eventfd eventfd2 execve exec exit fork exit_group faccessat fadvise readahead fallocate fallocate fanotify_init [ need privilege, ignore for now ] fanotify_mark [ need privilege, ignore for now ] fchdir fchmod chmod fchmodat fchown fchownat fcntl open, lockf, fcntl fdatasync hdd fgetxattr xattr finit_module flistxattr xattr flock flock fork fork fremovexattr xattr fsetxattr xattr fstat fallocate fstatfs sysinfo fsync fallocate, hdd ftruncate fallocate futex futex futimesat futimens wait get_mempolicy numa get_robust_list pthread get_thread_area getcpu numa getcwd get getdents getdent getegid get geteuid get getgid get getgroups get getitimer itimer getmntent sysinfo getpeername sock getpagesize [ legacy ] getpgid get getpgrp get getpid get getppid get getpriority get getrandom getrandom getpwd get getresgid get getresuid get getrlimit get getrlimit nice getrusage get getsid get getsockname sock getsockopt sock gettid get gettimeofday get getuid get getxattr init_module inotify_add_watch inotify inotify_init inotify inotify_rm_watch inotify io_cancel io_destroy aiol io_getevents aiol io_setup aiol io_submit aiol ioctl [ need privilege, ignore for now ] ioperm ditto iopl ditto ioprio_get ioprio_set ipc used by msg* glibc wrappers kcmp kcmp kexec_file_load [ need privilege, ignore for now ] kexec_load [ need privilege, ignore for now ] keyctl key kill kill lchown lgetxattr link link linkat listen sock listxattr llistxattr lookup_dcookie lremovexattr lseek hdd, lockf, mmap, seek lsetxattr lstat fstat madvise mmap, vm mbind numa membarrier membarrier memfd_create memfd migrate_pages numa mincore bigheap, mincore, mmap, vm mkdir dir mkdirat mknod mknod mknodat mlock mlock mlock2 mlock mlockall mlock mkstemp hdd mount [ need privilege, ignore for now ] move_pages numa mmap bigheap, mmap mmap2 mprotect mmap mq_getsetattr mq mq_notify mq_open mq mq_send mq mq_timedreceive mq mq_timedsend mq_unlink mq mq_receive mq mq_close mq mremap mremap msgctl msg msgget msg msgrcv msg msgsnd msg msync mmap munlock mlock munlockall mlock munmap mmap, mremap name_to_handle_at handle nanosleep timer nice nice open dentry, open, etc open_by_handle_at handle openat io pause kcmp perf_event_open --perf option personality personality pipe pipe, switch, etc pipe2 pivot_root [ need privilege, ignore for now ] poll poll posix_fallocate fallocate ppoll prctl process name setting pread readahead preadv prlimit get /proc proc process_vm_readv vm_rw process_vm_writev vm_rw pselect6 ptrace ptrace pwrite readahead, aio pwritev quotactl quota read pipe, zero, .. readahead readahead readdir fstat, inotitfy, proc readlink symlink readlinkat readv hdd reboot [ need privilege, ignore for now ] recv sock recvfrom recvmsg recvmmsg remap_file_pages remap removexattr rename rename renameat request_key restart_syscall [ ignore this ] rmdir dir rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo sched_get_priority_max sched sched_get_priority_min sched sched_getaffinity affinity sched_getattr sched_getparam sched_getscheduler sched_get_rr_interval sched_setaffinity affinity sched_setattr sched_setparam sched_setscheduler sched sched_yield yield seccomp seccomp (prctl) select poll semctl sem-sysv semget sem-sysv semop sem-sysv semtimedop sem_destroy sem sem_init sem sem_post sem sem_wait sem send sock sendfile sendfile sendmmsg sock sendmsg sock sendto set_mempolicy numa set_robust_list set_thread_area set_tid_address setdomainname [ need privilege, ignore for now ] setfsgid setfssuid setgid setgroups sethostname setitimer itimer setmntent sysinfo setns setpgid setpriority nice setregid setresgid setresuid setreuid setrlimit limit, rlimit setsid setsockopt sock settimeofday [ need privilege, ignore for now ] setuid setxattr sgetmask [obsolete] shmat shm-sysv shmctl shm-sysv shmdt shm-sysv shmget shm-sysv shutdown sock, sockpair sigaction sigfpe sigaltstack pthread, stack signal [ Avoid its use: use sigaction(2) instead ] signalfd sigfd sigpending sigpending sigprocmask pthread, sigfd sigreturn [ ignore ] siglongjmp sigfpe sigqueue sigq sigsetjmp sigfpe sigwaitinfo sigfpe sigsuspend sigsuspend socket sock socketcall [ implicit ] socketpair sockpair splice splice ssetmask [ obsolete ] stat fstat statfs sysinfo stime [ need privilege, ignore for now ] swapoff [ need privilege, ignore for now ] swapon [ need privilege, ignore for now ] symlink symlink symlinkat sync io sync_file_range sync-file sync_file_range2 [ potentially dangerous to data ] syncfs hdd, io sysfs [ obsolete ] sysinfo sysinfo syslog klog tee tee tgkill time get timer_create clock, timer timer_delete clock, timer timer_getoverrun timer timer_gettime clock timer_settime timer timerfd_create timerfd timerfd_gettime timerfd timerfd_settime timerfd times sysinfo tkill truncate ugetrlimit umask aio, mmap, sendfile, etc umount [ need privilege, ignore for now ] uname get unlink dentry, hdd, unlink unlinkat unshare clone, unshare userfaultfd userfaultfd ustat [ deprecated ] utime utime utimesat utimes utime vfork vfork vhangup [ ignore ] vmsplice vm-splice wait various wait3 [ obsolete ] wait4 [ obsolete ] waitid wait waitpid fork, wait, etc write hdd, null, pull writev hdd stress-ng-0.05.23/stress-unshare.c0000664000175000017500000000654312702231255015413 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_UNSHARE) #include #include #include #include #include #include #define MAX_PIDS (32) #define UNSHARE(flags) \ sys_unshare(name, flags, #flags); /* * unshare with some error checking */ void sys_unshare(const char *name, int flags, const char *flags_name) { int rc; #if NEED_GLIBC(2,14,0) rc = unshare(flags); #else rc = syscall(__NR_unshare, flags); #endif if ((rc < 0) && (errno != EPERM) && (errno != EINVAL)) { pr_fail(stderr, "%s: unshare(%s) failed, " "errno=%d (%s)\n", name, flags_name, errno, strerror(errno)); } } /* * stress_unshare() * stress resource unsharing */ int stress_unshare( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_PIDS]; (void)instance; do { size_t i, n; memset(pids, 0, sizeof(pids)); for (n = 0; n < MAX_PIDS; n++) { retry: if (!opt_do_run) goto reap; pids[n] = fork(); if (pids[n] < 0) { /* Out of resources for fork, re-do, ugh */ if (errno == EAGAIN) { usleep(10000); goto retry; } break; } if (pids[n] == 0) { /* Child */ setpgid(0, pgrp); stress_parent_died_alarm(); #if defined(CLONE_FS) UNSHARE(CLONE_FS); #endif #if defined(CLONE_FILES) UNSHARE(CLONE_FILES); #endif #if defined(CLONE_NEWIPC) UNSHARE(CLONE_NEWIPC); #endif #if defined(CLONE_NEWNET) UNSHARE(CLONE_NEWNET); #endif #if defined(CLONE_NEWNS) UNSHARE(CLONE_NEWNS); #endif #if defined(CLONE_NEWPID) UNSHARE(CLONE_NEWPID); #endif #if defined(CLONE_NEWUSER) UNSHARE(CLONE_NEWUSER); #endif #if defined(CLONE_NEWUTS) UNSHARE(CLONE_NEWUTS); #endif #if defined(CLONE_SYSVSEM) UNSHARE(CLONE_SYSVSEM); #endif #if defined(CLONE_THREAD) UNSHARE(CLONE_THREAD); #endif #if defined(CLONE_SIGHAND) UNSHARE(CLONE_SIGHAND); #endif #if defined(CLONE_VM) UNSHARE(CLONE_VM); #endif _exit(0); } setpgid(pids[n], pgrp); } reap: for (i = 0; i < n; i++) { int status; if (waitpid(pids[i], &status, 0) < 0) { if (errno != EINTR) pr_err(stderr, "%s: waitpid errno=%d (%s)\n", name, errno, strerror(errno)); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-context.c0000664000175000017500000000640112702231255015423 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_CONTEXT) #include #include #include #include #include #define STACK_SIZE (16384) static ucontext_t uctx_main, uctx_thread1, uctx_thread2, uctx_thread3; static uint64_t __counter, __max_ops; static void thread1(void) { do { __counter++; swapcontext(&uctx_thread1, &uctx_thread2); } while (opt_do_run && (!__max_ops || __counter < __max_ops)); } static void thread2(void) { do { __counter++; swapcontext(&uctx_thread2, &uctx_thread3); } while (opt_do_run && (!__max_ops || __counter < __max_ops)); } static void thread3(void) { do { __counter++; swapcontext(&uctx_thread3, &uctx_thread1); } while (opt_do_run && (!__max_ops || __counter < __max_ops)); } static int stress_context_init( const char *name, void (*func)(void), ucontext_t *link, ucontext_t *uctx, void *stack, const size_t stack_size) { if (getcontext(uctx) < 0) { pr_err(stderr, "%s: getcontext failed: %d (%s)\n", name, errno, strerror(errno)); return -1; } uctx->uc_stack.ss_sp = stack; uctx->uc_stack.ss_size = stack_size; uctx->uc_link = link; makecontext(uctx, func, 0); return 0; } /* * stress_context() * stress that exercises CPU context save/restore */ int stress_context( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { char stack_thread1[STACK_SIZE], stack_thread2[STACK_SIZE], stack_thread3[STACK_SIZE]; (void)instance; __counter = 0; __max_ops = max_ops * 1000; /* Create 3 micro threads */ if (stress_context_init(name, thread1, &uctx_main, &uctx_thread1, stack_thread1, sizeof(stack_thread1)) < 0) return EXIT_FAILURE; if (stress_context_init(name, thread2, &uctx_main, &uctx_thread2, stack_thread2, sizeof(stack_thread2)) < 0) return EXIT_FAILURE; if (stress_context_init(name, thread3, &uctx_main, &uctx_thread3, stack_thread3, sizeof(stack_thread3)) < 0) return EXIT_FAILURE; /* And start.. */ if (swapcontext(&uctx_main, &uctx_thread1) < 0) { pr_err(stderr, "%s: swapcontext failed: %d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } *counter = __counter / 1000; return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-copy-file.c0000664000175000017500000000773312702231255015637 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_COPY_FILE) #include #include #include #include #include #include #include static uint64_t opt_copy_file_bytes = DEFAULT_COPY_FILE_BYTES; static bool set_copy_file_bytes; static int sys_copy_file_range( int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) { #if defined(__NR_copy_file_range) return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags); #else (void)fd_in; (void)off_in; (void)fd_out; (void)off_out; (void)len; (void)flags; errno = ENOSYS; return -1; #endif } void stress_set_copy_file_bytes(const char *optarg) { set_copy_file_bytes = true; opt_copy_file_bytes = get_uint64_byte(optarg); check_range("copy-file-bytes", opt_copy_file_bytes, MIN_COPY_FILE_BYTES, MAX_COPY_FILE_BYTES); } /* * stress_copy_file * stress reading chunks of file using copy_file_range() */ int stress_copy_file( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int fd_in, fd_out, rc = EXIT_FAILURE; char filename[PATH_MAX], tmp[PATH_MAX]; pid_t pid = getpid(); if (!set_copy_file_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_copy_file_bytes = MAX_HDD_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_copy_file_bytes = MIN_HDD_BYTES; } if (opt_copy_file_bytes < DEFAULT_COPY_FILE_SIZE) opt_copy_file_bytes = DEFAULT_COPY_FILE_SIZE * 2; if (stress_temp_dir_mk(name, pid, instance) < 0) goto tidy_dir; (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); snprintf(tmp, sizeof(tmp), "%s-orig", filename); if ((fd_in = open(tmp, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto tidy_dir; } (void)unlink(tmp); if (ftruncate(fd_in, opt_copy_file_bytes) < 0) { rc = exit_status(errno); pr_fail_err(name, "ftruncate"); goto tidy_in; } if (fsync(fd_in) < 0) { pr_fail_err(name, "fsync"); goto tidy_in; } snprintf(tmp, sizeof(tmp), "%s-copy", filename); if ((fd_out = open(tmp, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto tidy_in; } (void)unlink(tmp); do { ssize_t ret; loff_t off_in, off_out; off_in = mwc64() % (opt_copy_file_bytes - DEFAULT_COPY_FILE_SIZE); off_out = mwc64() % (opt_copy_file_bytes - DEFAULT_COPY_FILE_SIZE); ret = sys_copy_file_range(fd_in, &off_in, fd_out, &off_out, DEFAULT_COPY_FILE_SIZE, 0); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_err(name, "copy_file_range"); goto tidy_out; } (void)fsync(fd_out); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy_out: (void)close(fd_out); tidy_in: (void)close(fd_in); tidy_dir: (void)stress_temp_dir_rm(name, pid, instance); return rc; } #endif stress-ng-0.05.23/stress-filename.c0000664000175000017500000002045112702231255015520 0ustar kingking/* * Copyright (C) 2013-2016 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 STRESS_FILENAME_PROBE (0) /* Default */ #define STRESS_FILENAME_POSIX (1) /* POSIX 2008.1 */ #define STRESS_FILENAME_EXT (2) /* EXT* filesystems */ typedef struct { int opt; const char *opt_text; } filename_opts_t; static const filename_opts_t filename_opts[] = { { STRESS_FILENAME_PROBE, "probe" }, { STRESS_FILENAME_POSIX, "posix" }, { STRESS_FILENAME_EXT, "ext" }, { -1, NULL } }; /* Allowed filename characters */ static char allowed[256]; static int filename_opt = STRESS_FILENAME_PROBE; /* * The Open Group Base Specifications Issue 7 * POSIX.1-2008, 3.278 Portable Filename Character Set */ static char posix_allowed[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789._-"; int stress_filename_opts(const char *opt) { size_t i; for (i = 0; filename_opts[i].opt_text; i++) { if (!strcmp(opt, filename_opts[i].opt_text)) { filename_opt = i; return 0; } } fprintf(stderr, "filename-opt option '%s' not known, options are:", opt); for (i = 0; filename_opts[i].opt_text; i++) fprintf(stderr, "%s %s", i == 0 ? "" : ",", filename_opts[i].opt_text); fprintf(stderr, "\n"); return -1; } /* * stress_filename_probe() * determine allowed filename chars by probing */ int stress_filename_probe( const char *name, char *filename, char *ptr, size_t *chars_allowed) { size_t i, j; /* * Determine allowed char set for filenames */ for (j = 0, i = 0; i < 256; i++) { int fd; if ((i == 0) || (i == '/')) continue; *ptr = i; *(ptr + 1) = 'X'; *(ptr + 2) = '\0'; if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { /* We only expect EINVAL on bad filenames */ if (errno != EINVAL) { pr_err(stderr, "%s: creat() failed when probing " "for allowed filename characters, " "errno = %d (%s)\n", name, errno, strerror(errno)); pr_inf(stderr, "%s: perhaps retry and use --filename-opts posix\n", name); *chars_allowed = 0; return -errno; } } else { (void)close(fd); (void)unlink(filename); allowed[j] = i; j++; } } *chars_allowed = j; return 0; } /* * stress_filename_ext() * determine allowed for ext* filesystems */ void stress_filename_ext(size_t *chars_allowed) { size_t i, j; for (j = 0, i = 0; i < 256; i++) { if ((i == 0) || (i == '/')) continue; allowed[j] = i; j++; } *chars_allowed = j; } /* * stress_filename_generate() * generate a filename of length sz_max */ void stress_filename_generate( char *filename, const size_t sz_max, const char ch) { size_t i; for (i = 0; i < sz_max; i++) { filename[i] = ch; } if (*filename == '.') *filename = '_'; filename[i] = '\0'; } /* * stress_filename_generate_random() * generate a filename of length sz_max with * random selection from possible char set */ void stress_filename_generate_random( char *filename, const size_t sz_max, const size_t chars_allowed) { size_t i; for (i = 0; i < sz_max; i++) { const int j = mwc32() % chars_allowed; filename[i] = allowed[j]; } if (*filename == '.') *filename = '_'; filename[i] = '\0'; } /* * stress_filename_test() * create a file, and check if it fails. * should_pass = true - create must pass * should_pass = false - expect it to fail (name too long) */ void stress_filename_test( const char *name, const char *filename, const size_t sz_max, const bool should_pass) { int fd; if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { if ((!should_pass) && (errno == ENAMETOOLONG)) return; pr_fail(stderr, "%s: open failed on file of length " "%zu bytes, errno=%d (%s)\n", name, sz_max, errno, strerror(errno)); } else { (void)close(fd); (void)unlink(filename); } } /* * stress_filename() * stress filename sizes etc */ int stress_filename ( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); int ret, rc = EXIT_FAILURE; size_t sz_left, sz_max; char dirname[PATH_MAX]; char filename[PATH_MAX]; char *ptr; struct statvfs buf; size_t i, chars_allowed = 0, sz; stress_temp_dir(dirname, sizeof(dirname), name, pid, instance); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_fail_err(name, "mkdir"); return EXIT_FAILURE; } } if (statvfs(dirname, &buf) < 0) { pr_fail_err(name, "statvfs"); goto tidy_dir; } if (instance == 0) pr_dbg(stderr, "%s: maximum file size: %lu bytes\n", name, (long unsigned) buf.f_namemax); strncpy(filename, dirname, sizeof(filename) - 1); ptr = filename + strlen(dirname); *(ptr++) = '/'; *(ptr) = '\0'; sz_left = sizeof(filename) - (ptr - filename); sz_max = (size_t)buf.f_namemax; if (sz_left >= PATH_MAX) { pr_fail(stderr, "%s: max file name larger than PATH_MAX\n", name); goto tidy_dir; } switch (filename_opt) { case STRESS_FILENAME_POSIX: strncpy(allowed, posix_allowed, sizeof(allowed)); chars_allowed = strlen(allowed); break; case STRESS_FILENAME_EXT: stress_filename_ext(&chars_allowed); break; case STRESS_FILENAME_PROBE: default: ret = stress_filename_probe(name, filename, ptr, &chars_allowed); if (ret < 0) { rc = exit_status(-ret); goto tidy_dir; } break; } if (instance == 0) pr_dbg(stdout, "%s: filesystem allows %zu unique characters in a filename\n", name, chars_allowed); if (chars_allowed == 0) { pr_fail(stderr, "%s: cannot determine allowed characters in a filename\n", name); goto tidy_dir; } i = 0; sz = 1; do { char ch = allowed[i]; size_t rnd_sz = 1 + (mwc32() % sz_max); i++; if (i >= chars_allowed) i = 0; /* Should succeed */ stress_filename_generate(ptr, 1, ch); stress_filename_test(name, filename, 1, true); stress_filename_generate_random(ptr, 1, chars_allowed); stress_filename_test(name, filename, 1, true); /* Should succeed */ stress_filename_generate(ptr, sz_max, ch); stress_filename_test(name, filename, sz_max, true); stress_filename_generate_random(ptr, sz_max, chars_allowed); stress_filename_test(name, filename, sz_max, true); /* Should succeed */ stress_filename_generate(ptr, sz_max - 1, ch); stress_filename_test(name, filename, sz_max - 1, true); stress_filename_generate_random(ptr, sz_max - 1, chars_allowed); stress_filename_test(name, filename, sz_max - 1, true); /* Should fail */ stress_filename_generate(ptr, sz_max + 1, ch); stress_filename_test(name, filename, sz_max + 1, false); stress_filename_generate_random(ptr, sz_max + 1, chars_allowed); stress_filename_test(name, filename, sz_max + 1, false); /* Should succeed */ stress_filename_generate(ptr, sz, ch); stress_filename_test(name, filename, sz, true); stress_filename_generate_random(ptr, sz, chars_allowed); stress_filename_test(name, filename, sz, true); /* Should succeed */ stress_filename_generate(ptr, rnd_sz, ch); stress_filename_test(name, filename, rnd_sz, true); stress_filename_generate_random(ptr, rnd_sz, chars_allowed); stress_filename_test(name, filename, rnd_sz, true); sz++; if (sz > sz_max) sz = 1; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy_dir: (void)rmdir(dirname); return rc; } stress-ng-0.05.23/stress-fork.c0000664000175000017500000000741412702231255014705 0ustar kingking/* * Copyright (C) 2013-2016 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 bool set_fork_max = false; #if defined(STRESS_VFORK) static uint64_t opt_vfork_max = DEFAULT_VFORKS; static bool set_vfork_max = false; #endif /* * stress_set_fork_max() * set maximum number of forks allowed */ void stress_set_fork_max(const char *optarg) { set_fork_max = true; opt_fork_max = get_uint64_byte(optarg); check_range("fork-max", opt_fork_max, MIN_FORKS, MAX_FORKS); } #if defined(STRESS_VFORK) /* * stress_set_vfork_max() * set maximum number of vforks allowed */ void stress_set_vfork_max(const char *optarg) { set_vfork_max = true; opt_vfork_max = get_uint64_byte(optarg); check_range("vfork-max", opt_vfork_max, MIN_VFORKS, MAX_VFORKS); } #endif /* * 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; pid_t pids[MAX_FORKS]; do { unsigned int i; memset(pids, 0, sizeof(pids)); for (i = 0; i < fork_max; i++) { pid_t pid = fork_fn(); if (pid == 0) { /* Child, immediately exit */ _exit(0); } if (pid > -1) setpgid(pids[i], pgrp); pids[i] = pid; if (!opt_do_run) break; } for (i = 0; i < fork_max; i++) { if (pids[i] > 0) { int status; /* Parent, wait for child */ (void)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, "%s: fork failed\n", name); } } } 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) { if (!set_fork_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_fork_max = MAX_FORKS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_fork_max = MIN_FORKS; } return stress_fork_fn(counter, instance, max_ops, name, fork, opt_fork_max); } #if defined(STRESS_VFORK) /* * 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) { if (!set_vfork_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_vfork_max = MAX_VFORKS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_vfork_max = MIN_VFORKS; } return stress_fork_fn(counter, instance, max_ops, name, vfork, opt_vfork_max); } #endif stress-ng-0.05.23/stress-cpu.c0000664000175000017500000014612012702231255014531 0ustar kingking/* * Copyright (C) 2013-2016 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" #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)(const char *name); typedef struct { const char *name; /* human readable form of stressor */ const stress_cpu_func func; /* the stressor function */ } stress_cpu_stressor_info_t; /* * opt_cpu_load_slice: * < 0 - number of iterations per busy slice * = 0 - random duration between 0..0.5 seconds * > 0 - milliseconds per busy slice */ static int32_t opt_cpu_load_slice = -64; static int32_t opt_cpu_load = 100; static const stress_cpu_stressor_info_t *opt_cpu_stressor; static const stress_cpu_stressor_info_t cpu_methods[]; /* Don't make this static to ensure dithering does not get optimised out */ uint8_t pixels[STRESS_CPU_DITHER_X][STRESS_CPU_DITHER_Y]; void stress_set_cpu_load(const char *optarg) { opt_cpu_load = get_int32(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); } } void stress_set_cpu_load_slice(const char *optarg) { opt_cpu_load_slice = get_int32(optarg); if ((opt_cpu_load < -5000) || (opt_cpu_load > 5000)) { fprintf(stderr, "CPU load must in the range -5000 to 5000.\n"); exit(EXIT_FAILURE); } } /* * stress_cpu_sqrt() * stress CPU on square roots */ static void HOT stress_cpu_sqrt(const char *name) { int i; for (i = 0; i < 16384; i++) { uint64_t rnd = mwc32(); double r = sqrt((double)rnd) * sqrt((double)rnd); if ((opt_flags & OPT_FLAGS_VERIFY) && (uint64_t)rint(r) != rnd) { pr_fail(stderr, "%s: sqrt error detected on " "sqrt(%" PRIu64 ")\n", name, 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(const char *) __attribute__((optimize("-O0"))); #endif /* * stress_cpu_loop() * simple CPU busy loop */ static void stress_cpu_loop(const char *name) { uint32_t i, i_sum = 0; const uint32_t sum = 134209536UL; for (i = 0; i < 16384; i++) { i_sum += i; FORCE_DO_NOTHING(); } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "%s: cpu loop 0..16383 sum was %" PRIu32 " and " "did not match the expected value of %" PRIu32 "\n", name, i_sum, sum); } /* * stress_cpu_gcd() * compute Greatest Common Divisor */ static void HOT OPTIMIZE3 stress_cpu_gcd(const char *name) { 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; FORCE_DO_NOTHING(); } if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "%s: gcd error detected, failed modulo " "or assigment operations\n", name); } /* * stress_cpu_bitops() * various bit manipulation hacks from bithacks * https://graphics.stanford.edu/~seander/bithacks.html */ static void HOT OPTIMIZE3 stress_cpu_bitops(const char *name) { 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, "%s: bitops error detected, failed " "bitops operations\n", name); } /* * stress_cpu_trig() * simple sin, cos trig functions */ static void HOT stress_cpu_trig(const char *name) { int i; long double d_sum = 0.0; (void)name; 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 HOT stress_cpu_hyperbolic(const char *name) { int i; double d_sum = 0.0; (void)name; 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 += (double)(coshf(theta) * sinhf(theta)); } { long double theta2 = theta * 2.0; d_sum += coshl(theta2); d_sum += cosh(theta2); d_sum += (double)coshf(theta2); } { long double theta3 = theta * 3.0; d_sum += sinhl(theta3); d_sum += sinh(theta3); d_sum += (double)sinhf(theta3); } } double_put(d_sum); } /* * stress_cpu_rand() * generate lots of pseudo-random integers */ static void HOT OPTIMIZE3 stress_cpu_rand(const char *name) { int i; uint32_t i_sum = 0; const uint32_t sum = 0xc253698c; MWC_SEED(); for (i = 0; i < 16384; i++) i_sum += mwc32(); if ((opt_flags & OPT_FLAGS_VERIFY) && (i_sum != sum)) pr_fail(stderr, "%s: rand error detected, failed sum of " "pseudo-random values\n", name); } /* * stress_cpu_rand48() * generate random values using rand48 family of functions */ static void HOT OPTIMIZE3 stress_cpu_rand48(const char *name) { int i; double d = 0; long int l = 0; (void)name; srand48(0x0defaced); for (i = 0; i < 16384; i++) { d += drand48(); l += lrand48(); } double_put(d); uint64_put(l); } /* * stress_cpu_nsqrt() * iterative Newton–Raphson square root */ static void HOT OPTIMIZE3 stress_cpu_nsqrt(const char *name) { 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, "%s: Newton-Raphson sqrt " "computation took more iterations " "than expected\n", name); if ((int)rintl(rt * rt) != i) pr_fail(stderr, "%s: Newton-Rapshon sqrt not " "accurate enough\n", name); } } } /* * stress_cpu_phi() * compute the Golden Ratio */ static void HOT OPTIMIZE3 stress_cpu_phi(const char *name) { 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 = mwc64() % 99; b = mwc64() % 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, "%s: Golden Ratio phi not accurate enough\n", name); } /* * fft_partial() * partial Fast Fourier Transform */ static void HOT OPTIMIZE3 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) { const double complex negI = -I; double complex v = tmp[i]; double complex t = cexp((negI * 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 HOT stress_cpu_fft(const char *name) { double complex buf[FFT_SIZE], tmp[FFT_SIZE]; int i; (void)name; 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 HOT OPTIMIZE3 stress_cpu_euler(const char *name) { long double e = 1.0, last_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, "%s: Euler computation took more iterations " "than expected\n", name); } /* * 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 = mwc32(); *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, const char *hash_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: %s error detected, failed hash %s sum\n", name, hash_name, hash_name); } /* * jenkin() * Jenkin's hash on random data * http://www.burtleburtle.net/bob/hash/doobs.html */ static uint32_t HOT OPTIMIZE3 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(const char *name) { 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, "%s: jenkin error detected, failed hash " "jenkin sum\n", name); } /* * pjw() * Hash a string, from Aho, Sethi, Ullman, Compiling Techniques. */ static uint32_t HOT OPTIMIZE3 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(const char *name) { stress_cpu_hash_generic(name, "pjw", pjw, 0xa89a91c0); } /* * djb2a() * Hash a string, from Dan Bernstein comp.lang.c (xor version) */ static uint32_t HOT OPTIMIZE3 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(const char *name) { stress_cpu_hash_generic(name, "djb2a", djb2a, 0x6a60cb5a); } /* * fnv1a() * Hash a string, using the improved 32 bit FNV-1a hash */ static uint32_t HOT OPTIMIZE3 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 HOT stress_cpu_fnv1a(const char *name) { stress_cpu_hash_generic(name, "fnv1a", fnv1a, 0x8ef17e80); } /* * sdbm() * Hash a string, using the sdbm data base hash and also * apparently used in GNU awk. */ static uint32_t OPTIMIZE3 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(const char *name) { stress_cpu_hash_generic(name, "sdbm", sdbm, 0x46357819); } /* * stress_cpu_idct() * compute 8x8 Inverse Discrete Cosine Transform */ static void HOT OPTIMIZE3 stress_cpu_idct(const char *name) { 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, "%s: IDCT error detected, " "IDCT[%d][%d] was %d, expecting 255\n", name, 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 *= mwc32(); \ b ^= mwc32(); \ a += mwc32(); \ b -= mwc32(); \ 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 HOT OPTIMIZE3 stress_cpu_int ## _sz(const char *name)\ { \ 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 = mwc32(); \ b = mwc32(); \ \ 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, "%s: int" # _sz " error detected, " \ "failed int" # _sz \ " math operations\n", name); \ } \ /* 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(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x62f086e6160e4e,0xd84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3)) #endif stress_cpu_int(uint64_t, 64, \ 0x013f7f6dc1d79197cULL, 0x01863d2c6969a51ceULL, 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 HOT OPTIMIZE3 stress_cpu_ ## _name(const char *name)\ { \ int i; \ _type a = 0.18728, b = mwc32(), c = mwc32(), d; \ \ (void)name; \ \ 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(HAVE_FLOAT_DECIMAL) && !defined(__clang__) stress_cpu_fp(_Decimal32, decimal32, sinf, cosf) stress_cpu_fp(_Decimal64, decimal64, sin, cos) stress_cpu_fp(_Decimal128, decimal128, sinl, cosl) #endif /* Append floating point literal specifier to literal value */ #define FP(val, ltype) val ## ltype #if defined(__STDC_IEC_559_COMPLEX__) /* * Generic complex stressor macro */ #define stress_cpu_complex(_type, _ltype, _name, _csin, _ccos) \ static void HOT OPTIMIZE3 stress_cpu_ ## _name(const char *name)\ { \ int i; \ _type cI = I; \ _type a = FP(0.18728, _ltype) + \ cI * FP(0.2762, _ltype), \ b = mwc32() - cI * FP(0.11121, _ltype), \ c = mwc32() + cI * mwc32(), d; \ \ (void)name; \ \ 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, f, complex_float, csinf, ccosf) stress_cpu_complex(complex double, , complex_double, csin, ccos) stress_cpu_complex(complex long double, l, complex_long_double, csinl, ccosl) #endif /* __STDC_IEC_559_COMPLEX__ */ #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 *= mwc32(); \ flt_a = (flt_b + flt_c) / flt_c; \ int_b ^= mwc32(); \ int_a += mwc32(); \ flt_b = flt_b * flt_c; \ int_b -= mwc32(); \ 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 HOT OPTIMIZE3 stress_cpu_int ## _sz ## _ ## _name(const char *name)\ { \ 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 = mwc32(), \ flt_c = mwc32(), flt_d; \ \ MWC_SEED(); \ int_a = mwc32(); \ int_b = mwc32(); \ \ 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, "%s: int" # _sz " error detected, "\ "failed int" # _sz "" # _ftype \ " math operations\n", name); \ \ 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, 0x13f7f6dc1d79197cULL, 0x1863d2c6969a51ceULL, C1, C2, C3, sinf, cosf) stress_cpu_int_fp(uint64_t, 64, double, double, 0x13f7f6dc1d79197cULL, 0x1863d2c6969a51ceULL, C1, C2, C3, sin, cos) stress_cpu_int_fp(uint64_t, 64, long double, longdouble, 0x13f7f6dc1d79197cULL, 0x1863d2c6969a51ceULL, C1, C2, C3, sinl, cosl) #if defined(STRESS_INT128) stress_cpu_int_fp(__uint128_t, 128, float, float, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sinf, cosf) stress_cpu_int_fp(__uint128_t, 128, double, double, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sin, cos) stress_cpu_int_fp(__uint128_t, 128, long double, longdouble, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), sinl, cosl) #if defined(HAVE_FLOAT_DECIMAL) && !defined(__clang__) stress_cpu_int_fp(__uint128_t, 128, _Decimal32, decimal32, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), (_Decimal32)sinf, (_Decimal32)cosf) stress_cpu_int_fp(__uint128_t, 128, _Decimal64, decimal64, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _UINT128(C1, C1), _UINT128(C2, C2), _UINT128(C3, C3), (_Decimal64)sin, (_Decimal64)cos) stress_cpu_int_fp(__uint128_t, 128, _Decimal128, decimal128, _UINT128(0x132af604d8b9183a,0x5e3af8fa7a663d74), _UINT128(0x0062f086e6160e4e,0x0d84c9f800365858), _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 HOT OPTIMIZE3 stress_cpu_rgb(const char *name) { int i; uint32_t rgb = mwc32() & 0xffffff; uint8_t r = rgb >> 16; uint8_t g = rgb >> 8; uint8_t b = rgb; (void)name; /* 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.299f * r) + (0.587f * g) + (0.114f * b); u = (b - y) * 0.565f; v = (r - y) * 0.713f; /* YUV back to RGB */ r = y + (1.403f * v); g = y - (0.344f * u) - (0.714f * v); b = y + (1.770f * 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 HOT OPTIMIZE3 stress_cpu_matrix_prod(const char *name) { 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; (void)name; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { a[i][j] = (long double)mwc32() * v; b[i][j] = (long double)mwc32() * 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 HOT OPTIMIZE3 stress_cpu_fibonacci(const char *name) { const uint64_t fn_res = 0xa94fad42221f2702ULL; 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, "%s: fibonacci error detected, summation " "or assignment failure\n", name); } /* * stress_cpu_psi * compute the constant psi, * the reciprocal Fibonacci constant */ static void HOT OPTIMIZE3 stress_cpu_psi(const char *name) { 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, "%s: calculation of reciprocal " "Fibonacci constant phi not as accurate " "as expected\n", name); if (i >= max_iter) pr_fail(stderr, "%s: calculation of reciprocal " "Fibonacci constant took more iterations " "than expected\n", name); } double_put(psi); } /* * stress_cpu_ln2 * compute ln(2) using series */ static void HOT OPTIMIZE3 stress_cpu_ln2(const char *name) { 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, "%s: calculation of ln(2) took more " "iterations than expected\n", name); double_put(ln2); } /* * ackermann() * a naive/simple implementation of the ackermann function */ static uint32_t HOT 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(const char *name) { uint32_t a = ackermann(3, 10); if ((opt_flags & OPT_FLAGS_VERIFY) && (a != 0x1ffd)) pr_fail(stderr, "%s: ackermann error detected, " "ackermann(3,10) miscalculated\n", name); } /* * stress_cpu_explog * compute exp(log(n)) */ static void HOT stress_cpu_explog(const char *name) { uint32_t i; double n = 1e6; (void)name; 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(const char *name) __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; \ uint64_put(next + i); /* * stress_cpu_jmp * jmp conditionals */ static void HOT stress_cpu_jmp(const char *name) { register int i, next = 0; (void)name; 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); } } /* * ccitt_crc16() * perform naive CCITT CRC16 */ static uint16_t HOT OPTIMIZE3 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(const char *name) { uint8_t buffer[1024]; size_t i; (void)name; 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 HOT OPTIMIZE3 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(const char *name) { long double precision = 0.00000001; int i; (void)name; for (i = 2; i < 11; i++) double_put(zeta((double complex)i, precision)); } /* * stress_cpu_gamma() * stress Euler–Mascheroni constant gamma */ static void HOT OPTIMIZE3 stress_cpu_gamma(const char *name) { 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, "%s: calculation of Euler-Mascheroni " "constant not as accurate as expected\n", name); if (k > 80000.0) pr_fail(stderr, "%s: calculation of Euler-Mascheroni " "constant took more iterations than " "expected\n", name); } } /* * stress_cpu_correlate() * * Introduction to Signal Processing, * Prentice-Hall, 1995, ISBN: 0-13-209172-0. */ static void HOT OPTIMIZE3 stress_cpu_correlate(const char *name) { 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]; (void)name; /* Generate some random data */ for (i = 0; i < data_len; i++) { data[i] = mwc64(); 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 HOT OPTIMIZE3 stress_cpu_sieve(const char *name) { 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 (STRESS_GETBIT(sieve, i)) for (j = i * i; j < SIEVE_SIZE; j += i) STRESS_CLRBIT(sieve, j); /* And count up number of primes */ for (j = 0, i = 2; i < SIEVE_SIZE; i++) { if (STRESS_GETBIT(sieve, i)) j++; } if ((opt_flags & OPT_FLAGS_VERIFY) && (j != 664579)) pr_fail(stderr, "%s: sieve error detected, number of " "primes has been miscalculated\n", name); } /* * is_prime() * return true if n is prime * http://en.wikipedia.org/wiki/Primality_test */ static inline HOT OPTIMIZE3 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(const char *name) { 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, "%s: prime error detected, number of primes " "between 0 and 1000000 miscalculated\n", name); } /* * stress_cpu_gray() * compute gray codes */ static void HOT OPTIMIZE3 stress_cpu_gray(const char *name) { uint32_t i; uint64_t sum = 0; for (i = 0; i < 0x10000; i++) { register uint32_t gray_code; /* Binary to Gray code */ gray_code = (i >> 1) ^ i; sum += gray_code; /* Gray code back to binary */ #if 0 { /* Slow iterative method */ register uint32_t mask; for (mask = gray_code >> 1; mask; mask >>= 1) gray_code ^= mask; } #else /* Fast non-loop method */ gray_code ^= (gray_code >> 1); gray_code ^= (gray_code >> 2); gray_code ^= (gray_code >> 4); gray_code ^= (gray_code >> 8); gray_code ^= (gray_code >> 16); #endif sum += gray_code; } if ((opt_flags & OPT_FLAGS_VERIFY) && (sum != 0xffff0000)) pr_fail(stderr, "%s: gray code error detected, sum of gray " "codes between 0x00000 and 0x10000 miscalculated\n", name); } /* * hanoi() * do a Hanoi move */ static uint32_t HOT 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(const char *name) { uint32_t n = hanoi(20, 'X', 'Y', 'Z'); if ((opt_flags & OPT_FLAGS_VERIFY) && (n != 1048576)) pr_fail(stderr, "%s: number of hanoi moves different from " "the expected number\n", name); uint64_put(n); } /* * factorial() * compute n! */ static long double HOT OPTIMIZE3 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 HOT OPTIMIZE3 stress_cpu_pi(const char *name) { 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, "%s: number of iterations to compute " "pi was more than expected\n", name); if (fabsl(pi - M_PI) > 1.0e-15) pr_fail(stderr, "%s: accuracy of computed pi is not " "as good as expected\n", name); } double_put(pi); } /* * stress_cpu_omega() * compute the constant omega * See http://en.wikipedia.org/wiki/Omega_constant */ static void HOT OPTIMIZE3 stress_cpu_omega(const char *name) { 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, "%s: number of iterations to compute " "omega was more than expected\n", name); if (fabsl(omega - OMEGA) > 1.0e-16) pr_fail(stderr, "%s: accuracy of computed omega is " "not as good as expected\n", name); } 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 HOT OPTIMIZE3 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[] = { 0xf1, /* 0b11110001 */ 0xd2, /* 0b11010010 */ 0xb4, /* 0b10110100 */ 0x78, /* 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 HOT OPTIMIZE3 stress_cpu_hamming(const char *name) { 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, "%s: hamming error detected, sum of 65536 " "hamming codes not correct\n", name); } static ptrdiff_t stress_cpu_callfunc_func( ssize_t n, uint64_t u64arg, uint32_t u32arg, uint16_t u16arg, uint8_t u8arg, uint64_t *p_u64arg, uint32_t *p_u32arg, uint16_t *p_u16arg, uint8_t *p_u8arg) { if (n > 0) return stress_cpu_callfunc_func(n - 1, u64arg, u32arg, u16arg, u8arg, p_u64arg, p_u32arg, p_u16arg, p_u8arg); else return &u64arg - p_u64arg; } /* * stress_cpu_callfunc() * deep function calls */ static void stress_cpu_callfunc(const char *name) { uint64_t u64arg = mwc64(); uint32_t u32arg = mwc32(); uint16_t u16arg = mwc16(); uint8_t u8arg = mwc8(); ptrdiff_t ret; (void)name; ret = stress_cpu_callfunc_func(1024, u64arg, u32arg, u16arg, u8arg, &u64arg, &u32arg, &u16arg, &u8arg); uint64_put((uint64_t)ret); } #define P2(n) n, n^1, n^1, n #define P4(n) P2(n), P2(n^1), P2(n^1), P2(n) #define P6(n) P4(n), P4(n^1), P4(n^1), P4(n) static const bool stress_cpu_parity_table[256] = { P6(0), P6(1), P6(1), P6(0) }; /* * stress_cpu_parity * compute parity different ways */ static void stress_cpu_parity(const char *name) { uint32_t val = 0x83fb5acf; size_t i; for (i = 0; i < 1000; i++, val++) { uint32_t v, parity, p; uint8_t *ptr; /* * Naive way */ v = val; parity = 0; while (v) { if (v & 1) parity = !parity; v >>= 1; } /* * Naive way with Brian Kernigan's bit counting optimisation * https://graphics.stanford.edu/~seander/bithacks.html */ v = val; p = 0; while (v) { p = !p; v = v & (v - 1); } if ((opt_flags & OPT_FLAGS_VERIFY) && (p != parity)) pr_fail(stderr, "%s: parity error detected, using " "optimised naive method\n", name); /* * "Compute parity of a word with a multiply" * the Andrew Shapira method, * https://graphics.stanford.edu/~seander/bithacks.html */ v = val; v ^= v >> 1; v ^= v >> 2; v = (v & 0x11111111U) * 0x11111111U; p = (v >> 28) & 1; if ((opt_flags & OPT_FLAGS_VERIFY) && (p != parity)) pr_fail(stderr, "%s: parity error detected, using the " "multiply Shapira method\n", name); /* * "Compute parity in parallel" * https://graphics.stanford.edu/~seander/bithacks.html */ v = val; v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; p = (0x6996 >> v) & 1; if ((opt_flags & OPT_FLAGS_VERIFY) && (p != parity)) pr_fail(stderr, "%s: parity error detected, using " "the parallel method\n", name); /* * "Compute parity by lookup table" * https://graphics.stanford.edu/~seander/bithacks.html * Variation #1 */ v = val; v ^= v >> 16; v ^= v >> 8; p = stress_cpu_parity_table[v & 0xff]; if ((opt_flags & OPT_FLAGS_VERIFY) && (p != parity)) pr_fail(stderr, "%s: parity error detected, using " "the lookup method, variation 1\n", name); /* * "Compute parity by lookup table" * https://graphics.stanford.edu/~seander/bithacks.html * Variation #2 */ ptr = (uint8_t *)&val; p = stress_cpu_parity_table[ptr[0] ^ ptr[1] ^ ptr[2] ^ ptr[3]]; if ((opt_flags & OPT_FLAGS_VERIFY) && (p != parity)) pr_fail(stderr, "%s: parity error detected, using the " "lookup method, variation 1\n", name); } } /* * stress_cpu_dither * perform 8 bit to 1 bit gray scale * Floyd–Steinberg dither */ static void stress_cpu_dither(const char *name) { size_t x, y; (void)name; /* * Generate some random 8 bit image */ for (y = 0; y < STRESS_CPU_DITHER_Y; y += 8) { for (x = 0; x < STRESS_CPU_DITHER_X; x ++) { uint64_t v = mwc64(); pixels[x][y + 0] = v; v >>= 8; pixels[x][y + 1] = v; v >>= 8; pixels[x][y + 2] = v; v >>= 8; pixels[x][y + 3] = v; v >>= 8; pixels[x][y + 4] = v; v >>= 8; pixels[x][y + 5] = v; v >>= 8; pixels[x][y + 6] = v; v >>= 8; pixels[x][y + 7] = v; } } /* * ..and dither */ for (y = 0; y < STRESS_CPU_DITHER_Y; y++) { for (x = 0; x < STRESS_CPU_DITHER_X; x++) { uint8_t pixel = pixels[x][y]; uint8_t quant = (pixel < 128) ? 0 : 255; int32_t error = pixel - quant; bool xok1 = x < (STRESS_CPU_DITHER_X - 1); bool xok2 = x > 0; bool yok1 = y < (STRESS_CPU_DITHER_Y - 1); if (xok1) pixels[x + 1][y] += (error * 7) >> 4; if (xok2 && yok1) pixels[x - 1][y + 1] += (error * 3) >> 4; if (yok1) pixels[x][y + 1] += (error * 5) >> 4; if (xok1 && yok1) pixels[x + 1][y + 1] += error >> 4; } } } /* * stress_cpu_union * perform bit field operations on a packed union */ static void stress_cpu_union(const char *name) { typedef union { struct { uint64_t b1:1; uint64_t b10:10; uint64_t b2:2; uint64_t b9:9; uint64_t b3:3; uint64_t b8:8; uint64_t b4:4; uint64_t b7:7; uint64_t b5:5; uint64_t b6:6; } bits64; uint64_t u64:64; union { uint8_t b1:1; uint8_t b7:7; uint8_t b8:8; } bits8; struct { uint16_t b15:15; uint16_t b1:1; } bits16; struct { uint32_t b10:10; uint32_t b20:20; uint32_t :1; uint32_t b1:1; } bits32; uint32_t u32:30; } __attribute__ ((packed)) u_t; static u_t u; size_t i; (void)name; for (i = 0; i < 1000; i++) { u.bits64.b1 ^= 1; u.bits64.b2--; u.bits32.b10 ^= ~0; u.bits64.b3++; u.bits16.b1--; u.bits8.b1++; u.bits64.b4 *= 2; u.bits32.b20 += 3; u.u64 += 0x1037fc2ae21ef829ULL; u.bits64.b6--; u.bits8.b7 *= 3; u.bits64.b5 += (u.bits64.b4 << 1); u.bits32.b1 ^= 1; u.bits64.b7++; u.bits8.b8 ^= 0xaa; u.bits64.b8--; u.bits16.b15 ^= 0xbeef; u.bits64.b9++; u.bits64.b10 *= 5; } } static const uint32_t queens_solutions[] = { -1, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200 }; /* * Solution from http://www.cl.cam.ac.uk/~mr10/backtrk.pdf * see section 2.1 */ static uint32_t queens_try( uint32_t left_diag, uint32_t cols, uint32_t right_diag, uint32_t all) { register uint32_t solutions = 0; register uint32_t poss = ~(left_diag | cols | right_diag) & all; while (poss) { register uint32_t bit = poss & -poss; register uint32_t new_cols = cols | bit; poss -= bit; solutions += (new_cols == all) ? 1 : queens_try((left_diag | bit) << 1, new_cols, (right_diag | bit) >> 1, all); } return solutions; } /* * stress_cpu_queens * solve the queens problem for sizes 1..12 */ static void stress_cpu_queens(const char *name) { uint32_t all, n; for (all = 1, n = 1; n < 13; n++) { uint32_t solutions = queens_try(0, 0, 0, all); if ((opt_flags & OPT_FLAGS_VERIFY) && (solutions != queens_solutions[n])) pr_fail(stderr, "%s: queens solution error detected " "on board size %" PRIu32 "\n", name, n); all = (all + all) + 1; } } /* * stress_cpu_all() * iterate over all cpu stressors */ static HOT OPTIMIZE3 void stress_cpu_all(const char *name) { static int i = 1; /* Skip over stress_cpu_all */ cpu_methods[i++].func(name); if (!cpu_methods[i].func) i = 1; } /* * Table of cpu stress methods */ static const stress_cpu_stressor_info_t cpu_methods[] = { { "all", stress_cpu_all }, /* Special "all test */ { "ackermann", stress_cpu_ackermann }, { "bitops", stress_cpu_bitops }, { "callfunc", stress_cpu_callfunc }, #if defined(__STDC_IEC_559_COMPLEX__) { "cdouble", stress_cpu_complex_double }, { "cfloat", stress_cpu_complex_float }, { "clongdouble", stress_cpu_complex_long_double }, #endif /* __STDC_IEC_559_COMPLEX__ */ { "correlate", stress_cpu_correlate }, { "crc16", stress_cpu_crc16 }, #if defined(HAVE_FLOAT_DECIMAL) && !defined(__clang__) { "decimal32", stress_cpu_decimal32 }, { "decimal64", stress_cpu_decimal64 }, { "decimal128", stress_cpu_decimal128 }, #endif { "dither", stress_cpu_dither }, { "djb2a", stress_cpu_djb2a }, { "double", stress_cpu_double }, { "euler", stress_cpu_euler }, { "explog", stress_cpu_explog }, { "fft", stress_cpu_fft }, { "fibonacci", stress_cpu_fibonacci }, { "float", stress_cpu_float }, { "fnv1a", stress_cpu_fnv1a }, { "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(HAVE_FLOAT_DECIMAL) && !defined(__clang__) { "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 }, { "parity", stress_cpu_parity }, { "phi", stress_cpu_phi }, { "pi", stress_cpu_pi }, { "pjw", stress_cpu_pjw }, { "prime", stress_cpu_prime }, { "psi", stress_cpu_psi }, { "queens", stress_cpu_queens }, { "rand", stress_cpu_rand }, { "rand48", stress_cpu_rand48 }, { "rgb", stress_cpu_rgb }, { "sdbm", stress_cpu_sdbm }, { "sieve", stress_cpu_sieve }, { "sqrt", stress_cpu_sqrt }, { "trig", stress_cpu_trig }, { "union", stress_cpu_union }, { "zeta", stress_cpu_zeta }, { NULL, NULL } }; /* * stress_set_cpu_method() * set the default cpu stress method */ int HOT OPTIMIZE3 stress_set_cpu_method(const char *name) { stress_cpu_stressor_info_t const *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; /* * Normal use case, 100% load, simple spinning on CPU */ if (opt_cpu_load == 100) { do { (void)func(name); (*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 { double t, delay; double t1, t2, t3; struct timeval tv; t1 = time_now(); if (opt_cpu_load_slice < 0) { /* < 0 specifies number of iterations to do per slice */ int j; for (j = 0; j < -opt_cpu_load_slice; j++) { (void)func(name); if (!opt_do_run) break; (*counter)++; } t2 = time_now(); } else if (opt_cpu_load_slice == 0) { /* == 0, random time slices */ double slice_end = t1 + (((double)mwc16()) / 131072.0); do { (void)func(name); t2 = time_now(); } while (t2 < slice_end); } else { /* > 0, time slice in milliseconds */ double slice_end = t1 + ((double)opt_cpu_load_slice / 1000.0); do { (void)func(name); t2 = time_now(); } while (t2 < slice_end); } t = t2 - t1; /* Must not calculate this with zero % load */ delay = t * (((100.0 / (double) opt_cpu_load)) - 1.0); delay -= bias; tv.tv_sec = delay; tv.tv_usec = (delay - tv.tv_sec) * 1000000.0; select(0, NULL, NULL, NULL, &tv); t3 = time_now(); /* Bias takes account of the time to do the delay */ bias = (t3 - t2) - delay; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-sigsuspend.c0000664000175000017500000000536512702231255016133 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #include #include #define CACHE_STRIDE_SHIFT (6) /* * stress_sigsuspend * stress sigsuspend */ int stress_sigsuspend( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid[MAX_SIGSUSPEND_PIDS]; size_t n, i; sigset_t mask; int status; uint64_t *counters, c; volatile uint64_t *v_counters; const size_t counters_size = (sizeof(uint64_t) * MAX_SIGSUSPEND_PIDS) << CACHE_STRIDE_SHIFT; (void)instance; v_counters = counters = mmap(NULL, counters_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (counters == MAP_FAILED) { pr_fail_dbg(name, "mmap"); return EXIT_FAILURE; } memset(counters, 0, counters_size); sigfillset(&mask); sigdelset(&mask, SIGUSR1); for (n = 0; n < MAX_SIGSUSPEND_PIDS; n++) { again: pid[n] = fork(); if (pid[n] < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); goto reap; } else if (pid[n] == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); while (opt_do_run) { sigsuspend(&mask); v_counters[n << CACHE_STRIDE_SHIFT]++; } _exit(0); } setpgid(pid[n], pgrp); } /* Parent */ do { c = 0; for (i = 0; i < n; i++) { c += v_counters[i << CACHE_STRIDE_SHIFT]; kill(pid[i], SIGUSR1); } } while (opt_do_run && (!max_ops || c < max_ops)); *counter = c; reap: for (i = 0; i < n; i++) { /* terminate child */ (void)kill(pid[i], SIGKILL); (void)waitpid(pid[i], &status, 0); } (void)munmap(counters, counters_size); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-vecmath.c0000664000175000017500000000762512702231255015377 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_VECMATH) #include #include #include #include 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; \ a <<= 1; \ b >>= 1; \ b += c; \ /* * stress_vecmath() * stress GCC vector maths */ int HOT OPTIMIZE3 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.05.23/stress-rlimit.c0000664000175000017500000000654112702231255015244 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_RLIMIT) #include #include #include #include #include #include #include #include #include #include static volatile bool do_jmp = true; static sigjmp_buf jmp_env; /* * stress_rlimit_handler() * rlimit generic handler */ static void MLOCKED stress_rlimit_handler(int dummy) { (void)dummy; if (do_jmp) siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } /* * stress_rlimit * stress by generating rlimit signals */ int stress_rlimit( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct rlimit limit; struct sigaction old_action_xcpu, old_action_xfsz; int fd; char filename[PATH_MAX]; const pid_t pid = getpid(); if (stress_sighandler(name, SIGXCPU, stress_rlimit_handler, &old_action_xcpu) < 0) return EXIT_FAILURE; if (stress_sighandler(name, SIGXFSZ, stress_rlimit_handler, &old_action_xfsz) < 0) return EXIT_FAILURE; (void)umask(0077); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); if (stress_temp_dir_mk(name, pid, instance) < 0) return EXIT_FAILURE; if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { pr_fail_err(name, "creat"); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } (void)unlink(filename); /* Trigger SIGXCPU every second */ limit.rlim_cur = 1; limit.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CPU, &limit); /* Trigger SIGXFSZ every time we truncate file */ limit.rlim_cur = 1; limit.rlim_max = 1; setrlimit(RLIMIT_FSIZE, &limit); do { int ret; ret = sigsetjmp(jmp_env, 1); /* * We return here if we generate an rlimit signal, 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 { /* Trigger an rlimit signal */ if (ftruncate(fd, 2) < 0) { /* Ignore */ } } } while (opt_do_run && (!max_ops || *counter < max_ops)); do_jmp = false; (void)stress_sigrestore(name, SIGXCPU, &old_action_xcpu); (void)stress_sigrestore(name, SIGXFSZ, &old_action_xfsz); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-qsort.c0000664000175000017500000001146112702231255015111 0ustar kingking/* * Copyright (C) 2013-2016 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_qsort_size = DEFAULT_QSORT_SIZE; static bool set_qsort_size = false; static volatile bool do_jmp = true; static sigjmp_buf jmp_env; /* * stress_qsort_handler() * SIGALRM generic handler */ static void MLOCKED stress_qsort_handler(int dummy) { (void)dummy; if (do_jmp) { do_jmp = false; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } } /* * stress_set_qsort_size() * set qsort size */ void stress_set_qsort_size(const void *optarg) { set_qsort_size = true; 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; size_t n, i; struct sigaction old_action; int ret; (void)instance; if (!set_qsort_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_qsort_size = MAX_QSORT_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_qsort_size = MIN_QSORT_SIZE; } n = (size_t)opt_qsort_size; if ((data = calloc(n, sizeof(int32_t))) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_NO_RESOURCE; } if (stress_sighandler(name, SIGALRM, stress_qsort_handler, &old_action) < 0) { free(data); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); if (ret) { /* * We return here if SIGALRM jmp'd back */ (void)stress_sigrestore(name, SIGALRM, &old_action); goto tidy; } /* This is expensive, do it once */ for (ptr = data, i = 0; i < n; i++) *ptr++ = mwc32(); 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, "%s: sort error " "detected, incorrect ordering " "found\n", name); 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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; /* And re-order by byte compare */ qsort((uint8_t *)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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); do_jmp = false; (void)stress_sigrestore(name, SIGALRM, &old_action); tidy: free(data); return EXIT_SUCCESS; } stress-ng-0.05.23/net.c0000664000175000017500000001043512702231255013206 0ustar kingking/* * Copyright (C) 2013-2016 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; const int domain_flags; } domain_t; static const domain_t domains[] = { { "ipv4", AF_INET, DOMAIN_INET }, { "ipv6", AF_INET6, DOMAIN_INET6 }, { "unix", AF_UNIX, DOMAIN_UNIX }, { NULL, -1, ~0 } }; /* * 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 int domain_mask, const char *name, const char *domain_name, int *domain) { size_t i; for (i = 0; domains[i].name; i++) { if ((domain_mask & domains[i].domain_flags) && !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++) if (domain_mask & domains[i].domain_flags) 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_fail_dbg(name, "unknown domain"); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } } /* * setup just the socket address port */ void HOT stress_set_sockaddr_port( const int domain, const int port, struct sockaddr *sockaddr) { switch (domain) { #ifdef AF_INET case AF_INET: { struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; addr->sin_port = htons(port); break; } #endif #ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr; addr->sin6_port = htons(port); break; } #endif #ifdef AF_UNIX case AF_UNIX: break; #endif default: break; } } stress-ng-0.05.23/stress-vm-splice.c0000664000175000017500000000605212702231255015640 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_VM_SPLICE) #include #include #include #include #include #include #include #include static size_t opt_vm_splice_bytes = DEFAULT_VM_SPLICE_BYTES; static bool set_vm_splice_bytes = false; void stress_set_vm_splice_bytes(const char *optarg) { set_vm_splice_bytes = true; 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(); size_t sz; (void)instance; if (!set_vm_splice_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_vm_splice_bytes = MAX_VM_SPLICE_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_vm_splice_bytes = MIN_VM_SPLICE_BYTES; } sz = opt_vm_splice_bytes & ~(page_size - 1); buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (buf == MAP_FAILED) { int rc = exit_status(errno); pr_fail_dbg(name, "mmap"); return rc; } if (pipe(fds) < 0) { (void)munmap(buf, sz); pr_fail_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_fail_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.05.23/stress-brk.c0000664000175000017500000000754312702231255014525 0ustar kingking/* * Copyright (C) 2013-2016 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: if (!opt_do_run) return EXIT_SUCCESS; pid = fork(); if (pid < 0) { if (errno == EAGAIN) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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 *start_ptr; bool touch = !(opt_flags & OPT_FLAGS_BRK_NOTOUCH); int i = 0; setpgid(0, pgrp); stress_parent_died_alarm(); /* 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 { uint8_t *ptr; i++; if (i > 8) { i = 0; ptr = sbrk(0); ptr -= page_size; if (brk(ptr) < 0) ptr = (void *)-1; } else { 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)); } 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.05.23/stress-membarrier.c0000664000175000017500000000725512702231255016074 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MEMBARRIER) #include #include #include #include #include #include #define MAX_MEMBARRIER_THREADS (4) static volatile bool keep_running; static sigset_t set; enum membarrier_cmd { MEMBARRIER_CMD_QUERY = 0, MEMBARRIER_CMD_SHARED = (1 << 0), }; static int sys_membarrier(int cmd, int flags) { #if defined(__NR_membarrier) return syscall(__NR_membarrier, cmd, flags); #else errno = ENOSYS; return -1; #endif } static void *stress_membarrier_thread(void *ctxt) { static void *nowt = NULL; uint8_t stack[SIGSTKSZ]; stack_t ss; char *name = (char *)ctxt; (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 totally unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_fail_err("pthread", "sigaltstack"); return &nowt; } while (keep_running && opt_do_run) { if (sys_membarrier(MEMBARRIER_CMD_SHARED, 0) < 0) { pr_err(stderr, "%s: membarrier failed: errno=%d: (%s)\n", name, errno, strerror(errno)); break; } } return &nowt; } /* * stress on membarrier() * stress system by IO sync calls */ int stress_membarrier( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int ret; pthread_t pthreads[MAX_MEMBARRIER_THREADS]; size_t i; int pthread_ret[MAX_MEMBARRIER_THREADS]; (void)instance; ret = sys_membarrier(MEMBARRIER_CMD_QUERY, 0); if (ret < 0) { pr_err(stderr, "%s: membarrier failed: errno=%d: (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } if (!(ret & MEMBARRIER_CMD_SHARED)) { pr_inf(stderr, "%s: membarrier MEMBARRIER_CMD_SHARED " "not supported\n", name); return EXIT_FAILURE; } sigfillset(&set); memset(pthread_ret, 0, sizeof(ret)); keep_running = true; for (i = 0; i < MAX_MEMBARRIER_THREADS; i++) { pthread_ret[i] = pthread_create(&pthreads[i], NULL, stress_membarrier_thread, (void *)name); } do { ret = sys_membarrier(MEMBARRIER_CMD_SHARED, 0); if (ret < 0) { pr_err(stderr, "%s: membarrier failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); keep_running = false; for (i = 0; i < MAX_MEMBARRIER_THREADS; i++) { if (pthread_ret[i] == 0) pthread_join(pthreads[i], NULL); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-matrix.c0000664000175000017500000002023412702231255015243 0ustar kingking/* * Copyright (C) 2013-2016 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" typedef float matrix_type_t; /* * the CPU stress test has different classes of cpu stressor */ typedef void (*stress_matrix_func)( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]); typedef struct { const char *name; /* human readable form of stressor */ const stress_matrix_func func; /* the stressor function */ } stress_matrix_stressor_info_t; static const stress_matrix_stressor_info_t *opt_matrix_stressor; static const stress_matrix_stressor_info_t matrix_methods[]; static size_t opt_matrix_size = 128; static bool set_matrix_size = false; void stress_set_matrix_size(const char *optarg) { uint64_t size; set_matrix_size = true; size = get_uint64_byte(optarg); check_range("matrix-size", size, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE); opt_matrix_size = (size_t)size; } /* * stress_matrix_prod(void) * matrix product */ static void OPTIMIZE3 stress_matrix_prod( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { size_t i; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { register size_t k; for (k = 0; k < n; k++) { r[i][j] += a[i][k] * b[k][j]; } if (!opt_do_run) return; } } } /* * stress_matrix_add(void) * matrix addition */ static void OPTIMIZE3 stress_matrix_add( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = a[i][j] + b[i][j]; } if (!opt_do_run) return; } } /* * stress_matrix_sub(void) * matrix subtraction */ static void OPTIMIZE3 stress_matrix_sub( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = a[i][j] - b[i][j]; } if (!opt_do_run) return; } } /* * stress_matrix_trans(void) * matrix transpose */ static void OPTIMIZE3 stress_matrix_trans( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], /* Ignored */ matrix_type_t r[n][n]) { register size_t i; (void)b; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = a[j][i]; } if (!opt_do_run) return; } } /* * stress_matrix_mult(void) * matrix scalar multiply */ static void OPTIMIZE3 stress_matrix_mult( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; (void)b; matrix_type_t v = b[0][0]; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = v * a[i][j]; } if (!opt_do_run) return; } } /* * stress_matrix_div(void) * matrix scalar divide */ static void OPTIMIZE3 stress_matrix_div( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; (void)b; matrix_type_t v = b[0][0]; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = a[i][j] / v; } if (!opt_do_run) return; } } /* * stress_matrix_hadamard(void) * matrix hadamard product * (A o B)ij = AijBij */ static void OPTIMIZE3 stress_matrix_hadamard( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { r[i][j] = a[i][j] * b[i][j]; } if (!opt_do_run) return; } } /* * stress_matrix_frobenius(void) * matrix frobenius product * A : B = Sum(AijBij) */ static void OPTIMIZE3 stress_matrix_frobenius( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; matrix_type_t sum = 0.0; (void)r; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { sum += a[i][j] * b[i][j]; } if (!opt_do_run) return; } double_put(sum); } /* * stress_matrix_copy(void) * naive matrix copy, r = a */ static void OPTIMIZE3 stress_matrix_copy( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; (void)b; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) r[i][j] = a[i][j]; if (!opt_do_run) return; } } /* * stress_matrix_mean(void) * arithmetic mean */ static void OPTIMIZE3 stress_matrix_mean( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { register size_t i; for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) r[i][j] = (a[i][j] + b[i][j]) / 2.0; if (!opt_do_run) return; } } /* * stress_matrix_all() * iterate over all cpu stressors */ static void OPTIMIZE3 stress_matrix_all( const size_t n, matrix_type_t a[n][n], matrix_type_t b[n][n], matrix_type_t r[n][n]) { static int i = 1; /* Skip over stress_matrix_all */ matrix_methods[i++].func(n, a, b, r); if (!matrix_methods[i].func) i = 1; } /* * Table of cpu stress methods */ static const stress_matrix_stressor_info_t matrix_methods[] = { { "all", stress_matrix_all }, /* Special "all" test */ { "add", stress_matrix_add }, { "copy", stress_matrix_copy }, { "div", stress_matrix_div }, { "frobenius", stress_matrix_frobenius }, { "hadamard", stress_matrix_hadamard }, { "mean", stress_matrix_mean }, { "mult", stress_matrix_mult }, { "prod", stress_matrix_prod }, { "sub", stress_matrix_sub }, { "trans", stress_matrix_trans }, { NULL, NULL } }; /* * stress_set_matrix_method() * set the default matrix stress method */ int stress_set_matrix_method(const char *name) { stress_matrix_stressor_info_t const *info = matrix_methods; for (info = matrix_methods; info->func; info++) { if (!strcmp(info->name, name)) { opt_matrix_stressor = info; return 0; } } fprintf(stderr, "matrix-method must be one of:"); for (info = matrix_methods; info->func; info++) { fprintf(stderr, " %s", info->name); } fprintf(stderr, "\n"); return -1; } /* * stress_matrix() * stress CPU by doing floating point math ops */ int stress_matrix( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { stress_matrix_func func = opt_matrix_stressor->func; size_t n; const matrix_type_t v = 1 / (matrix_type_t)((uint32_t)~0); (void)instance; (void)name; if (!set_matrix_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_matrix_size = MAX_MATRIX_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_matrix_size = MIN_MATRIX_SIZE; } n = opt_matrix_size; { register size_t i; matrix_type_t a[n][n], b[n][n], r[n][n]; /* * Initialise matrices */ for (i = 0; i < n; i++) { register size_t j; for (j = 0; j < n; j++) { a[i][j] = (matrix_type_t)mwc64() * v; b[i][j] = (matrix_type_t)mwc64() * v; r[i][j] = 0.0; } } /* * Normal use case, 100% load, simple spinning on CPU */ do { (void)func(n, a, b, r); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-urandom.c0000664000175000017500000000363112702231255015406 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_URANDOM) #include #include #include #include #include #include #include /* * 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_fail_err(name, "open"); return EXIT_FAILURE; } do { char buffer[8192]; ssize_t ret; ret = read(fd, buffer, sizeof(buffer)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_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.05.23/stress-mmap.c0000664000175000017500000002244512702231255014677 0ustar kingking/* * Copyright (C) 2013-2016 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 NO_MEM_RETRIES_MAX (100) static size_t opt_mmap_bytes = DEFAULT_MMAP_BYTES; static bool set_mmap_bytes = false; /* Misc randomly chosen mmap flags */ static int mmap_flags[] = { #if defined(MAP_HUGE_2MB) && defined(MAP_HUGETLB) MAP_HUGE_2MB | MAP_HUGETLB, #endif #if defined(MAP_HUGE_1GB) && defined(MAP_HUGETLB) MAP_HUGE_1GB | MAP_HUGETLB, #endif #if defined(MAP_NONBLOCK) MAP_NONBLOCK, #endif #if defined(MAP_GROWSDOWN) MAP_GROWSDOWN, #endif #if defined(MAP_LOCKED) MAP_LOCKED, #endif #if defined(MAP_32BIT) && (defined(__x86_64__) || defined(__x86_64)) MAP_32BIT, #endif /* This will segv if no backing, so don't use it for now */ #if 0 && defined(MAP_NORESERVE) MAP_NORESERVE, #endif 0 }; void stress_set_mmap_bytes(const char *optarg) { set_mmap_bytes = true; 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, const size_t page_size) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += page_size) { if (!opt_do_run) break; for (j = 0; j < page_size; j++) if (*ptr++ != val++) return -1; val++; } return 0; } static void stress_mmap_set( uint8_t *buf, const size_t sz, const size_t page_size) { size_t i, j; uint8_t val = 0; uint8_t *ptr = buf; for (i = 0; i < sz; i += page_size) { if (!opt_do_run) break; for (j = 0; j < page_size; j++) *ptr++ = val++; val++; } } /* * stress_mmap_mprotect() * cycle through page settings on a region of mmap'd memory */ static void stress_mmap_mprotect(const char *name, void *addr, const size_t len) { if (opt_flags & OPT_FLAGS_MMAP_MPROTECT) { /* Cycle through potection */ if (mprotect(addr, len, PROT_NONE) < 0) pr_fail(stderr, "%s: mprotect set to PROT_NONE failed\n", name); if (mprotect(addr, len, PROT_READ) < 0) pr_fail(stderr, "%s: mprotect set to PROT_READ failed\n", name); if (mprotect(addr, len, PROT_WRITE) < 0) pr_fail(stderr, "%s: mprotect set to PROT_WRITE failed\n", name); if (mprotect(addr, len, PROT_EXEC) < 0) pr_fail(stderr, "%s: mprotect set to PROT_EXEC failed\n", name); if (mprotect(addr, len, PROT_READ | PROT_WRITE) < 0) pr_fail(stderr, "%s: mprotect set to PROT_READ | PROT_WRITE failed\n", name); } } /* * 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(); size_t sz, pages4k; #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; int no_mem_retries = 0; char filename[PATH_MAX]; #ifdef MAP_POPULATE flags |= MAP_POPULATE; #endif if (!set_mmap_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_mmap_bytes = MAX_MMAP_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_mmap_bytes = MIN_MMAP_BYTES; } sz = opt_mmap_bytes & ~(page_size - 1); pages4k = sz / page_size; /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); if (opt_flags & OPT_FLAGS_MMAP_FILE) { ssize_t ret, rc; char ch = '\0'; rc = stress_temp_dir_mk(name, pid, instance); if (rc < 0) return exit_status(-rc); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); (void)unlink(filename); (void)stress_temp_dir_rm(name, pid, instance); return rc; } (void)unlink(filename); if (lseek(fd, sz - sizeof(ch), SEEK_SET) < 0) { pr_fail_err(name, "lseek"); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return EXIT_FAILURE; } redo: ret = write(fd, &ch, sizeof(ch)); if (ret != sizeof(ch)) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; rc = exit_status(errno); pr_fail_err(name, "write"); (void)close(fd); (void)stress_temp_dir_rm(name, pid, instance); return rc; } flags &= ~(MAP_ANONYMOUS | MAP_PRIVATE); flags |= MAP_SHARED; } do { uint8_t mapped[pages4k]; uint8_t *mappings[pages4k]; size_t n; const int rnd = mwc32() % SIZEOF_ARRAY(mmap_flags); const int rnd_flag = mmap_flags[rnd]; if (no_mem_retries >= NO_MEM_RETRIES_MAX) { pr_err(stderr, "%s: gave up trying to mmap, no available memory\n", name); break; } if (!opt_do_run) break; buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, flags | rnd_flag, fd, 0); if (buf == MAP_FAILED) { /* Force MAP_POPULATE off, just in case */ #ifdef MAP_POPULATE flags &= ~MAP_POPULATE; #endif no_mem_retries++; if (no_mem_retries > 1) usleep(100000); 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(name, 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, page_size); if (opt_flags & OPT_FLAGS_VERIFY) { if (stress_mmap_check(buf, sz, page_size) < 0) pr_fail(stderr, "%s: mmap'd region of %zu bytes does " "not contain expected data\n", name, 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 = mwc64() % 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(name, mappings[page], page_size); (void)munmap(mappings[page], page_size); n--; break; } if (!opt_do_run) goto cleanup; } } (void)munmap(buf, sz); #ifdef MAP_FIXED /* * Step #2, map them back in random order */ for (n = pages4k; n; ) { uint64_t j, i = mwc64() % 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(mappings[page], page_size); (void)madvise_random(mappings[page], page_size); stress_mmap_mprotect(name, mappings[page], page_size); mapped[page] = PAGE_MAPPED; /* Ensure we can write to the mapped page */ stress_mmap_set(mappings[page], page_size, page_size); if (stress_mmap_check(mappings[page], page_size, page_size) < 0) pr_fail(stderr, "%s: mmap'd region of %zu bytes does " "not contain expected data\n", name, 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(name, mappings[n], page_size); (void)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.05.23/stress-fault.c0000664000175000017500000000722612702231255015060 0ustar kingking/* * Copyright (C) 2013-2016 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 ret, i = 0; const pid_t pid = getpid(); ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); do { char *ptr; int fd; fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { if ((errno == ENOSPC) || (errno == ENOMEM)) continue; /* Try again */ 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) { if (errno == ENOSPC) { (void)close(fd); continue; /* Try again */ } (void)close(fd); pr_err(stderr, "%s: posix_fallocate failed: errno=%d (%s)\n", name, errno, strerror(errno)); break; } #else { char buffer[1]; redo: if (opt_do_run && (write(fd, buffer, sizeof(buffer)) < 0)) { if ((errno == EAGAIN) || (errno == EINTR)) goto redo; if (errno == ENOSPC) { (void)close(fd); continue; } (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, "%s: page faults: minor: %lu, major: %lu\n", name, usage.ru_minflt, usage.ru_majflt); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-heapsort.c0000664000175000017500000001173112702231255015566 0ustar kingking/* * Copyright (C) 2016 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(STRESS_HEAPSORT) #include #include #include #include #include #include #include static uint64_t opt_heapsort_size = DEFAULT_HEAPSORT_SIZE; static bool set_heapsort_size = false; static volatile bool do_jmp = true; static sigjmp_buf jmp_env; /* * stress_heapsort_handler() * SIGALRM generic handler */ static void MLOCKED stress_heapsort_handler(int dummy) { (void)dummy; if (do_jmp) { do_jmp = false; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } } /* * stress_set_heapsort_size() * set heapsort size */ void stress_set_heapsort_size(const void *optarg) { set_heapsort_size = true; opt_heapsort_size = get_uint64_byte(optarg); check_range("heapsort-size", opt_heapsort_size, MIN_HEAPSORT_SIZE, MAX_HEAPSORT_SIZE); } /* * stress_heapsort_cmp_1() * heapsort comparison - sort on int32 values */ static int stress_heapsort_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_heapsort_cmp_1() * heapsort comparison - reverse sort on int32 values */ static int stress_heapsort_cmp_2(const void *p1, const void *p2) { return stress_heapsort_cmp_1(p2, p1); } /* * stress_heapsort_cmp_1() * heapsort comparison - sort on int8 values */ static int stress_heapsort_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_heapsort() * stress heapsort */ int stress_heapsort( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data, *ptr; size_t n, i; struct sigaction old_action; int ret; (void)instance; if (!set_heapsort_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_heapsort_size = MAX_HEAPSORT_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_heapsort_size = MIN_HEAPSORT_SIZE; } n = (size_t)opt_heapsort_size; if ((data = calloc(n, sizeof(int32_t))) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_FAILURE; } if (stress_sighandler(name, SIGALRM, stress_heapsort_handler, &old_action) < 0) { free(data); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); if (ret) { /* * We return here if SIGALRM jmp'd back */ (void)stress_sigrestore(name, SIGALRM, &old_action); goto tidy; } /* This is expensive, do it once */ for (ptr = data, i = 0; i < n; i++) *ptr++ = mwc32(); do { /* Sort "random" data */ heapsort(data, n, sizeof(uint32_t), stress_heapsort_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, "%s: sort error " "detected, incorrect ordering " "found\n", name); break; } } } if (!opt_do_run) break; /* Reverse sort */ heapsort(data, n, sizeof(uint32_t), stress_heapsort_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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; /* And re-order by byte compare */ heapsort(data, n * 4, sizeof(uint8_t), stress_heapsort_cmp_3); /* Reverse sort this again */ heapsort(data, n, sizeof(uint32_t), stress_heapsort_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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); do_jmp = false; (void)stress_sigrestore(name, SIGALRM, &old_action); tidy: free(data); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/log.c0000664000175000017500000000702412702231255013201 0ustar kingking/* * Copyright (C) 2013-2016 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 uint16_t abort_fails; /* count of failures */ static bool abort_msg_emitted; static FILE *log_file = NULL; /* * pr_yaml() * print to yaml file if it is open */ int pr_yaml(FILE *fp, const char *const fmt, ...) { va_list ap; int ret = 0; va_start(ap, fmt); if (fp) ret = vfprintf(fp, fmt, ap); va_end(ap); return ret; } /* * pr_closelog() * log closing, performed via exit() */ static void pr_closelog(void) { if (log_file) { fclose(log_file); log_file = NULL; } } /* * pr_openlog() * optional pr logging to a file */ void pr_openlog(const char *filename) { if (!filename) return; log_file = fopen(filename, "w"); if (!log_file) { pr_err(stderr, "Cannot open log file %s\n", filename); return; } atexit(pr_closelog); } /* * pr_msg() * print some debug or info messages */ int pr_msg( FILE *fp, const uint64_t flag, const char *const fmt, ...) { va_list ap; int ret = 0; va_start(ap, fmt); if ((flag & PR_FAIL) || (opt_flags & flag)) { char buf[4096]; const char *type = ""; if (flag & PR_ERROR) type = "error:"; if (flag & PR_DEBUG) type = "debug:"; if (flag & PR_INFO) type = "info: "; if (flag & PR_FAIL) type = "fail: "; if (opt_flags & OPT_FLAGS_LOG_BRIEF) { ret = vfprintf(fp, fmt, ap); } else { int n = snprintf(buf, sizeof(buf), "%s [%i] ", type, getpid()); ret = vsnprintf(buf + n, sizeof(buf) - n, fmt, ap); fprintf(fp, "%s: %s", app_name, 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; pr_msg(fp, PR_INFO, "%d failures " "reached, aborting stress " "process\n", ABORT_FAILURES); fflush(fp); } } } /* Log messages to log file if --log-file specified */ if (log_file) { fprintf(log_file, "%s: %s", app_name, buf); fflush(log_file); } /* Log messages if syslog requested, don't log DEBUG */ if ((opt_flags & OPT_FLAGS_SYSLOG) && (!(flag & PR_DEBUG))) { syslog(LOG_INFO, "%s", buf); } } va_end(ap); return ret; } /* * pr_msg_fail() * print failure message with errno */ void pr_msg_fail( const uint64_t flag, const char *name, const char *what, const int err) { pr_msg(stderr, flag, "%s: %s failed, errno=%d (%s)\n", name, what, err, strerror(err)); } stress-ng-0.05.23/stress-kill.c0000664000175000017500000000446012702231255014675 0ustar kingking/* * Copyright (C) 2013-2016 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) { const pid_t pid = getpid(); (void)instance; if (stress_sighandler(name, SIGUSR1, SIG_IGN, NULL) < 0) return EXIT_FAILURE; do { int ret; ret = kill(pid, SIGUSR1); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: kill failed: errno=%d (%s)\n", name, errno, strerror(errno)); /* Zero signal can be used to see if process exists */ ret = kill(pid, 0); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: kill failed: errno=%d (%s)\n", name, errno, strerror(errno)); /* * Zero signal can be used to see if process exists, * -1 pid means signal sent to every process caller has * permission to send to */ ret = kill(-1, 0); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: kill 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.05.23/stress-zlib.c0000664000175000017500000002170612702231255014704 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_ZLIB) #include #include #include #include #include #include #include #include "zlib.h" #define DATA_SIZE (65536) /* Must be a multiple of 8 bytes */ typedef void (*stress_rand_data_func)(uint32_t *data, const int size); /* * stress_rand_data_binary() * fill buffer with random binary data */ static void stress_rand_data_binary(uint32_t *data, const int size) { const int n = size / sizeof(uint32_t); register int i; for (i = 0; i < n; i++, data++) *data = mwc32(); } /* * stress_rand_data_text() * fill buffer with random ASCII text */ static void stress_rand_data_text(uint32_t *data, const int size) { stress_strnrnd((char *)data, size); } /* * stress_rand_data_01() * fill buffer with random ASCII 0 or 1 */ static void stress_rand_data_01(uint32_t *data, const int size) { unsigned char *ptr = (unsigned char *)data; register int i; for (i = 0; i < size; i += 8, ptr += 8) { uint8_t v = mwc8(); *(ptr + 0) = '0' + (v & 1); v >>= 1; *(ptr + 1) = '0' + (v & 1); v >>= 1; *(ptr + 2) = '0' + (v & 1); v >>= 1; *(ptr + 3) = '0' + (v & 1); v >>= 1; *(ptr + 4) = '0' + (v & 1); v >>= 1; *(ptr + 5) = '0' + (v & 1); v >>= 1; *(ptr + 6) = '0' + (v & 1); v >>= 1; *(ptr + 7) = '0' + (v & 1); } } /* * stress_rand_data_digits() * fill buffer with random ASCII '0' .. '9' */ static void stress_rand_data_digits(uint32_t *data, const int size) { unsigned char *ptr = (unsigned char *)data; register int i; for (i = 0; i < size; i++, ptr++) *ptr = '0' + (mwc32() % 10); } /* * stress_rand_data_00_ff() * fill buffer with random 0x00 or 0xff */ static void stress_rand_data_00_ff(uint32_t *data, const int size) { unsigned char *ptr = (unsigned char *)data; register int i; for (i = 0; i < size; i += 8, ptr += 8) { uint8_t v = mwc8(); *(ptr + 0) = (v & 1) ? 0x00 : 0xff; *(ptr + 1) = (v & 2) ? 0x00 : 0xff; *(ptr + 2) = (v & 4) ? 0x00 : 0xff; *(ptr + 3) = (v & 8) ? 0x00 : 0xff; *(ptr + 4) = (v & 16) ? 0x00 : 0xff; *(ptr + 5) = (v & 32) ? 0x00 : 0xff; *(ptr + 6) = (v & 64) ? 0x00 : 0xff; *(ptr + 7) = (v & 128) ? 0x00 : 0xff; } } /* * stress_rand_data_nybble() * fill buffer with 0x00..0x0f */ static void stress_rand_data_nybble(uint32_t *data, const int size) { unsigned char *ptr = (unsigned char *)data; register int i; for (i = 0; i < size; i += 8, ptr += 8) { uint32_t v = mwc32(); *(ptr + 0) = v & 0xf; v >>= 4; *(ptr + 1) = v & 0xf; v >>= 4; *(ptr + 2) = v & 0xf; v >>= 4; *(ptr + 3) = v & 0xf; v >>= 4; *(ptr + 4) = v & 0xf; v >>= 4; *(ptr + 5) = v & 0xf; v >>= 4; *(ptr + 6) = v & 0xf; v >>= 4; *(ptr + 7) = v & 0xf; } } /* * stress_rand_data_rarely_1() * fill buffer with data that is 1 in every 32 bits 1 */ static void stress_rand_data_rarely_1(uint32_t *data, const int size) { const int n = size / sizeof(uint32_t); register int i; for (i = 0; i < n; i++, data++) *data = 1 << (mwc32() & 0x1f); } /* * stress_rand_data_rarely_0() * fill buffer with data that is 1 in every 32 bits 0 */ static void stress_rand_data_rarely_0(uint32_t *data, const int size) { const int n = size / sizeof(uint32_t); register int i; for (i = 0; i < n; i++, data++) *data = ~(1 << (mwc32() & 0x1f)); } static const stress_rand_data_func rand_data_funcs[] = { stress_rand_data_rarely_1, stress_rand_data_rarely_0, stress_rand_data_binary, stress_rand_data_text, stress_rand_data_01, stress_rand_data_digits, stress_rand_data_00_ff, stress_rand_data_nybble }; /* * stress_zlib_err() * turn a zlib error to something human readable */ const char *stress_zlib_err(const int zlib_err) { static char buf[1024]; switch (zlib_err) { case Z_OK: return "no error"; case Z_ERRNO: snprintf(buf, sizeof(buf), "system error, errno=%d (%s)\n", errno, strerror(errno)); return buf; case Z_STREAM_ERROR: return "invalid compression level"; case Z_DATA_ERROR: return "invalid or incomplete deflate data"; case Z_MEM_ERROR: return "out of memory"; case Z_VERSION_ERROR: return "zlib version mismatch"; default: snprintf(buf, sizeof(buf), "unknown zlib error %d\n", zlib_err); return buf; } } /* * stress_zlib_inflate() * inflate compressed data out of the read * end of a pipe fd */ int stress_zlib_inflate(const char *name, const int fd) { int ret; z_stream stream_inf; stream_inf.zalloc = Z_NULL; stream_inf.zfree = Z_NULL; stream_inf.opaque = Z_NULL; ret = inflateInit(&stream_inf); if (ret != Z_OK) { pr_fail(stderr, "%s: zlib inflateInit error: %s\n", name, stress_zlib_err(ret)); return EXIT_FAILURE; } for (;;) { ssize_t sz; unsigned char in[DATA_SIZE]; sz = read(fd, in, DATA_SIZE); if (sz <= 0) break; stream_inf.avail_in = sz; stream_inf.next_in = in; do { unsigned char out[DATA_SIZE]; stream_inf.avail_out = DATA_SIZE; stream_inf.next_out = out; ret = inflate(&stream_inf, Z_NO_FLUSH); } while ((ret == Z_OK) && (stream_inf.avail_out == 0)); } (void)inflateEnd(&stream_inf); return ((ret == Z_OK) || (ret == Z_STREAM_END)) ? EXIT_SUCCESS : EXIT_FAILURE; } /* * stress_zlib_deflate() * compress random data and write it down the * write end of a pipe fd */ int stress_zlib_deflate( const char *name, const int fd, const uint32_t instance, const uint64_t max_ops, uint64_t *counter) { int ret; bool do_run; z_stream stream_def; uint64_t bytes_in = 0, bytes_out = 0; stream_def.zalloc = Z_NULL; stream_def.zfree = Z_NULL; stream_def.opaque = Z_NULL; ret = deflateInit(&stream_def, Z_BEST_COMPRESSION); if (ret != Z_OK) { pr_fail(stderr, "%s: zlib deflateInit error: %s\n", name, stress_zlib_err(ret)); return EXIT_FAILURE; } do { uint32_t in[DATA_SIZE / sizeof(uint32_t)]; rand_data_funcs[mwc32() % SIZEOF_ARRAY(rand_data_funcs)](in, DATA_SIZE); stream_def.avail_in = DATA_SIZE; stream_def.next_in = (unsigned char *)in; do_run = opt_do_run && (!max_ops || *counter < max_ops); bytes_in += DATA_SIZE; do { unsigned char out[DATA_SIZE]; int def_size, rc; int flush = do_run ? Z_NO_FLUSH : Z_FINISH; stream_def.avail_out = DATA_SIZE; stream_def.next_out = out; rc = deflate(&stream_def, flush); if ((rc != Z_OK) && (rc != Z_STREAM_END)) { pr_fail(stderr, "%s: zlib deflate error: %s\n", name, stress_zlib_err(rc)); do_run = false; ret = EXIT_FAILURE; break; } def_size = DATA_SIZE - stream_def.avail_out; bytes_out += def_size; if (write(fd, out, def_size) != def_size) { if ((errno != EINTR) && (errno != EPIPE)) { ret = EXIT_FAILURE; pr_fail(stderr, "%s: write error: errno=%d (%s)\n", name, errno, strerror(errno)); } do_run = false; break; } (*counter)++; } while (do_run && stream_def.avail_out == 0); } while (do_run); pr_inf(stderr, "%s: instance %" PRIu32 ": compression ratio: %5.2f%%\n", name, instance, 100.0 * (double)bytes_out / (double)bytes_in); (void)deflateEnd(&stream_def); return ret; } /* * stress_zlib() * stress cpu with compression and decompression */ int stress_zlib( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int ret, fds[2], status; pid_t pid; if (pipe(fds) < 0) { pr_err(stderr, "%s: pipe failed, errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { (void)close(fds[0]); (void)close(fds[1]); pr_err(stderr, "%s: fork failed, errno=%d (%s)\n", name, errno, strerror(errno)); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); (void)close(fds[1]); ret = stress_zlib_inflate(name, fds[0]); (void)close(fds[0]); exit(ret); } else { (void)close(fds[0]); ret = stress_zlib_deflate(name, fds[1], instance, max_ops, counter); (void)close(fds[1]); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); return ret; } #endif stress-ng-0.05.23/stress-zombie.c0000664000175000017500000001061712702231255015230 0ustar kingking/* * Copyright (C) 2013-2016 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_zombie_max = DEFAULT_ZOMBIES; static bool set_zombie_max = false; typedef struct zombie { pid_t pid; struct zombie *next; } zombie_t; typedef struct { zombie_t *head; /* Head of zombie procs list */ zombie_t *tail; /* Tail of zombie procs list */ zombie_t *free; /* List of free'd zombies */ uint64_t length; /* Length of list */ } zombie_list_t; static zombie_list_t zombies; /* * stress_zombie_new() * allocate a new zombie, add to end of list */ static zombie_t *stress_zombie_new(void) { zombie_t *new; if (zombies.free) { /* Pop an old one off the free list */ new = zombies.free; zombies.free = new->next; new->next = NULL; } else { new = calloc(1, sizeof(*new)); if (!new) return NULL; } if (zombies.head) zombies.tail->next = new; else zombies.head = new; zombies.tail = new; zombies.length++; return new; } /* * stress_zombie_head_remove * reap a zombie and remove a zombie from head of list, put it onto * the free zombie list */ void stress_zombie_head_remove(void) { if (zombies.head) { int status; (void)waitpid(zombies.head->pid, &status, 0); zombie_t *head = zombies.head; if (zombies.tail == zombies.head) { zombies.tail = NULL; zombies.head = NULL; } else { zombies.head = head->next; } /* Shove it on the free list */ head->next = zombies.free; zombies.free = head; zombies.length--; } } /* * stress_zombie_free() * free the zombies off the zombie free lists */ void stress_zombie_free(void) { while (zombies.head) { zombie_t *next = zombies.head->next; free(zombies.head); zombies.head = next; } while (zombies.free) { zombie_t *next = zombies.free->next; free(zombies.free); zombies.free = next; } } /* * stress_set_zombie_max() * set maximum number of zombies allowed */ void stress_set_zombie_max(const char *optarg) { set_zombie_max = true; opt_zombie_max = get_uint64_byte(optarg); check_range("zombie-max", opt_zombie_max, MIN_ZOMBIES, MAX_ZOMBIES); } /* * stress_zombie() * stress by zombieing and exiting */ int stress_zombie( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint64_t max_zombies = 0; (void)instance; if (!set_zombie_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_zombie_max = MAX_ZOMBIES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_zombie_max = MIN_ZOMBIES; } do { if (zombies.length < opt_zombie_max) { zombie_t *zombie; zombie = stress_zombie_new(); if (!zombie) break; zombie->pid = fork(); if (zombie->pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); stress_zombie_free(); _exit(0); } if (zombie->pid == -1) { /* Reached max forks? .. then reap */ stress_zombie_head_remove(); continue; } setpgid(zombie->pid, pgrp); if (max_zombies < zombies.length) max_zombies = zombies.length; (*counter)++; } else { stress_zombie_head_remove(); } } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_inf(stderr, "%s: created a maximum of %" PRIu64 " zombies\n", name, max_zombies); /* And reap */ while (zombies.head) { stress_zombie_head_remove(); } /* And free */ stress_zombie_free(); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-tsearch.c0000664000175000017500000000676412702231255015404 0ustar kingking/* * Copyright (C) 2013-2016 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; static bool set_tsearch_size = false; /* * stress_set_tsearch_size() * set tsearch size from given option string */ void stress_set_tsearch_size(const char *optarg) { set_tsearch_size = true; 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; size_t i, n; (void)instance; if (!set_tsearch_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_tsearch_size = MAX_TSEARCH_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_tsearch_size = MIN_TSEARCH_SIZE; } n = (size_t)opt_tsearch_size; if ((data = malloc(sizeof(int32_t) * n)) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_FAILURE; } do { void *root = NULL; /* Step #1, populate tree */ for (i = 0; i < n; i++) { data[i] = ((mwc32() & 0xfff) << 20) ^ i; if (tsearch(&data[i], &root, cmp) == NULL) { size_t j; pr_err(stderr, "%s: cannot allocate new " "tree node\n", name); 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, "%s: element %zu " "could not be found\n", name, i); else { int32_t *val; val = *result; if (*val != data[i]) pr_fail(stderr, "%s: element " "%zu found %" PRIu32 ", expecting %" PRIu32 "\n", name, 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, "%s: element %zu could not " "be found\n", name, i); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); abort: free(data); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-exec.c0000664000175000017500000001006412702231255014663 0ustar kingking/* * Copyright (C) 2013-2016 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_EXEC) static uint64_t opt_exec_max = DEFAULT_EXECS; static bool set_exec_max = false; /* * stress_set_exec_max() * set maximum number of forks allowed */ void stress_set_exec_max(const char *optarg) { set_exec_max = true; opt_exec_max = get_uint64_byte(optarg); check_range("exec-max", opt_exec_max, MIN_EXECS, MAX_EXECS); } /* * stress_exec() * stress by forking and exec'ing */ int stress_exec( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_FORKS]; char path[PATH_MAX + 1]; ssize_t len; uint64_t exec_fails = 0, exec_calls = 0; char *argv_new[] = { NULL, "--exec-exit", NULL }; char *env_new[] = { NULL }; (void)instance; /* * Don't want to run this when running as root as * this could allow somebody to try and run another * executable as root. */ if (geteuid() == 0) { pr_inf(stderr, "%s: running as root, won't run test.\n", name); return EXIT_FAILURE; } /* * Determine our own self as the executable, e.g. run stress-ng */ len = readlink("/proc/self/exe", path, sizeof(path)); if (len < 0 || len > PATH_MAX) { pr_fail(stderr, "%s: readlink on /proc/self/exe failed\n", name); return EXIT_FAILURE; } path[len] = '\0'; argv_new[0] = path; do { unsigned int i; memset(pids, 0, sizeof(pids)); for (i = 0; i < opt_exec_max; i++) { pids[i] = fork(); if (pids[i] == 0) { int ret, fd_out, fd_in; setpgid(0, pgrp); stress_parent_died_alarm(); if ((fd_out = open("/dev/null", O_WRONLY)) < 0) { pr_fail(stderr, "%s: child open on /dev/null failed\n", name); _exit(EXIT_FAILURE); } if ((fd_in = open("/dev/zero", O_RDONLY)) < 0) { pr_fail(stderr, "%s: child open on /dev/zero failed\n", name); (void)close(fd_out); _exit(EXIT_FAILURE); } dup2(fd_out, STDOUT_FILENO); dup2(fd_out, STDERR_FILENO); dup2(fd_in, STDIN_FILENO); (void)close(fd_out); (void)close(fd_in); ret = execve(path, argv_new, env_new); /* Child, immediately exit */ _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } if (pids[i] > -1) setpgid(pids[i], pgrp); if (!opt_do_run) break; } for (i = 0; i < opt_exec_max; i++) { if (pids[i] > 0) { int status; /* Parent, wait for child */ (void)waitpid(pids[i], &status, 0); exec_calls++; (*counter)++; if (WEXITSTATUS(status) != EXIT_SUCCESS) exec_fails++; } } for (i = 0; i < opt_exec_max; i++) { if ((pids[i] < 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: fork failed\n", name); } } } while (opt_do_run && (!max_ops || *counter < max_ops)); if ((exec_fails > 0) && (opt_flags & OPT_FLAGS_VERIFY)) { pr_fail(stderr, "%s: %" PRIu64 " execs failed (%.2f%%)\n", name, exec_fails, (double)exec_fails * 100.0 / (double)(exec_calls)); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-splice.c0000664000175000017500000000544312702231255015223 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SPLICE) #include #include #include #include #include #include #include static size_t opt_splice_bytes = DEFAULT_SPLICE_BYTES; static bool set_splice_bytes = false; void stress_set_splice_bytes(const char *optarg) { set_splice_bytes = true; 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]; if (!set_splice_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_splice_bytes = MAX_SPLICE_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_splice_bytes = MIN_SPLICE_BYTES; } (void)instance; if (pipe(fds) < 0) { pr_fail_err(name, "pipe"); return EXIT_FAILURE; } if ((fd_in = open("/dev/zero", O_RDONLY)) < 0) { (void)close(fds[0]); (void)close(fds[1]); pr_fail_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_fail_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.05.23/stress-mmapmany.c0000664000175000017500000000650012702231255015556 0ustar kingking/* * Copyright (C) 2013-2016 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 MMAP_MAX (256*1024) /* * stress_mmapmany() * stress mmap with many pages being mapped */ int stress_mmapmany( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t page_size = stress_get_pagesize(); pid_t pid; size_t max = sysconf(_SC_MAPPED_FILES); max = STRESS_MAXIMUM(max, MMAP_MAX); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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) { uint8_t *mappings[max]; size_t i, n; setpgid(0, pgrp); stress_parent_died_alarm(); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { for (n = 0; opt_do_run && (n < max); n++) { if (!opt_do_run || (max_ops && *counter >= max_ops)) break; mappings[n] = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mappings[n] == MAP_FAILED) break; if (munmap(mappings[n] + page_size, page_size) < 0) break; (*counter)++; } for (i = 0; i < n; i++) { munmap(mappings[i], page_size); munmap(mappings[i] + page_size, page_size); munmap(mappings[i] + page_size + page_size, page_size); } } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-xattr.c0000664000175000017500000001001112702231255015071 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_XATTR) #include #include #include #include #include #include #include #include #include #include /* * stress_xattr * stress the xattr operations */ int stress_xattr( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid = getpid(); int ret, fd, rc = EXIT_FAILURE; char filename[PATH_MAX]; ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto out; } (void)unlink(filename); do { int i, j; int ret; char name[32]; char value[32]; ssize_t sz; char *buffer; for (i = 0; i < 4096; i++) { snprintf(name, sizeof(name), "user.var_%d", i); snprintf(value, sizeof(value), "orig-value-%i", i); ret = fsetxattr(fd, name, value, strlen(value), XATTR_CREATE); if (ret < 0) { if (errno == ENOTSUP) { pr_inf(stderr, "%s stressor will be " "skipped, filesystem does not " "support xattr.\n", name); } if (errno == ENOSPC || errno == EDQUOT) break; pr_fail_err(name, "fsetxattr"); goto out_close; } } for (j = 0; j < i; j++) { snprintf(name, sizeof(name), "user.var_%d", j); snprintf(value, sizeof(value), "value-%i", j); ret = fsetxattr(fd, name, value, strlen(value), XATTR_REPLACE); if (ret < 0) { if (errno == ENOSPC || errno == EDQUOT) break; pr_fail_err(name, "fsetxattr"); goto out_close; } } for (j = 0; j < i; j++) { char tmp[sizeof(value)]; snprintf(name, sizeof(name), "user.var_%d", j); snprintf(value, sizeof(value), "value-%i", j); ret = fgetxattr(fd, name, tmp, sizeof(tmp)); if (ret < 0) { pr_fail_err(name, "fgetxattr"); goto out_close; } if (strncmp(value, tmp, ret)) { pr_fail(stderr, "%s: fgetxattr values " "different %.*s vs %.*s\n", name, ret, value, ret, tmp); goto out_close; } } /* Determine how large a buffer we required... */ sz = flistxattr(fd, NULL, 0); if (sz < 0) { pr_fail_err(name, "fremovexattr"); goto out_close; } buffer = malloc(sz); if (buffer) { /* ...and fetch */ sz = flistxattr(fd, buffer, sz); free(buffer); if (sz < 0) { pr_fail_err(name, "fremovexattr"); goto out_close; } } for (j = 0; j < i; j++) { snprintf(name, sizeof(name), "user.var_%d", j); ret = fremovexattr(fd, name); if (ret < 0) { pr_fail_err(name, "fremovexattr"); goto out_close; } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; out_close: (void)close(fd); out: (void)stress_temp_dir_rm(name, pid, instance); return rc; } #endif stress-ng-0.05.23/stress-mergesort.c0000664000175000017500000001200412702231255015742 0ustar kingking/* * Copyright (C) 2016 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(STRESS_MERGESORT) #include #include #include #include #include #include #include static uint64_t opt_mergesort_size = DEFAULT_MERGESORT_SIZE; static bool set_mergesort_size = false; static volatile bool do_jmp = true; static sigjmp_buf jmp_env; /* * stress_mergesort_handler() * SIGALRM generic handler */ static void MLOCKED stress_mergesort_handler(int dummy) { (void)dummy; if (do_jmp) { do_jmp = false; siglongjmp(jmp_env, 1); /* Ugly, bounce back */ } } /* * stress_set_mergesort_size() * set mergesort size */ void stress_set_mergesort_size(const void *optarg) { set_mergesort_size = true; opt_mergesort_size = get_uint64_byte(optarg); check_range("mergesort-size", opt_mergesort_size, MIN_MERGESORT_SIZE, MAX_MERGESORT_SIZE); } /* * stress_mergesort_cmp_1() * mergesort comparison - sort on int32 values */ static int stress_mergesort_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_mergesort_cmp_1() * mergesort comparison - reverse sort on int32 values */ static int stress_mergesort_cmp_2(const void *p1, const void *p2) { return stress_mergesort_cmp_1(p2, p1); } /* * stress_mergesort_cmp_1() * mergesort comparison - sort on int8 values */ static int stress_mergesort_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_mergesort() * stress mergesort */ int stress_mergesort( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int32_t *data, *ptr; size_t n, i; struct sigaction old_action; int ret; (void)instance; if (!set_mergesort_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_mergesort_size = MAX_MERGESORT_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_mergesort_size = MIN_MERGESORT_SIZE; } n = (size_t)opt_mergesort_size; if ((data = calloc(n, sizeof(int32_t))) == NULL) { pr_fail_dbg(name, "malloc"); return EXIT_FAILURE; } if (stress_sighandler(name, SIGALRM, stress_mergesort_handler, &old_action) < 0) { free(data); return EXIT_FAILURE; } ret = sigsetjmp(jmp_env, 1); if (ret) { /* * We return here if SIGALRM jmp'd back */ (void)stress_sigrestore(name, SIGALRM, &old_action); goto tidy; } /* This is expensive, do it once */ for (ptr = data, i = 0; i < n; i++) *ptr++ = mwc32(); do { /* Sort "random" data */ mergesort(data, n, sizeof(uint32_t), stress_mergesort_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, "%s: sort error " "detected, incorrect ordering " "found\n", name); break; } } } if (!opt_do_run) break; /* Reverse sort */ mergesort(data, n, sizeof(uint32_t), stress_mergesort_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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; /* And re-order by byte compare */ mergesort(data, n * 4, sizeof(uint8_t), stress_mergesort_cmp_3); /* Reverse sort this again */ mergesort(data, n, sizeof(uint32_t), stress_mergesort_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, "%s: reverse sort " "error detected, incorrect " "ordering found\n", name); break; } } } if (!opt_do_run) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); do_jmp = false; (void)stress_sigrestore(name, SIGALRM, &old_action); tidy: free(data); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-timerfd.c0000664000175000017500000001010512702231255015365 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_TIMERFD) #include #include #include #include #include #include static volatile uint64_t timerfd_counter = 0; static int timerfd; static uint64_t opt_timerfd_freq = DEFAULT_TIMERFD_FREQ; static bool set_timerfd_freq = false; static double rate_ns; /* * stress_set_timerfd_freq() * set timer frequency from given option */ void stress_set_timerfd_freq(const char *optarg) { set_timerfd_freq = true; opt_timerfd_freq = get_uint64(optarg); check_range("timerfd-freq", opt_timerfd_freq, MIN_TIMERFD_FREQ, MAX_TIMERFD_FREQ); } /* * stress_timerfd_set() * set timerfd, ensure it is never zero */ static void stress_timerfd_set(struct itimerspec *timer) { double rate; if (opt_flags & OPT_FLAGS_TIMERFD_RAND) { /* Mix in some random variation */ double r = ((double)(mwc32() % 10000) - 5000.0) / 40000.0; rate = rate_ns + (rate_ns * r); } else { rate = rate_ns; } timer->it_value.tv_sec = (long long int)rate / 1000000000; timer->it_value.tv_nsec = (long long int)rate % 1000000000; if (timer->it_value.tv_sec == 0 && timer->it_value.tv_nsec < 1) timer->it_value.tv_nsec = 1; timer->it_interval.tv_sec = timer->it_value.tv_sec; timer->it_interval.tv_nsec = timer->it_value.tv_nsec; } /* * stress_timerfd * stress timerfd */ int stress_timerfd( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct itimerspec timer; (void)instance; if (!set_timerfd_freq) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_timerfd_freq = MAX_TIMERFD_FREQ; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_timerfd_freq = MIN_TIMERFD_FREQ; } rate_ns = opt_timerfd_freq ? 1000000000 / opt_timerfd_freq : 1000000000; timerfd = timerfd_create(CLOCK_REALTIME, 0); if (timerfd < 0) { pr_fail_err(name, "timerfd_create"); (void)close(timerfd); return EXIT_FAILURE; } stress_timerfd_set(&timer); if (timerfd_settime(timerfd, 0, &timer, NULL) < 0) { pr_fail_err(name, "timer_settime"); (void)close(timerfd); return EXIT_FAILURE; } do { int ret; uint64_t exp; struct itimerspec value; struct timeval timeout; fd_set rdfs; FD_ZERO(&rdfs); FD_SET(timerfd, &rdfs); timeout.tv_sec = 0; timeout.tv_usec = 500000; if (!opt_do_run) break; ret = select(timerfd + 1, &rdfs, NULL, NULL, &timeout); if (ret < 0) { if (errno == EINTR) continue; pr_fail_err(name, "select"); break; } if (ret < 1) continue; /* Timeout */ ret = read(timerfd, &exp, sizeof exp); if (ret < 0) { pr_fail_err(name, "timerfd read"); break; } if (timerfd_gettime(timerfd, &value) < 0) { pr_fail_err(name, "timerfd_gettime"); break; } if (opt_flags & OPT_FLAGS_TIMERFD_RAND) { stress_timerfd_set(&timer); if (timerfd_settime(timerfd, 0, &timer, NULL) < 0) { pr_fail_err(name, "timer_settime"); break; } } (*counter)++; } while (opt_do_run && (!max_ops || timerfd_counter < max_ops)); (void)close(timerfd); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-stream.c0000664000175000017500000001602712702231255015237 0ustar kingking/* * Copyright (C) 2016 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. * * This stressor is loosely based on the STREAM Sustainable * Memory Bandwidth In High Performance Computers tool. * https://www.cs.virginia.edu/stream/ * https://www.cs.virginia.edu/stream/FTP/Code/stream.c * * This is loosely based on a variant of the STREAM benchmark code, * so DO NOT submit results based on this as it is intended to * stress memory and compute and NOT intended for STREAM accurate * tuned or non-tuned benchmarking whatsoever. I believe this * conforms to section 3a, 3b of the original License. * */ #define _GNU_SOURCE #include #include #include #include #include "stress-ng.h" static uint64_t opt_stream_L3_size = DEFAULT_STREAM_L3_SIZE; static bool set_stream_L3_size = false; void stress_set_stream_L3_size(const char *optarg) { set_stream_L3_size = true; opt_stream_L3_size = get_uint64_byte(optarg); check_range("stream-L3-size", opt_stream_L3_size, MIN_STREAM_L3_SIZE, MAX_STREAM_L3_SIZE); } static inline void OPTIMIZE3 stress_stream_copy( double *RESTRICT c, const double *RESTRICT a, const uint64_t n) { register uint64_t i; for (i = 0; i < n; i++) c[i] = a[i]; } static inline void OPTIMIZE3 stress_stream_scale( double *RESTRICT b, const double *RESTRICT c, const double q, const uint64_t n) { register uint64_t i; for (i = 0; i < n; i++) b[i] = q * c[i]; } static inline void OPTIMIZE3 stress_stream_add( const double *RESTRICT a, const double *RESTRICT b, double *RESTRICT c, const uint64_t n) { register uint64_t i; for (i = 0; i < n; i++) c[i] = a[i] + b[i]; } static inline void OPTIMIZE3 stress_stream_triad( double *RESTRICT a, const double *RESTRICT b, const double *RESTRICT c, const double q, const uint64_t n) { register uint64_t i; for (i = 0; i < n; i++) a[i] = b[i] + (c[i] * q); } static void stress_stream_init_data( double *RESTRICT data, const uint64_t n) { uint64_t i; for (i = 0; i < n; i++) data[i] = (double)mwc32() / (double)mwc64(); } static inline void *stress_stream_mmap(const char *name, uint64_t sz) { void *ptr; ptr = mmap(NULL, (size_t)sz, PROT_READ | PROT_WRITE, #if defined(MAP_POPULATE) MAP_POPULATE | #endif MAP_SHARED | MAP_ANONYMOUS, -1, 0); /* Coverity Scan believes NULL can be returned, doh */ if (!ptr || (ptr == MAP_FAILED)) { pr_err(stderr, "%s: cannot allocate %" PRIu64 " bytes\n", name, sz); ptr = MAP_FAILED; } return ptr; } static inline uint64_t stream_L3_size( const char *name, const uint32_t instance) { uint64_t cache_size = MEM_CACHE_SIZE; #if defined(__linux__) cpus_t *cpu_caches = NULL; cpu_cache_t *cache = NULL; uint16_t max_cache_level; cpu_caches = get_all_cpu_cache_details(); if (!cpu_caches) { if (!instance) pr_inf(stderr, "%s: using built-in defaults as unable to " "determine cache details\n", name); return cache_size; } max_cache_level = get_max_cache_level(cpu_caches); if ((max_cache_level > 0) && (max_cache_level < 3) && (!instance)) pr_inf(stderr, "%s: no L3 cache, using L%" PRIu16 " size instead\n", name, max_cache_level); cache = get_cpu_cache(cpu_caches, max_cache_level); if (!cache) { if (!instance) pr_inf(stderr, "%s: using built-in defaults as no suitable " "cache found\n", name); free_cpu_caches(cpu_caches); return cache_size; } if (!cache->size) { if (!instance) pr_inf(stderr, "%s: using built-in defaults as unable to " "determine cache size\n", name); free_cpu_caches(cpu_caches); return cache_size; } cache_size = cache->size; free_cpu_caches(cpu_caches); #else if (!instance) pr_inf(stderr, "%s: using built-in defaults as unable to " "determine cache details\n", name); #endif return cache_size; } /* * stress_stream() * stress cache/memory/CPU with stream stressors */ int stress_stream( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int rc = EXIT_FAILURE; double *a, *b, *c; const double q = 3.0; double mb_rate, mb, fp_rate, fp, t1, t2, dt; uint64_t L3, sz, n; bool guess = false; L3 = (set_stream_L3_size) ? opt_stream_L3_size : stream_L3_size(name, instance); /* Have to take a hunch and badly guess size */ if (!L3) { guess = true; L3 = stress_get_processors_configured() * DEFAULT_STREAM_L3_SIZE; } if (instance == 0) { pr_inf(stderr, "%s: stressor loosely based on a variant of the " "STREAM benchmark code\n", name); pr_inf(stderr, "%s: do NOT submit any of these results " "to the STREAM benchmark results\n", name); if (guess) { pr_inf(stderr, "%s: cannot determine CPU L3 cache size, " "defaulting to %" PRIu64 "K\n", name, L3 / 1024); } else { pr_inf(stderr, "%s: Using CPU cache size of %" PRIu64 "K\n", name, L3 / 1024); } } /* ..and shared amongst all the STREAM stressor instances */ L3 /= stressor_instances(STRESS_STREAM); /* * Each array must be at least 4 x the * size of the L3 cache */ sz = (L3 * 4); n = sz / sizeof(double); a = stress_stream_mmap(name, sz); if (a == MAP_FAILED) goto err_a; b = stress_stream_mmap(name, sz); if (b == MAP_FAILED) goto err_b; c = stress_stream_mmap(name, sz); if (c == MAP_FAILED) goto err_c; stress_stream_init_data(a, n); stress_stream_init_data(b, n); stress_stream_init_data(c, n); t1 = time_now(); do { stress_stream_copy(c, a, n); stress_stream_scale(b, c, q, n); stress_stream_add(c, b, a, n); stress_stream_triad(a, b, c, q, n); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); t2 = time_now(); mb = ((double)((*counter) * 10) * (double)sz) / (double)MB; fp = ((double)((*counter) * 4) * (double)sz) / (double)MB; dt = t2 - t1; if (dt >= 4.5) { mb_rate = mb / (dt); fp_rate = fp / (dt); pr_inf(stderr, "%s: memory rate: %.2f MB/sec, %.2f Mflop/sec" " (instance %" PRIu32 ")\n", name, mb_rate, fp_rate, instance); } else { if (instance == 0) pr_inf(stderr, "%s: run too short to determine memory rate\n", name); } rc = EXIT_SUCCESS; (void)munmap(c, sz); err_c: (void)munmap(b, sz); err_b: (void)munmap(a, sz); err_a: return rc; } stress-ng-0.05.23/stress-switch.c0000664000175000017500000000671612702231255015251 0ustar kingking/* * Copyright (C) 2013-2016 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 SWITCH_STOP 'X' /* * 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]; size_t buf_size; (void)instance; #if defined(__linux__) && NEED_GLIBC(2,9,0) if (pipe2(pipefds, O_DIRECT) < 0) { pr_fail_dbg(name, "pipe2"); return EXIT_FAILURE; } buf_size = 1; #else if (pipe(pipefds) < 0) { pr_fail_dbg(name, "pipe"); return EXIT_FAILURE; } buf_size = stress_get_pagesize(); #endif #if defined(F_SETPIPE_SZ) if (fcntl(pipefds[0], F_SETPIPE_SZ, buf_size) < 0) { pr_dbg(stderr, "%s: could not force pipe size to 1 page, " "errno = %d (%s)\n", name, errno, strerror(errno)); } if (fcntl(pipefds[1], F_SETPIPE_SZ, buf_size) < 0) { pr_dbg(stderr, "%s: could not force pipe size to 1 page, " "errno = %d (%s)\n", name, errno, strerror(errno)); } #endif again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; (void)close(pipefds[0]); (void)close(pipefds[1]); pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { char buf[buf_size]; setpgid(0, pgrp); stress_parent_died_alarm(); (void)close(pipefds[1]); while (opt_do_run) { ssize_t ret; ret = read(pipefds[0], buf, sizeof(buf)); if (ret < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; pr_fail_dbg(name, "read"); break; } if (ret == 0) break; if (*buf == SWITCH_STOP) break; } (void)close(pipefds[0]); exit(EXIT_SUCCESS); } else { char buf[buf_size]; int status; /* Parent */ setpgid(pid, pgrp); (void)close(pipefds[0]); memset(buf, '_', buf_size); do { ssize_t ret; ret = write(pipefds[1], buf, sizeof(buf)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "write"); break; } continue; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); memset(buf, SWITCH_STOP, sizeof(buf)); if (write(pipefds[1], buf, sizeof(buf)) <= 0) pr_fail_dbg(name, "termination write"); (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } return EXIT_SUCCESS; } stress-ng-0.05.23/mincore.c0000664000175000017500000000424612702231255014057 0ustar kingking/* * Copyright (C) 2013-2016 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, const size_t buf_len) { #if !defined(__gnu_hurd__) #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) char *vec; #else unsigned char *vec; #endif volatile char *buffer; size_t vec_len, i; const size_t page_size = stress_get_pagesize(); uintptr_t uintptr = (uintptr_t)buf & (page_size - 1); 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((void *)uintptr, 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 restore contents */ 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.05.23/cache.c0000664000175000017500000003171412702231255013466 0ustar kingking/* * Copyright (C) 2016 Intel, 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. * */ #include "stress-ng.h" #if defined(__linux__) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #if defined(__linux__) #define SYS_CPU_PREFIX "/sys/devices/system/cpu" #define GLOB_PATTERN SYS_CPU_PREFIX "/cpu[0-9]*" #define SYS_CPU_CACHE_DIR "/cache" #define GLOB_PATTERN_INDEX_PREFIX "/index[0-9]*" #endif /* * append @element to array @path (which has len @len) */ #define MK_PATH(path, len, element) \ memset((path) + len, '\0', sizeof(path) - len); \ strncpy((path) + len, element, strlen(element)) static const struct generic_map cache_type_map[] = { {"data" , CACHE_TYPE_DATA}, {"instruction" , CACHE_TYPE_INSTRUCTION}, {"unified" , CACHE_TYPE_UNIFIED}, { NULL , CACHE_TYPE_UNKNOWN} }; static const char *get_cache_name(cache_type_t type) __attribute__((unused)); /** * file_exists() * @path: file to check. * Determine if specified file exists. * * Returns: file type if @path exists, else 0. **/ static int file_exists(const char *path) { struct stat st; if (!path) { pr_dbg(stderr, "%s: empty path specified\n", __func__); return 0; } if (stat(path, &st) < 0) return 0; return (st.st_mode & S_IFMT); } /* * get_contents() * @path: file to read. * Reads the contents of @file, returning the value as a string. * * Returns: dynamically-allocated copy of the contents of @path, * or NULL on error. */ static char *get_contents(const char *path) { FILE *fp = NULL; char *contents = NULL; struct stat st; size_t size; if (!path) { pr_dbg(stderr, "%s: empty path specified\n", __func__); return NULL; } fp = fopen(path, "r"); if (!fp) return NULL; if (fstat(fileno(fp), &st) < 0) goto err_close; size = st.st_size; contents = malloc(size); if (!contents) goto err_close; if (!fgets(contents, size, fp)) goto err; (void)fclose(fp); return contents; err: free(contents); err_close: (void)fclose(fp); return NULL; } /* * get_string_from_file() * @path: file to read contents of. * * Returns: dynamically-allocated copy of the contents of @path, * or NULL on error. */ static char *get_string_from_file(const char *path) { char *str; ssize_t len; str = get_contents(path); if (!str) return NULL; len = strlen(str) - 1; if ((len >= 0) && (str[len] == '\n')) str[len] = '\0'; return str; } /* * size_to_bytes() * Convert human-readable integer sizes (such as "32K", "4M") into bytes. * * Supports: * * - bytes ('B'). * - kibibytes ('K' - aka KiB). * - mebibytes ('M' - aka MiB). * * Returns: size in bytes, or 0 on error. */ static uint64_t size_to_bytes(const char *str) { uint64_t bytes; uint64_t multiplier; unsigned long int value; int ret; char *s; if (!str) { pr_dbg(stderr, "%s: empty string specified\n", __func__); return 0; } ret = sscanf(str, "%lu%ms", &value, &s); if (ret != 2 || !s) { pr_dbg(stderr, "%s: failed to parse suffix from \"%s\"\n", __func__, str); return 0; } switch(*s) { case 'B': multiplier = 1; break; case 'K': multiplier = 1024; break; case 'M': multiplier = (1024 * 1024); break; default: pr_err(stderr, "unable to convert string to bytes: %s\n", str); bytes = 0; goto out; } bytes = value * multiplier; out: free(s); return bytes; } /* get_cache_type() * @name: human-readable cache type. * Convert a human-readable cache type into a cache_type_t. * * Returns: cache_type_t or CACHE_TYPE_UNKNOWN on error. */ static cache_type_t get_cache_type(const char *name) { const struct generic_map *p; if (!name) { pr_dbg(stderr, "%s: no cache type specified\n", __func__); goto out; } for (p = cache_type_map; p && p->name; p++) { if (!strcasecmp(p->name, name)) return p->value; } out: return CACHE_TYPE_UNKNOWN; } /* * get_cache_name() * @type: cache_type_t to convert into a string. * Convert a cache_type_t to a human-readable cache type. * * Returns: read-only string representation, or NULL on error. */ static const char * get_cache_name(cache_type_t type) { const struct generic_map *p; for (p = cache_type_map; p && p->name; p++) { if (p->value == type) return p->name; } return NULL; } /* add_cpu_cache_detail() * @cache: cpu_cache_t pointer. * @index_path: full /sys path to the particular cpu cache which is to * be represented by @cache. * Populate the specified @cache based on the given cache index. * * Returns: EXIT_FAILURE or EXIT_SUCCESS. */ static int add_cpu_cache_detail(cpu_cache_t *cache, const char *index_path) { char path[PATH_MAX] = { 0 }; size_t len; char *contents = NULL; int ret = EXIT_FAILURE; if (!cache) { pr_dbg(stderr, "%s: invalid cache specified\n", __func__); goto out; } if (!index_path) { pr_dbg(stderr, "%s: invalid index specified\n", __func__); goto out; } len = strlen(index_path); strncpy(path, index_path, len); MK_PATH(path, len, "/type"); contents = get_string_from_file(path); if (!contents) goto out; cache->type = (cache_type_t)get_cache_type(contents); if (cache->type == CACHE_TYPE_UNKNOWN) goto out; free(contents); MK_PATH(path, len, "/size"); contents = get_string_from_file(path); if (!contents) goto out; cache->size = size_to_bytes(contents); free(contents); MK_PATH(path, len, "/level"); contents = get_string_from_file(path); if (!contents) goto out; cache->level = (uint16_t)atoi(contents); free(contents); MK_PATH(path, len, "/coherency_line_size"); contents = get_string_from_file(path); if (!contents) goto out; cache->line_size = (uint32_t)atoi(contents); free(contents); MK_PATH(path, len, "/ways_of_associativity"); contents = get_string_from_file(path); /* Don't error if file is not readable: cache may not be * way-based. */ cache->ways = contents ? atoi(contents) : 0; ret = EXIT_SUCCESS; out: if (contents) free(contents); return ret; } /* * get_cache_by_cpu() * @cpu: cpu to consider. * @cache_level: numeric cache level (1-indexed). * Obtain the cpu cache indexed by @cache_level. * * POTENTIAL BUG: assumes only 1 data cache per CPU cache level. * * Returns: cpu_cache_t, or NULL on error. */ static cpu_cache_t * get_cache_by_cpu(const cpu_t *cpu, const int cache_level) { uint32_t i; if (!cpu || !cache_level) return NULL; for (i = 0; i < cpu->cache_count; i++) { cpu_cache_t *p; p = &cpu->caches[i]; if (p->level != cache_level) continue; /* we want a data cache */ if (p->type != CACHE_TYPE_INSTRUCTION) return p; } return NULL; } /* * get_max_cache_level() * @cpus: array of cpus to query. * Determine the maximum cache level available on the system. * * Returns: 1-index value denoting highest cache level, or 0 on error. */ uint16_t get_max_cache_level(const cpus_t *cpus) { cpu_t *cpu; uint32_t i; uint16_t max = 0; if (!cpus) { pr_dbg(stderr, "%s: invalid cpus parameter\n", __func__); return 0; } /* * FIXME: should really determine current CPU index using * sched_getcpu(3) rather than just taking the first cpu. */ cpu = &cpus->cpus[0]; for (i=0; i < cpu->cache_count; i++) { cpu_cache_t *cache; cache = &cpu->caches[i]; max = cache->level > max ? cache->level : max; } return max; } /* * get_cpu_cache() * @cpus: array of cpus to query. * @cache_level: numeric cache level (1-indexed). * Obtain a cpu cache of level @cache_level. * * Returns: cpu_cache_t pointer, or NULL on error. */ cpu_cache_t * get_cpu_cache(const cpus_t *cpus, const uint16_t cache_level) { cpu_t *cpu; if (!cpus) { pr_dbg(stderr, "%s: invalid cpus parameter\n", __func__); return NULL; } if (!cache_level) { pr_dbg(stderr, "%s: invalid cache_level: %d\n", __func__, cache_level); return NULL; } /* FIXME: should really determine current CPU index using * sched_getcpu(3) rather than just taking the first cpu. */ cpu = &cpus->cpus[0]; return get_cache_by_cpu(cpu, cache_level); } /* * get_cpu_cache_details() * @cpu: cpu to fill in. * @cpu_path: Full /sys path to cpu which will be represented by @cpu. * Populate @cpu with details from @cpu_path. * * Returns: EXIT_FAILURE or EXIT_SUCCESS. */ static int get_cpu_cache_details(cpu_t *cpu, const char *cpu_path) { uint32_t i; size_t len, len2; glob_t globbuf; char glob_path[PATH_MAX] = { 0 }; char **results; int ret = EXIT_FAILURE; int ret2; memset(&globbuf, 0, sizeof(globbuf)); if (!cpu) { pr_dbg(stderr, "%s: invalid cpu parameter\n", __func__); return ret; } if (!cpu_path) { pr_dbg(stderr, "%s: invalid cpu path parameter\n", __func__); return ret; } len = strlen(cpu_path); strncat(glob_path, cpu_path, len); len2 = strlen(SYS_CPU_CACHE_DIR); strncat(glob_path, SYS_CPU_CACHE_DIR, len2); len += len2; ret2 = file_exists(glob_path); if (!ret2) { /* * Not an error since some platforms don't provide cache * details * via /sys (ARM). */ pr_dbg(stderr, "%s does not exist\n", glob_path); return ret; } if (ret2 != S_IFDIR) { pr_err(stderr, "file %s is not a directory\n", glob_path); return ret; } strncat(glob_path, GLOB_PATTERN_INDEX_PREFIX, sizeof(glob_path) - len - 1); ret2 = glob(glob_path, GLOB_ONLYDIR, NULL, &globbuf); if (ret2 != 0) { pr_err(stderr, "glob on regex \"%s\" failed: %d\n", glob_path, ret); return ret; } results = globbuf.gl_pathv; cpu->cache_count = globbuf.gl_pathc; if (!cpu->cache_count) { pr_err(stderr, "no CPU caches found\n"); goto err; } cpu->caches = calloc(cpu->cache_count, sizeof(cpu_cache_t)); if (!cpu->caches) { size_t cache_bytes = cpu->cache_count * sizeof(cpu_cache_t); pr_err(stderr, "failed to allocate %zu bytes for cpu caches\n", cache_bytes); goto err; } for (i = 0; i < cpu->cache_count; i++) { ret2 = add_cpu_cache_detail(&cpu->caches[i], results[i]); if (ret2 != EXIT_SUCCESS) goto err; } ret = EXIT_SUCCESS; err: globfree(&globbuf); /* reset */ glob_path[0] = '\0'; return ret; } /* * get_all_cpu_cache_details() * Obtain information on all cpus caches on the system. * * Returns: dynamically-allocated cpus_t object, or NULL on error. */ cpus_t * get_all_cpu_cache_details(void) { uint32_t i; int ret; char path[PATH_MAX] = { 0 }; glob_t globbuf; char **results; cpus_t *cpus = NULL; size_t cpu_count; size_t len; memset(&globbuf, 0, sizeof(globbuf)); ret = file_exists(SYS_CPU_PREFIX); if (!ret) { pr_err(stderr, "%s does not exist\n", SYS_CPU_PREFIX); return NULL; } if (ret != S_IFDIR) { pr_err(stderr, "file %s is not a directory\n", SYS_CPU_PREFIX); return NULL; } ret = glob(GLOB_PATTERN, GLOB_ONLYDIR, NULL, &globbuf); if (ret != 0) { pr_err(stderr, "glob on regex \"%s\" failed: %d\n", GLOB_PATTERN, ret); return NULL; } results = globbuf.gl_pathv; cpu_count = globbuf.gl_pathc; if (!cpu_count) { /* Maybe we should check this? */ pr_err(stderr, "no CPUs found - is /sys mounted?\n"); goto out; } cpus = calloc(1, sizeof(cpus_t)); if (!cpus) goto out; cpus->count = (uint32_t)cpu_count; cpus->cpus = calloc(cpu_count, sizeof(cpu_t)); if (!cpus->cpus) { free(cpus); cpus = NULL; goto out; } for (i = 0; i < cpus->count; i++) { char *contents = NULL; cpu_t *cpu; cpu = &cpus->cpus[i]; cpu->num = i; if (i == 0) { /* 1st CPU cannot be taken offline */ cpu->online = 1; } else { len = strlen(results[i]); MK_PATH(path, len, "/online"); contents = get_string_from_file(path); if (!contents) goto out; cpu->online = atoi(contents); free(contents); } ret = get_cpu_cache_details(&cpus->cpus[i], results[i]); if (ret != EXIT_SUCCESS) { free(cpus->cpus); free(cpus); cpus = NULL; goto out; } } out: globfree(&globbuf); return cpus; } /* * free_cpu_caches() * @cpus: value returned by get_all_cpu_cache_details(). * * Undo the action of get_all_cpu_cache_details() by freeing all * associated resources. */ void free_cpu_caches(cpus_t *cpus) { uint32_t i; if (!cpus) return; for (i = 0; i < cpus->count; i++) { cpu_t *cpu = &cpus->cpus[i]; free(cpu->caches); } free(cpus->cpus); free(cpus); } #endif /* __linux__ */ stress-ng-0.05.23/stress-ng.h0000664000175000017500000017307312702231255014362 0ustar kingking/* * Copyright (C) 2013-2016 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 #include #include #include #if defined (__linux__) #include #include #include #include #include #include #include #include #endif #include #include #if defined (__GLIBC__) #include #endif #if defined (__linux__) /* * BeagleBoneBlack with 4.1.15 kernel does not * define the following, these should be defined * in linux/posix_types.h - define them just in * case they don't exist. */ #ifndef __kernel_long_t typedef long int __kernel_long_t; typedef unsigned long int __kernel_ulong_t; #endif #endif #define EXIT_NOT_SUCCESS (2) #define EXIT_NO_RESOURCE (3) /* * STRESS_ASSERT(test) * throw compile time error if test not true */ #define STRESS_CONCAT(a, b) a ## b #define STRESS_CONCAT_EXPAND(a, b) STRESS_CONCAT(a, b) #define STRESS_ASSERT(expr) \ enum { STRESS_CONCAT_EXPAND(STRESS_ASSERT_AT_LINE_, __LINE__) = 1 / !!(expr) }; #define STRESS_MINIMUM(a,b) (((a) < (b)) ? (a) : (b)) #define STRESS_MAXIMUM(a,b) (((a) > (b)) ? (a) : (b)) #define _VER_(major, minor, patchlevel) \ ((major * 10000) + (minor * 100) + patchlevel) #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) #define NEED_GLIBC(major, minor, patchlevel) \ _VER_(major, minor, patchlevel) <= _VER_(__GLIBC__, __GLIBC_MINOR__, 0) #else #define NEED_GLIBC(major, minor, patchlevel) (0) #endif #if defined(__GNUC__) && defined(__GNUC_MINOR__) #if defined(__GNUC_PATCHLEVEL__) #define NEED_GNUC(major, minor, patchlevel) \ _VER_(major, minor, patchlevel) <= _VER_(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else #define NEED_GNUC(major, minor, patchlevel) \ _VER_(major, minor, patchlevel) <= _VER_(__GNUC__, __GNUC_MINOR__, 0) #endif #else #define NEED_GNUC(major, minor, patchlevel) (0) #endif #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 */ #define SOCKET_BUF (8192) /* Socket I/O buffer size */ #define UDP_BUF (1024) /* UDP I/O buffer size */ #define SOCKET_PAIR_BUF (64) /* Socket pair I/O buffer size */ #define ABORT_FAILURES (5) /* Number of failures before we abort */ /* debug output bitmasks */ #define PR_ERROR 0x0000000000001ULL /* Print errors */ #define PR_INFO 0x0000000000002ULL /* Print info */ #define PR_DEBUG 0x0000000000004ULL /* Print debug */ #define PR_FAIL 0x0000000000008ULL /* Print test failure message */ #define PR_ALL (PR_ERROR | PR_INFO | PR_DEBUG | PR_FAIL) /* Option bit masks */ #define OPT_FLAGS_AFFINITY_RAND 0x0000000000010ULL /* Change affinity randomly */ #define OPT_FLAGS_DRY_RUN 0x0000000000020ULL /* Don't actually run */ #define OPT_FLAGS_METRICS 0x0000000000040ULL /* Dump metrics at end */ #define OPT_FLAGS_VM_KEEP 0x0000000000080ULL /* Don't keep re-allocating */ #define OPT_FLAGS_RANDOM 0x0000000000100ULL /* Randomize */ #define OPT_FLAGS_SET 0x0000000000200ULL /* Set if user specifies stress procs */ #define OPT_FLAGS_KEEP_NAME 0x0000000000400ULL /* Keep stress names to stress-ng */ #define OPT_FLAGS_UTIME_FSYNC 0x0000000000800ULL /* fsync after utime modification */ #define OPT_FLAGS_METRICS_BRIEF 0x0000000001000ULL /* dump brief metrics */ #define OPT_FLAGS_VERIFY 0x0000000002000ULL /* verify mode */ #define OPT_FLAGS_MMAP_MADVISE 0x0000000004000ULL /* enable random madvise settings */ #define OPT_FLAGS_MMAP_MINCORE 0x0000000008000ULL /* mincore force pages into mem */ #define OPT_FLAGS_TIMES 0x0000000010000ULL /* user/system time summary */ #define OPT_FLAGS_CACHE_PREFETCH 0x0000000020000ULL /* cache prefetch */ #define OPT_FLAGS_CACHE_FLUSH 0x0000000040000ULL /* cache flush */ #define OPT_FLAGS_CACHE_FENCE 0x0000000080000ULL /* cache fence */ #define OPT_FLAGS_CACHE_MASK (OPT_FLAGS_CACHE_FLUSH | \ OPT_FLAGS_CACHE_FENCE | \ OPT_FLAGS_CACHE_PREFETCH) #define OPT_FLAGS_MMAP_FILE 0x0000000100000ULL /* mmap onto a file */ #define OPT_FLAGS_MMAP_ASYNC 0x0000000200000ULL /* mmap file asynchronous I/O */ #define OPT_FLAGS_MMAP_MPROTECT 0x0000000400000ULL /* mmap mprotect enabled */ #define OPT_FLAGS_LOCKF_NONBLK 0x0000000800000ULL /* Non-blocking lockf */ #define OPT_FLAGS_MINCORE_RAND 0x0000001000000ULL /* mincore randomize */ #define OPT_FLAGS_BRK_NOTOUCH 0x0000002000000ULL /* brk, don't touch page */ #define OPT_FLAGS_HDD_SYNC 0x0000004000000ULL /* HDD O_SYNC */ #define OPT_FLAGS_HDD_DSYNC 0x0000008000000ULL /* HDD O_DYNC */ #define OPT_FLAGS_HDD_DIRECT 0x0000010000000ULL /* HDD O_DIRECT */ #define OPT_FLAGS_HDD_NOATIME 0x0000020000000ULL /* HDD O_NOATIME */ #define OPT_FLAGS_STACK_FILL 0x0000040000000ULL /* Fill stack */ #define OPT_FLAGS_MINIMIZE 0x0000080000000ULL /* Minimize */ #define OPT_FLAGS_MAXIMIZE 0x0000100000000ULL /* Maximize */ #define OPT_FLAGS_MINMAX_MASK (OPT_FLAGS_MINIMIZE | OPT_FLAGS_MAXIMIZE) #define OPT_FLAGS_SYSLOG 0x0000200000000ULL /* log test progress to syslog */ #define OPT_FLAGS_AGGRESSIVE 0x0000400000000ULL /* aggressive mode enabled */ #define OPT_FLAGS_TIMER_RAND 0x0000800000000ULL /* Enable random timer freq */ #define OPT_FLAGS_TIMERFD_RAND 0x0001000000000ULL /* Enable random timerfd freq */ #define OPT_FLAGS_ALL 0x0002000000000ULL /* --all mode */ #define OPT_FLAGS_SEQUENTIAL 0x0004000000000ULL /* --sequential mode */ #define OPT_FLAGS_PERF_STATS 0x0008000000000ULL /* --perf stats mode */ #define OPT_FLAGS_LOG_BRIEF 0x0010000000000ULL /* --log-brief */ #define OPT_FLAGS_THERMAL_ZONES 0x0020000000000ULL /* --tz thermal zones */ #define OPT_FLAGS_TIMER_SLACK 0x0040000000000ULL /* --timer-slack */ #define OPT_FLAGS_SOCKET_NODELAY 0x0080000000000ULL /* --sock-nodelay */ #define OPT_FLAGS_UDP_LITE 0x0100000000000ULL /* --udp-lite */ #define OPT_FLAGS_SEEK_PUNCH 0x0200000000000ULL /* --seek-punch */ #define OPT_FLAGS_CACHE_NOAFF 0x0400000000000ULL /* disable CPU affinity */ #define OPT_FLAGS_IGNITE_CPU 0x0800000000000ULL /* --cpu-ignite */ #define OPT_FLAGS_PATHOLOGICAL 0x1000000000000ULL /* --pathological */ #define OPT_FLAGS_AGGRESSIVE_MASK \ (OPT_FLAGS_AFFINITY_RAND | OPT_FLAGS_UTIME_FSYNC | \ OPT_FLAGS_MMAP_MADVISE | OPT_FLAGS_MMAP_MINCORE | \ OPT_FLAGS_CACHE_FLUSH | OPT_FLAGS_CACHE_FENCE | \ OPT_FLAGS_MMAP_FILE | OPT_FLAGS_MMAP_ASYNC | \ OPT_FLAGS_MMAP_MPROTECT | OPT_FLAGS_LOCKF_NONBLK |\ OPT_FLAGS_MINCORE_RAND | OPT_FLAGS_HDD_SYNC | \ OPT_FLAGS_HDD_DSYNC | OPT_FLAGS_HDD_DIRECT | \ OPT_FLAGS_STACK_FILL | OPT_FLAGS_CACHE_PREFETCH | \ OPT_FLAGS_AGGRESSIVE | OPT_FLAGS_IGNITE_CPU) /* 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 */ #define CLASS_PIPE_IO 0x00000200 /* pipe I/O */ #define CLASS_FILESYSTEM 0x00000400 /* file system */ #define CLASS_DEV 0x00000800 /* device (null, zero, etc) */ #define CLASS_SECURITY 0x00001000 /* security APIs */ #define CLASS_PATHOLOGICAL 0x00002000 /* can hang a machine */ /* Network domains flags */ #define DOMAIN_INET 0x00000001 /* AF_INET */ #define DOMAIN_INET6 0x00000002 /* AF_INET6 */ #define DOMAIN_UNIX 0x00000004 /* AF_UNIX */ #define DOMAIN_INET_ALL (DOMAIN_INET | DOMAIN_INET6) #define DOMAIN_ALL (DOMAIN_INET | DOMAIN_INET6 | DOMAIN_UNIX) /* Large prime to stride around large VM regions */ #define PRIME_64 (0x8f0000000017116dULL) /* Logging helpers */ extern int pr_msg(FILE *fp, const uint64_t flag, const char *const fmt, ...) __attribute__((format(printf, 3, 4))); extern void pr_msg_fail(const uint64_t flag, const char *name, const char *what, const int err); extern int pr_yaml(FILE *fp, const char *const fmt, ...); extern void pr_yaml_runinfo(FILE *fp); extern void pr_openlog(const char *filename); #define pr_dbg(fp, fmt, args...) pr_msg(fp, PR_DEBUG, fmt, ## args) #define pr_inf(fp, fmt, args...) pr_msg(fp, PR_INFO, fmt, ## args) #define pr_err(fp, fmt, args...) pr_msg(fp, PR_ERROR, fmt, ## args) #define pr_fail(fp, fmt, args...) pr_msg(fp, PR_FAIL, fmt, ## args) #define pr_tidy(fp, fmt, args...) pr_msg(fp, opt_sigint ? PR_INFO : PR_DEBUG, fmt, ## args) #define pr_fail_err(name, what) pr_msg_fail(PR_FAIL | PR_ERROR, name, what, errno) #define pr_fail_errno(name, what, e) pr_msg_fail(PR_FAIL | PR_ERROR, name, what, e) #define pr_fail_dbg(name, what) pr_msg_fail(PR_DEBUG, name, what, errno) /* 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) #define MAX_32 (0xffffffffUL) /* Stressor defaults */ #define MIN_AIO_REQUESTS (1) #define MAX_AIO_REQUESTS (4096) #define DEFAULT_AIO_REQUESTS (16) #define MIN_AIO_LINUX_REQUESTS (1) #define MAX_AIO_LINUX_REQUESTS (4096) #define DEFAULT_AIO_LINUX_REQUESTS (64) #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_CLONES (1) #define MAX_CLONES (1000000) #define DEFAULT_CLONES (8192) #define MIN_COPY_FILE_BYTES (128 * MB) #define MAX_COPY_FILE_BYTES (256ULL * GB) #define DEFAULT_COPY_FILE_BYTES (256 * MB) #define DEFAULT_COPY_FILE_SIZE (2 * MB) #define MIN_DENTRIES (1) #define MAX_DENTRIES (1000000) #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 (256ULL * 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_FALLOCATE_BYTES (1 * MB) #if UINTPTR_MAX == MAX_32 #define MAX_FALLOCATE_BYTES (MAX_32) #else #define MAX_FALLOCATE_BYTES (4 * GB) #endif #define DEFAULT_FALLOCATE_BYTES (1 * GB) #define MIN_FIEMAP_SIZE (1 * MB) #if UINTPTR_MAX == MAX_32 #define MAX_FIEMAP_SIZE (0xffffe00) #else #define MAX_FIEMAP_SIZE (256ULL * GB) #endif #define DEFAULT_FIEMAP_SIZE (16 * MB) #define MIN_FIFO_READERS (1) #define MAX_FIFO_READERS (64) #define DEFAULT_FIFO_READERS (4) #define MIN_ITIMER_FREQ (1) #define MAX_ITIMER_FREQ (100000000) #define DEFAULT_ITIMER_FREQ (1000000) #define MIN_MQ_SIZE (1) #define MAX_MQ_SIZE (32) #define DEFAULT_MQ_SIZE (10) #define MIN_SEMAPHORE_PROCS (2) #define MAX_SEMAPHORE_PROCS (64) #define DEFAULT_SEMAPHORE_PROCS (2) #define MIN_EXECS (1) #define MAX_EXECS (16000) #define DEFAULT_EXECS (1) #define MIN_FORKS (1) #define MAX_FORKS (16000) #define DEFAULT_FORKS (1) #define MIN_HEAPSORT_SIZE (1 * KB) #define MAX_HEAPSORT_SIZE (4 * MB) #define DEFAULT_HEAPSORT_SIZE (256 * KB) #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 (64) #define DEFAULT_LEASE_BREAKERS (1) #define MIN_LSEARCH_SIZE (1 * KB) #define MAX_LSEARCH_SIZE (1 * MB) #define DEFAULT_LSEARCH_SIZE (8 * KB) #define MIN_MALLOC_BYTES (1 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_MALLOC_BYTES (MAX_32) #else #define MAX_MALLOC_BYTES (4 * GB) #endif #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_MALLOC_THRESHOLD (1) #define MAX_MALLOC_THRESHOLD (256 * MB) #define DEFAULT_MALLOC_THRESHOLD (128 * KB) #define MIN_MATRIX_SIZE (16) #define MAX_MATRIX_SIZE (4096) #define DEFAULT_MATRIX_SIZE (256) #define MIN_MERGESORT_SIZE (1 * KB) #define MAX_MERGESORT_SIZE (4 * MB) #define DEFAULT_MERGESORT_SIZE (256 * KB) #define MIN_MMAP_BYTES (4 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_MMAP_BYTES (MAX_32) #else #define MAX_MMAP_BYTES (4 * GB) #endif #define DEFAULT_MMAP_BYTES (256 * MB) #define MIN_MREMAP_BYTES (4 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_MREMAP_BYTES (MAX_32) #else #define MAX_MREMAP_BYTES (4 * GB) #endif #define DEFAULT_MREMAP_BYTES (256 * MB) #define MIN_PTHREAD (1) #define MAX_PTHREAD (30000) #define DEFAULT_PTHREAD (1024) #define MIN_QSORT_SIZE (1 * KB) #define MAX_QSORT_SIZE (4 * MB) #define DEFAULT_QSORT_SIZE (256 * KB) #define MIN_READAHEAD_BYTES (1 * MB) #define MAX_READAHEAD_BYTES (256ULL * GB) #define DEFAULT_READAHEAD_BYTES (1 * GB) #define MIN_SENDFILE_SIZE (1 * KB) #define MAX_SENDFILE_SIZE (1 * GB) #define DEFAULT_SENDFILE_SIZE (4 * MB) #define MIN_SEEK_SIZE (1 * MB) #if UINTPTR_MAX == MAX_32 #define MAX_SEEK_SIZE (0xffffe00) #else #define MAX_SEEK_SIZE (256ULL * GB) #endif #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 (256 * MB) #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_SHM_POSIX_BYTES (1 * MB) #define MAX_SHM_POSIX_BYTES (1 * GB) #define DEFAULT_SHM_POSIX_BYTES (8 * MB) #define MIN_SHM_POSIX_OBJECTS (1) #define MAX_SHM_POSIX_OBJECTS (128) #define DEFAULT_SHM_POSIX_OBJECTS (32) #define MAX_SIGSUSPEND_PIDS (4) #define MIN_SLEEP (1) #define MAX_SLEEP (30000) #define DEFAULT_SLEEP (1024) #define MIN_SOCKET_PORT (1024) #define MAX_SOCKET_PORT (65535) #define DEFAULT_SOCKET_PORT (5000) #define MIN_SOCKET_FD_PORT (1024) #define MAX_SOCKET_FD_PORT (65535) #define DEFAULT_SOCKET_FD_PORT (8000) #define MIN_SPLICE_BYTES (1*KB) #define MAX_SPLICE_BYTES (64*MB) #define DEFAULT_SPLICE_BYTES (64*KB) #define MIN_STREAM_L3_SIZE (4 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_STREAM_L3_SIZE (MAX_32) #else #define MAX_STREAM_L3_SIZE (4 * GB) #endif #define DEFAULT_STREAM_L3_SIZE (4 * MB) #define MIN_SYNC_FILE_BYTES (1 * MB) #if UINTPTR_MAX == MAX_32 #define MAX_SYNC_FILE_BYTES (MAX_32) #else #define MAX_SYNC_FILE_BYTES (4 * GB) #endif #define DEFAULT_SYNC_FILE_BYTES (1 * GB) #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_TIMERFD_FREQ (1) #define MAX_TIMERFD_FREQ (100000000) #define DEFAULT_TIMERFD_FREQ (1000000) #define MIN_UDP_PORT (1024) #define MAX_UDP_PORT (65535) #define DEFAULT_UDP_PORT (7000) #define MIN_USERFAULTFD_BYTES (4 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_USERFAULTFD_BYTES (MAX_32) #else #define MAX_USERFAULTFD_BYTES (4 * GB) #endif #define DEFAULT_USERFAULTFD_BYTES (16 * MB) #define MIN_VM_BYTES (4 * KB) #if UINTPTR_MAX == MAX_32 #define MAX_VM_BYTES (MAX_32) #else #define MAX_VM_BYTES (4 * GB) #endif #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) #if UINTPTR_MAX == MAX_32 #define MAX_VM_RW_BYTES (MAX_32) #else #define MAX_VM_RW_BYTES (4 * GB) #endif #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 MIN_ZOMBIES (1) #define MAX_ZOMBIES (1000000) #define DEFAULT_ZOMBIES (8192) #define DEFAULT_TIMEOUT (60 * 60 * 24) #define DEFAULT_BACKOFF (0) #define DEFAULT_LINKS (8192) #define DEFAULT_DIRS (8192) #define STR_SHARED_SIZE (65536 * 32) #define MEM_CACHE_SIZE (65536 * 32) #define DEFAULT_CACHE_LEVEL 3 #define UNDEFINED (-1) #define PAGE_MAPPED (0x01) #define PAGE_MAPPED_FAIL (0x02) #define FFT_SIZE (4096) #define STRESS_CPU_DITHER_X (1024) #define STRESS_CPU_DITHER_Y (768) #define STRESS_NBITS(a) (sizeof(a[0]) * 8) #define STRESS_GETBIT(a, i) (a[i / STRESS_NBITS(a)] & (1 << (i & (STRESS_NBITS(a)-1)))) #define STRESS_CLRBIT(a, i) (a[i / STRESS_NBITS(a)] &= ~(1 << (i & (STRESS_NBITS(a)-1)))) #define STRESS_SETBIT(a, i) (a[i / STRESS_NBITS(a)] |= (1 << (i & (STRESS_NBITS(a)-1)))) #define SIEVE_SIZE (10000000) /* MWC random number initial seed */ #define MWC_SEED_Z (362436069UL) #define MWC_SEED_W (521288629UL) #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 NEED_GNUC(4,7,0) #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__) #define RESTRICT __restrict #else #define RESTRICT #endif #if defined(__GNUC__) && !defined(__clang__) && defined(__SIZEOF_INT128__) #define STRESS_INT128 1 #endif #if defined(__linux__) #define STRESS_IONICE #endif #if (_BSD_SOURCE || _SVID_SOURCE || !defined(__gnu_hurd__)) #define STRESS_PAGE_IN #endif #if defined(__linux__) #define STRESS_IOPRIO #endif #if defined(__GNUC__) && defined(__linux__) #define STRESS_MALLOPT #endif #if defined(__GNUC__) && !defined(__clang__) && NEED_GNUC(4,6,0) #define OPTIMIZE3 __attribute__((optimize("-O3"))) #else #define OPTIMIZE3 #endif #if defined(__GNUC__) #define WARN_UNUSED __attribute__((warn_unused_result)) #endif #if defined(__GNUC__) || defined(__clang__) #define FORCE_DO_NOTHING() __asm__ __volatile__("") #else #define FORCE_DO_NOTHING() while (0) #endif #if defined(__linux__) && \ defined(PR_SET_TIMERSLACK) && \ defined(PR_GET_TIMERSLACK) #define PRCTL_TIMER_SLACK #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 { uint32_t w; uint32_t z; } mwc_t; /* Force aligment to nearest cache line */ #if defined(__GNUC__) #define ALIGN64 __attribute__ ((aligned(64))) #else #define ALIGN64 #endif #if defined(__GNUC__) && NEED_GNUC(4,6,0) #define HOT __attribute__ ((hot)) #else #define HOT #endif #if defined(__GNUC__) && NEED_GNUC(4,6,0) #define MLOCKED __attribute__((__section__("mlocked"))) #define MLOCKED_SECTION 1 #else #define MLOCKED #endif #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) && defined(__NR_perf_event_open) #define STRESS_PERF_STATS (1) #define STRESS_PERF_INVALID (~0ULL) enum { STRESS_PERF_HW_CPU_CYCLES = 0, STRESS_PERF_HW_INSTRUCTIONS, STRESS_PERF_HW_CACHE_REFERENCES, STRESS_PERF_HW_CACHE_MISSES, STRESS_PERF_HW_STALLED_CYCLES_FRONTEND, STRESS_PERF_HW_STALLED_CYCLES_BACKEND, STRESS_PERF_HW_BRANCH_INSTRUCTIONS, STRESS_PERF_HW_BRANCH_MISSES, STRESS_PERF_HW_BUS_CYCLES, STRESS_PERF_HW_REF_CPU_CYCLES, STRESS_PERF_SW_PAGE_FAULTS_MIN, STRESS_PERF_SW_PAGE_FAULTS_MAJ, STRESS_PERF_SW_CONTEXT_SWITCHES, STRESS_PERF_SW_CPU_MIGRATIONS, STRESS_PERF_SW_ALIGNMENT_FAULTS, STRESS_PERF_TP_PAGE_FAULT_USER, STRESS_PERF_TP_PAGE_FAULT_KERNEL, STRESS_PERF_TP_SYSCALLS_ENTER, STRESS_PERF_TP_SYSCALLS_EXIT, STRESS_PERF_TP_TLB_FLUSH, STRESS_PERF_TP_KMALLOC, STRESS_PERF_TP_KMALLOC_NODE, STRESS_PERF_TP_KFREE, STRESS_PERF_TP_MM_PAGE_ALLOC, STRESS_PERF_TP_MM_PAGE_FREE, STRESS_PERF_TP_KMEM_CACHE_ALLOC, STRESS_PERF_TP_KMEM_CACHE_ALLOC_NODE, STRESS_PERF_TP_KMEM_CACHE_FREE, STRESS_PERF_TP_RCU_UTILIZATION, STRESS_PERF_TP_SCHED_MIGRATE_TASK, STRESS_PERF_TP_SCHED_MOVE_NUMA, STRESS_PERF_TP_SCHED_WAKEUP, STRESS_PERF_TP_SIGNAL_GENERATE, STRESS_PERF_TP_SIGNAL_DELIVER, STRESS_PERF_TP_IRQ_ENTRY, STRESS_PERF_TP_IRQ_EXIT, STRESS_PERF_TP_SOFTIRQ_ENTRY, STRESS_PERF_TP_SOFTIRQ_EXIT, STRESS_PERF_TP_WRITEBACK_DIRTY_INODE, STRESS_PERF_TP_WRITEBACK_DIRTY_PAGE, STRESS_PERF_MAX }; /* per perf counter info */ typedef struct { uint64_t counter; /* perf counter */ int fd; /* perf per counter fd */ } perf_stat_t; /* per stressor perf info */ typedef struct { perf_stat_t perf_stat[STRESS_PERF_MAX]; /* perf counters */ int perf_opened; /* count of opened counters */ } stress_perf_t; #endif #if defined(__linux__) #define STRESS_THERMAL_ZONES (1) #define STRESS_THERMAL_ZONES_MAX (31) /* best if prime */ #endif #if defined(STRESS_THERMAL_ZONES) /* per stressor thermal zone info */ typedef struct tz_info { char *path; char *type; size_t index; struct tz_info *next; } tz_info_t; typedef struct { uint64_t temperature; /* temperature in Celsius * 1000 */ } tz_stat_t; typedef struct { tz_stat_t tz_stat[STRESS_THERMAL_ZONES_MAX]; } stress_tz_t; #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 */ #if defined(STRESS_PERF_STATS) stress_perf_t sp; /* perf counters */ #endif #if defined(STRESS_THERMAL_ZONES) stress_tz_t tz; /* thermal zones */ #endif } proc_stats_t; /* Shared memory segment */ typedef struct { uint8_t *mem_cache; /* Shared memory cache */ uint64_t mem_cache_size; /* Bytes */ uint16_t mem_cache_level; /* 1=L1, 2=L2, 3=L3 */ uint32_t mem_cache_ways; /* cache ways size */ uint8_t str_shared[STR_SHARED_SIZE]; /* str copying buffer */ struct { uint32_t futex[STRESS_PROCS_MAX]; /* Shared futexes */ uint64_t timeout[STRESS_PROCS_MAX]; /* Shared futex timeouts */ } futex; #if defined(__linux__) struct { sem_t sem; /* Shared posix semaphores */ bool init; /* Semaphores initialised? */ } sem_posix; #endif struct { key_t key_id; /* System V semaphore key id */ int sem_id; /* System V semaphore id */ bool init; /* System V semaphore initialized */ } sem_sysv; #if defined(STRESS_PERF_STATS) struct { bool no_perf; /* true = Perf not available */ pthread_spinlock_t lock; /* spinlock on no_perf updates */ } perf; #endif #if defined(STRESS_THERMAL_ZONES) tz_info_t *tz_info; /* List of valid thermal zones */ #endif proc_stats_t stats[0]; /* 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 { STRESS_START = -1, #if defined(__linux__) && NEED_GLIBC(2,3,0) __STRESS_AFFINITY, #define STRESS_AFFINITY __STRESS_AFFINITY #endif #if defined(__linux__) && defined(AF_ALG) __STRESS_AF_ALG, #define STRESS_AF_ALG __STRESS_AF_ALG #endif #if defined(HAVE_LIB_RT) && defined(__linux__) && NEED_GLIBC(2,1,0) __STRESS_AIO, #define STRESS_AIO __STRESS_AIO #endif #if defined(__linux__) && \ defined(HAVE_LIB_AIO) && \ defined(__NR_io_setup) && \ defined(__NR_io_destroy) && \ defined(__NR_io_submit) && \ defined(__NR_io_getevents) __STRESS_AIO_LINUX, #define STRESS_AIO_LINUX __STRESS_AIO_LINUX #endif #if defined(__linux__) && defined(HAVE_APPARMOR) __STRESS_APPARMOR, #define STRESS_APPARMOR __STRESS_APPARMOR #endif STRESS_BRK, STRESS_BSEARCH, STRESS_BIGHEAP, #if defined(__linux__) && defined(MS_BIND) && defined(MS_REC) __STRESS_BIND_MOUNT, #define STRESS_BIND_MOUNT __STRESS_BIND_MOUNT #endif STRESS_CACHE, #if defined(__linux__) && defined(HAVE_SYS_CAP_H) __STRESS_CAP, #define STRESS_CAP __STRESS_CAP #endif STRESS_CHDIR, STRESS_CHMOD, #if defined(HAVE_LIB_RT) && _POSIX_C_SOURCE >= 199309L __STRESS_CLOCK, #define STRESS_CLOCK __STRESS_CLOCK #endif #if defined(__linux__) && NEED_GLIBC(2,14,0) __STRESS_CLONE, #define STRESS_CLONE __STRESS_CLONE #endif #if !defined(__OpenBSD__) __STRESS_CONTEXT, #define STRESS_CONTEXT __STRESS_CONTEXT #endif #if defined(__linux__) && (__NR_copy_file_range) __STRESS_COPY_FILE, #define STRESS_COPY_FILE __STRESS_COPY_FILE #endif STRESS_CPU, #if defined(__linux__) __STRESS_CPU_ONLINE, #define STRESS_CPU_ONLINE __STRESS_CPU_ONLINE #endif #if defined(HAVE_LIB_CRYPT) __STRESS_CRYPT, #define STRESS_CRYPT __STRESS_CRYPT #endif STRESS_DAEMON, STRESS_DENTRY, STRESS_DIR, STRESS_DUP, #if defined(HAVE_LIB_RT) && defined(__linux__) && NEED_GLIBC(2,3,2) __STRESS_EPOLL, #define STRESS_EPOLL __STRESS_EPOLL #endif #if defined(__linux__) && NEED_GLIBC(2,8,0) __STRESS_EVENTFD, #define STRESS_EVENTFD __STRESS_EVENTFD #endif #if defined(__linux__) __STRESS_EXEC, #define STRESS_EXEC __STRESS_EXEC #endif #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && NEED_GLIBC(2,10,0) __STRESS_FALLOCATE, #define STRESS_FALLOCATE __STRESS_FALLOCATE #endif STRESS_FAULT, STRESS_FCNTL, #if defined(__linux__) && defined(FS_IOC_FIEMAP) __STRESS_FIEMAP, #define STRESS_FIEMAP __STRESS_FIEMAP #endif STRESS_FIFO, STRESS_FILENAME, STRESS_FLOCK, STRESS_FORK, STRESS_FP_ERROR, STRESS_FSTAT, #if defined(__linux__) && defined(__NR_futex) __STRESS_FUTEX, #define STRESS_FUTEX __STRESS_FUTEX #endif STRESS_GET, #if defined(__linux__) && defined(__NR_getrandom) __STRESS_GETRANDOM, #define STRESS_GETRANDOM __STRESS_GETRANDOM #endif #if defined(__linux__) && defined(__NR_getdents64) __STRESS_GETDENT, #define STRESS_GETDENT __STRESS_GETDENT #endif #if defined(__linux__) && defined(__NR_name_to_handle_at) && \ defined(__NR_open_by_handle_at) && NEED_GLIBC(2,14,0) __STRESS_HANDLE, #define STRESS_HANDLE __STRESS_HANDLE #endif STRESS_HDD, #if defined(HAVE_LIB_BSD) __STRESS_HEAPSORT, #define STRESS_HEAPSORT __STRESS_HEAPSORT #endif STRESS_HSEARCH, #if defined(STRESS_X86) && defined(__GNUC__) && NEED_GNUC(4,6,0) __STRESS_ICACHE, #define STRESS_ICACHE __STRESS_ICACHE #endif #if defined(__linux__) && NEED_GLIBC(2,9,0) __STRESS_INOTIFY, #define STRESS_INOTIFY __STRESS_INOTIFY #endif STRESS_IOSYNC, STRESS_ITIMER, #if defined(__linux__) && defined(__NR_kcmp) __STRESS_KCMP, #define STRESS_KCMP __STRESS_KCMP #endif #if defined(HAVE_KEYUTILS_H) && defined(__linux__) && defined(__NR_add_key) && defined(__NR_keyctl) __STRESS_KEY, #define STRESS_KEY __STRESS_KEY #endif STRESS_KILL, #if defined(__linux__) && defined(__NR_syslog) __STRESS_KLOG, #define STRESS_KLOG __STRESS_KLOG #endif #if defined(F_SETLEASE) && defined(F_WRLCK) && defined(F_UNLCK) __STRESS_LEASE, #define STRESS_LEASE __STRESS_LEASE #endif STRESS_LINK, #if (defined(__GNUC__) || defined(__clang__)) && defined(STRESS_X86) && defined(__linux__) __STRESS_LOCKBUS, #define STRESS_LOCKBUS __STRESS_LOCKBUS #endif #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \ (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) __STRESS_LOCKF, #define STRESS_LOCKF __STRESS_LOCKF #endif STRESS_LONGJMP, STRESS_LSEARCH, STRESS_MALLOC, STRESS_MATRIX, #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) && defined(__NR_membarrier) __STRESS_MEMBARRIER, #define STRESS_MEMBARRIER __STRESS_MEMBARRIER #endif STRESS_MEMCPY, #if defined(__linux__) && defined(__NR_memfd_create) __STRESS_MEMFD, #define STRESS_MEMFD __STRESS_MEMFD #endif #if defined(HAVE_LIB_BSD) __STRESS_MERGESORT, #define STRESS_MERGESORT __STRESS_MERGESORT #endif #if !defined(__gnu_hurd__) && NEED_GLIBC(2,2,0) __STRESS_MINCORE, #define STRESS_MINCORE __STRESS_MINCORE #endif STRESS_MKNOD, #if defined(_POSIX_MEMLOCK_RANGE) __STRESS_MLOCK, #define STRESS_MLOCK __STRESS_MLOCK #endif STRESS_MMAP, #if defined(__linux__) __STRESS_MMAPFORK, #define STRESS_MMAPFORK __STRESS_MMAPFORK #endif STRESS_MMAPMANY, #if defined(__linux__) && NEED_GLIBC(2,4,0) __STRESS_MREMAP, #define STRESS_MREMAP __STRESS_MREMAP #endif #if !defined(__gnu_hurd__) && NEED_GLIBC(2,0,0) __STRESS_MSG, #define STRESS_MSG __STRESS_MSG #endif #if defined(HAVE_LIB_RT) && defined(__linux__) __STRESS_MQ, #define STRESS_MQ __STRESS_MQ #endif STRESS_NICE, STRESS_NULL, #if defined(__linux__) && \ defined(__NR_get_mempolicy) && \ defined(__NR_mbind) && \ defined(__NR_migrate_pages) && \ defined(__NR_move_pages) && \ defined(__NR_set_mempolicy) __STRESS_NUMA, #define STRESS_NUMA __STRESS_NUMA #endif #if defined(__linux__) && defined(F_SETPIPE_SZ) __STRESS_OOM_PIPE, #define STRESS_OOM_PIPE __STRESS_OOM_PIPE #endif STRESS_OPEN, #if defined(__linux__) __STRESS_PERSONALITY, #define STRESS_PERSONALITY __STRESS_PERSONALITY #endif STRESS_PIPE, STRESS_POLL, #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) __STRESS_PROCFS, #define STRESS_PROCFS __STRESS_PROCFS #endif #if defined(HAVE_LIB_PTHREAD) __STRESS_PTHREAD, #define STRESS_PTHREAD __STRESS_PTHREAD #endif #if defined(__linux__) __STRESS_PTRACE, #define STRESS_PTRACE __STRESS_PTRACE #endif STRESS_QSORT, #if defined(__linux__) && ( \ defined(Q_GETQUOTA) || \ defined(Q_GETFMT) || \ defined(Q_GETINFO) || \ defined(Q_GETSTATS) || \ defined(Q_SYNC)) __STRESS_QUOTA, #define STRESS_QUOTA __STRESS_QUOTA #endif #if defined(STRESS_X86) && !defined(__OpenBSD__) && NEED_GNUC(4,6,0) __STRESS_RDRAND, #define STRESS_RDRAND __STRESS_RDRAND #endif #if defined(__linux__) && NEED_GLIBC(2,3,0) __STRESS_READAHEAD, #define STRESS_READAHEAD __STRESS_READAHEAD #endif #if defined(__linux__) && NEED_GLIBC(2,3,0) && defined(__NR_remap_file_pages) __STRESS_REMAP_FILE_PAGES, #define STRESS_REMAP_FILE_PAGES __STRESS_REMAP_FILE_PAGES #endif STRESS_RENAME, #if defined(__linux__) __STRESS_RLIMIT, #define STRESS_RLIMIT __STRESS_RLIMIT #endif #if defined(HAVE_SECCOMP_H) && defined(__linux__) && defined(PR_SET_SECCOMP) __STRESS_SECCOMP, #define STRESS_SECCOMP __STRESS_SECCOMP #endif STRESS_SEEK, #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) __STRESS_SEMAPHORE_POSIX, #define STRESS_SEMAPHORE_POSIX __STRESS_SEMAPHORE_POSIX #endif #if defined(__linux__) __STRESS_SEMAPHORE_SYSV, #define STRESS_SEMAPHORE_SYSV __STRESS_SEMAPHORE_SYSV #endif #if defined(__linux__) && NEED_GLIBC(2,1,0) __STRESS_SENDFILE, #define STRESS_SENDFILE __STRESS_SENDFILE #endif #if defined(HAVE_LIB_RT) __STRESS_SHM_POSIX, #define STRESS_SHM_POSIX __STRESS_SHM_POSIX #endif STRESS_SHM_SYSV, #if defined(__linux__) && NEED_GLIBC(2,8,0) __STRESS_SIGFD, #define STRESS_SIGFD __STRESS_SIGFD #endif STRESS_SIGFPE, STRESS_SIGPENDING, #if _POSIX_C_SOURCE >= 199309L && !defined(__gnu_hurd__) __STRESS_SIGQUEUE, #define STRESS_SIGQUEUE __STRESS_SIGQUEUE #endif STRESS_SIGSEGV, STRESS_SIGSUSPEND, #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) __STRESS_SLEEP, #define STRESS_SLEEP __STRESS_SLEEP #endif STRESS_SOCKET, #if defined(__linux__) __STRESS_SOCKET_FD, #define STRESS_SOCKET_FD __STRESS_SOCKET_FD #endif STRESS_SOCKET_PAIR, __STRESS_SPAWN, #define STRESS_SPAWN __STRESS_SPAWN #if defined(__linux__) && NEED_GLIBC(2,5,0) __STRESS_SPLICE, #define STRESS_SPLICE __STRESS_SPLICE #endif STRESS_STACK, STRESS_STR, STRESS_STREAM, STRESS_SWITCH, STRESS_SYMLINK, #if defined(__linux__) && defined(__NR_sync_file_range) && NEED_GLIBC(2,10,0) __STRESS_SYNC_FILE, #define STRESS_SYNC_FILE __STRESS_SYNC_FILE #endif STRESS_SYSINFO, #if defined(HAVE_LIB_PTHREAD) && defined(__linux__) __STRESS_SYSFS, #define STRESS_SYSFS __STRESS_SYSFS #endif #if defined(__linux__) && NEED_GLIBC(2,5,0) __STRESS_TEE, #define STRESS_TEE __STRESS_TEE #endif #if defined(HAVE_LIB_RT) && defined(__linux__) __STRESS_TIMER, #define STRESS_TIMER __STRESS_TIMER #endif #if defined(__linux__) __STRESS_TIMERFD, #define STRESS_TIMERFD __STRESS_TIMERFD #endif #if defined(STRESS_X86) && !defined(__OpenBSD__) && NEED_GNUC(4,6,0) __STRESS_TSC, #define STRESS_TSC __STRESS_TSC #endif STRESS_TSEARCH, STRESS_UDP, #if defined(AF_PACKET) __STRESS_UDP_FLOOD, #define STRESS_UDP_FLOOD __STRESS_UDP_FLOOD #endif #if defined(__linux__) && defined(__NR_unshare) __STRESS_UNSHARE, #define STRESS_UNSHARE __STRESS_UNSHARE #endif #if defined(__linux__) || defined(__gnu_hurd__) __STRESS_URANDOM, #define STRESS_URANDOM __STRESS_URANDOM #endif #if defined(__linux__) && \ defined(__NR_userfaultfd) __STRESS_USERFAULTFD, #define STRESS_USERFAULTFD __STRESS_USERFAULTFD #endif STRESS_UTIME, #if defined(STRESS_VECTOR) __STRESS_VECMATH, #define STRESS_VECMATH __STRESS_VECMATH #endif __STRESS_VFORK, #define STRESS_VFORK __STRESS_VFORK STRESS_VM, #if defined(__linux__) && \ defined(__NR_process_vm_readv) && defined(__NR_process_vm_writev) && \ NEED_GLIBC(2,15,0) __STRESS_VM_RW, #define STRESS_VM_RW __STRESS_VM_RW #endif #if defined(__linux__) && NEED_GLIBC(2,5,0) __STRESS_VM_SPLICE, #define STRESS_VM_SPLICE __STRESS_VM_SPLICE #endif #if !defined(__gnu_hurd__) && !defined(__NetBSD__) __STRESS_WAIT, #define STRESS_WAIT __STRESS_WAIT #endif STRESS_WCS, #if defined(__linux__) && defined(HAVE_XATTR_H) __STRESS_XATTR, #define STRESS_XATTR __STRESS_XATTR #endif #if defined(_POSIX_PRIORITY_SCHEDULING) __STRESS_YIELD, #define STRESS_YIELD __STRESS_YIELD #endif STRESS_ZERO, #if defined(HAVE_LIB_Z) __STRESS_ZLIB, #define STRESS_ZLIB __STRESS_ZLIB #endif STRESS_ZOMBIE, /* 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 defined(STRESS_FALLOCATE) 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(STRESS_TIMER) OPT_TIMER = 'T', #endif #if defined(STRESS_URANDOM) OPT_URANDOM = 'u', #endif OPT_VERBOSE = 'v', OPT_VERSION = 'V', OPT_YIELD = 'y', OPT_YAML = 'Y', OPT_EXCLUDE = 'x', /* Long options only */ OPT_LONG_OPS_START = 0x7f, #if defined(STRESS_AFFINITY) OPT_AFFINITY, OPT_AFFINITY_OPS, OPT_AFFINITY_RAND, #endif #if defined(STRESS_AF_ALG) OPT_AF_ALG, OPT_AF_ALG_OPS, #endif OPT_AGGRESSIVE, #if defined(STRESS_AIO) OPT_AIO, OPT_AIO_OPS, OPT_AIO_REQUESTS, #endif #if defined(STRESS_AIO_LINUX) OPT_AIO_LINUX, OPT_AIO_LINUX_OPS, OPT_AIO_LINUX_REQUESTS, #endif #if defined(STRESS_APPARMOR) OPT_APPARMOR, OPT_APPARMOR_OPS, #endif OPT_BRK, OPT_BRK_OPS, OPT_BRK_NOTOUCH, OPT_BSEARCH, OPT_BSEARCH_OPS, OPT_BSEARCH_SIZE, OPT_BIGHEAP_OPS, OPT_BIGHEAP_GROWTH, #if defined(STRESS_BIND_MOUNT) OPT_BIND_MOUNT, OPT_BIND_MOUNT_OPS, #endif OPT_CLASS, OPT_CACHE_OPS, OPT_CACHE_PREFETCH, OPT_CACHE_FLUSH, OPT_CACHE_FENCE, OPT_CACHE_LEVEL, OPT_CACHE_WAYS, OPT_CACHE_NO_AFFINITY, #if defined(STRESS_CAP) OPT_CAP, OPT_CAP_OPS, #endif OPT_CHDIR, OPT_CHDIR_OPS, OPT_CHMOD, OPT_CHMOD_OPS, #if defined(STRESS_CLOCK) OPT_CLOCK, OPT_CLOCK_OPS, #endif #if defined(STRESS_CLONE) OPT_CLONE, OPT_CLONE_OPS, OPT_CLONE_MAX, #endif #if defined(STRESS_CONTEXT) OPT_CONTEXT, OPT_CONTEXT_OPS, #endif #if defined(STRESS_COPY_FILE) OPT_COPY_FILE, OPT_COPY_FILE_OPS, OPT_COPY_FILE_BYTES, #endif OPT_CPU_OPS, OPT_CPU_METHOD, OPT_CPU_LOAD_SLICE, #if defined(STRESS_CPU_ONLINE) OPT_CPU_ONLINE, OPT_CPU_ONLINE_OPS, #endif #if defined(STRESS_CRYPT) OPT_CRYPT, OPT_CRYPT_OPS, #endif OPT_DAEMON, OPT_DAEMON_OPS, OPT_DENTRY_OPS, OPT_DENTRIES, OPT_DENTRY_ORDER, OPT_DIR, OPT_DIR_OPS, OPT_DUP, OPT_DUP_OPS, #if defined(STRESS_EPOLL) OPT_EPOLL, OPT_EPOLL_OPS, OPT_EPOLL_PORT, OPT_EPOLL_DOMAIN, #endif #if defined(STRESS_EVENTFD) OPT_EVENTFD, OPT_EVENTFD_OPS, #endif #if defined(STRESS_EXEC) OPT_EXEC, OPT_EXEC_OPS, OPT_EXEC_MAX, #endif #if defined(STRESS_FALLOCATE) OPT_FALLOCATE_OPS, OPT_FALLOCATE_BYTES, #endif OPT_FAULT, OPT_FAULT_OPS, OPT_FCNTL, OPT_FCNTL_OPS, #if defined(STRESS_FIEMAP) OPT_FIEMAP, OPT_FIEMAP_OPS, #endif OPT_FIFO, OPT_FIFO_OPS, OPT_FIFO_READERS, OPT_FILENAME, OPT_FILENAME_OPS, OPT_FILENAME_OPTS, OPT_FLOCK, OPT_FLOCK_OPS, OPT_FORK_OPS, OPT_FORK_MAX, OPT_FP_ERROR, OPT_FP_ERROR_OPS, OPT_FSTAT, OPT_FSTAT_OPS, OPT_FSTAT_DIR, OPT_FUTEX, OPT_FUTEX_OPS, OPT_GET, OPT_GET_OPS, #if defined(STRESS_GETRANDOM) OPT_GETRANDOM, OPT_GETRANDOM_OPS, #endif #if defined(STRESS_GETDENT) OPT_GETDENT, OPT_GETDENT_OPS, #endif #if defined(STRESS_HANDLE) OPT_HANDLE, OPT_HANDLE_OPS, #endif OPT_HDD_BYTES, OPT_HDD_WRITE_SIZE, OPT_HDD_OPS, OPT_HDD_OPTS, #if defined(STRESS_HEAPSORT) OPT_HEAPSORT, OPT_HEAPSORT_OPS, OPT_HEAPSORT_INTEGERS, #endif OPT_HSEARCH, OPT_HSEARCH_OPS, OPT_HSEARCH_SIZE, OPT_ICACHE, OPT_ICACHE_OPS, OPT_IGNITE_CPU, #if defined(STRESS_INOTIFY) OPT_INOTIFY, OPT_INOTIFY_OPS, #endif #if defined(STRESS_IONICE) OPT_IONICE_CLASS, OPT_IONICE_LEVEL, #endif OPT_IOSYNC_OPS, OPT_ITIMER, OPT_ITIMER_OPS, OPT_ITIMER_FREQ, #if defined(STRESS_KCMP) OPT_KCMP, OPT_KCMP_OPS, #endif #if defined(STRESS_KEY) OPT_KEY, OPT_KEY_OPS, #endif OPT_KILL, OPT_KILL_OPS, #if defined(STRESS_KLOG) OPT_KLOG, OPT_KLOG_OPS, #endif #if defined(STRESS_LEASE) OPT_LEASE, OPT_LEASE_OPS, OPT_LEASE_BREAKERS, #endif OPT_LINK, OPT_LINK_OPS, #if defined(STRESS_LOCKBUS) OPT_LOCKBUS, OPT_LOCKBUS_OPS, #endif #if defined(STRESS_LOCKF) OPT_LOCKF, OPT_LOCKF_OPS, OPT_LOCKF_NONBLOCK, #endif OPT_LOG_BRIEF, OPT_LOG_FILE, OPT_LONGJMP, OPT_LONGJMP_OPS, OPT_LSEARCH, OPT_LSEARCH_OPS, OPT_LSEARCH_SIZE, OPT_MALLOC, OPT_MALLOC_OPS, OPT_MALLOC_BYTES, OPT_MALLOC_MAX, #if defined(STRESS_MALLOPT) OPT_MALLOC_THRESHOLD, #endif OPT_MATRIX, OPT_MATRIX_OPS, OPT_MATRIX_SIZE, OPT_MATRIX_METHOD, OPT_MAXIMIZE, #if defined(STRESS_MEMBARRIER) OPT_MEMBARRIER, OPT_MEMBARRIER_OPS, #endif OPT_MEMCPY, OPT_MEMCPY_OPS, #if defined(STRESS_MEMFD) OPT_MEMFD, OPT_MEMFD_OPS, #endif #if defined(STRESS_MERGESORT) OPT_MERGESORT, OPT_MERGESORT_OPS, OPT_MERGESORT_INTEGERS, #endif OPT_METRICS_BRIEF, #if defined(STRESS_MINCORE) OPT_MINCORE, OPT_MINCORE_OPS, OPT_MINCORE_RAND, #endif OPT_MKNOD, OPT_MKNOD_OPS, OPT_MINIMIZE, #if defined(STRESS_MLOCK) OPT_MLOCK, OPT_MLOCK_OPS, #endif OPT_MMAP, OPT_MMAP_OPS, OPT_MMAP_BYTES, OPT_MMAP_FILE, OPT_MMAP_ASYNC, OPT_MMAP_MPROTECT, #if defined(__linux__) OPT_MMAPFORK, OPT_MMAPFORK_OPS, #endif OPT_MMAPMANY, OPT_MMAPMANY_OPS, #if defined(STRESS_MREMAP) OPT_MREMAP, OPT_MREMAP_OPS, OPT_MREMAP_BYTES, #endif OPT_MSG, OPT_MSG_OPS, #if defined(STRESS_MQ) OPT_MQ, OPT_MQ_OPS, OPT_MQ_SIZE, #endif OPT_NICE, OPT_NICE_OPS, OPT_NO_MADVISE, OPT_NULL, OPT_NULL_OPS, #if defined(STRESS_NUMA) OPT_NUMA, OPT_NUMA_OPS, #endif #if defined(STRESS_OOM_PIPE) OPT_OOM_PIPE, OPT_OOM_PIPE_OPS, #endif OPT_OPEN_OPS, #if defined(STRESS_PAGE_IN) OPT_PAGE_IN, #endif OPT_PATHOLOGICAL, #if defined(STRESS_PERF_STATS) OPT_PERF_STATS, #endif #if defined(STRESS_PERSONALITY) OPT_PERSONALITY, OPT_PERSONALITY_OPS, #endif OPT_PIPE_OPS, #if defined(F_SETPIPE_SZ) OPT_PIPE_SIZE, #endif OPT_PIPE_DATA_SIZE, OPT_POLL_OPS, #if defined(STRESS_PROCFS) OPT_PROCFS, OPT_PROCFS_OPS, #endif #if defined(STRESS_PTHREAD) OPT_PTHREAD, OPT_PTHREAD_OPS, OPT_PTHREAD_MAX, #endif OPT_PTRACE, OPT_PTRACE_OPS, OPT_QSORT, OPT_QSORT_OPS, OPT_QSORT_INTEGERS, OPT_QUOTA, OPT_QUOTA_OPS, #if defined(STRESS_RDRAND) OPT_RDRAND, OPT_RDRAND_OPS, #endif #if defined(STRESS_READAHEAD) OPT_READAHEAD, OPT_READAHEAD_OPS, OPT_READAHEAD_BYTES, #endif #if defined(STRESS_REMAP_FILE_PAGES) OPT_REMAP_FILE_PAGES, OPT_REMAP_FILE_PAGES_OPS, #endif OPT_RENAME_OPS, #if defined(STRESS_RLIMIT) OPT_RLIMIT, OPT_RLIMIT_OPS, #endif OPT_SCHED, OPT_SCHED_PRIO, #if defined(STRESS_SECCOMP) OPT_SECCOMP, OPT_SECCOMP_OPS, #endif OPT_SEEK, OPT_SEEK_OPS, #if defined(FALLOC_FL_PUNCH_HOLE) && \ defined(FALLOC_FL_KEEP_SIZE) __OPT_SEEK_PUNCH, #define OPT_SEEK_PUNCH __OPT_SEEK_PUNCH #endif OPT_SEEK_SIZE, #if defined(STRESS_SENDFILE) OPT_SENDFILE, OPT_SENDFILE_OPS, OPT_SENDFILE_SIZE, #endif OPT_SEMAPHORE_POSIX, OPT_SEMAPHORE_POSIX_OPS, OPT_SEMAPHORE_POSIX_PROCS, #if defined(STRESS_SEMAPHORE_SYSV) OPT_SEMAPHORE_SYSV, OPT_SEMAPHORE_SYSV_OPS, OPT_SEMAPHORE_SYSV_PROCS, #endif #if defined(STRESS_SHM_POSIX) OPT_SHM_POSIX, OPT_SHM_POSIX_OPS, OPT_SHM_POSIX_BYTES, OPT_SHM_POSIX_OBJECTS, #endif OPT_SHM_SYSV, OPT_SHM_SYSV_OPS, OPT_SHM_SYSV_BYTES, OPT_SHM_SYSV_SEGMENTS, OPT_SEQUENTIAL, #if defined(STRESS_SIGFD) OPT_SIGFD, OPT_SIGFD_OPS, #endif OPT_SIGFPE, OPT_SIGFPE_OPS, OPT_SIGPENDING, OPT_SIGPENDING_OPS, #if defined(STRESS_SIGQUEUE) OPT_SIGQUEUE, OPT_SIGQUEUE_OPS, #endif OPT_SIGSEGV, OPT_SIGSEGV_OPS, OPT_SIGSUSPEND, OPT_SIGSUSPEND_OPS, #if defined(STRESS_SLEEP) OPT_SLEEP, OPT_SLEEP_OPS, OPT_SLEEP_MAX, #endif OPT_SOCKET_OPS, OPT_SOCKET_DOMAIN, OPT_SOCKET_NODELAY, OPT_SOCKET_OPTS, OPT_SOCKET_PORT, #if defined(STRESS_SOCKET_FD) OPT_SOCKET_FD, OPT_SOCKET_FD_OPS, #endif OPT_SOCKET_PAIR, OPT_SOCKET_PAIR_OPS, OPT_SWITCH_OPS, OPT_SPAWN, OPT_SPAWN_OPS, #if defined(STRESS_SPLICE) OPT_SPLICE, OPT_SPLICE_OPS, OPT_SPLICE_BYTES, #endif OPT_STACK, OPT_STACK_OPS, OPT_STACK_FILL, OPT_STR, OPT_STR_OPS, OPT_STR_METHOD, OPT_STREAM, OPT_STREAM_OPS, OPT_STREAM_L3_SIZE, OPT_SYMLINK, OPT_SYMLINK_OPS, #if defined(STRESS_SYNC_FILE) OPT_SYNC_FILE, OPT_SYNC_FILE_OPS, OPT_SYNC_FILE_BYTES, #endif OPT_SYSINFO, OPT_SYSINFO_OPS, #if defined(STRESS_SYSFS) OPT_SYSFS, OPT_SYSFS_OPS, #endif OPT_SYSLOG, #if defined(STRESS_TEE) OPT_TEE, OPT_TEE_OPS, #endif OPT_TEMP_PATH, OPT_THERMAL_ZONES, #if defined(PRCTL_TIMER_SLACK) OPT_TIMER_SLACK, #endif #if defined(STRESS_TIMER) OPT_TIMER_OPS, OPT_TIMER_FREQ, OPT_TIMER_RAND, #endif #if defined(STRESS_TIMERFD) OPT_TIMERFD, OPT_TIMERFD_OPS, OPT_TIMERFD_FREQ, OPT_TIMERFD_RAND, #endif OPT_TIMES, #if defined(STRESS_TSC) OPT_TSC, OPT_TSC_OPS, #endif OPT_TSEARCH, OPT_TSEARCH_OPS, OPT_TSEARCH_SIZE, OPT_UDP, OPT_UDP_OPS, OPT_UDP_PORT, OPT_UDP_DOMAIN, #if defined(IPPROTO_UDPLITE) __OPT_UDP_LITE, #define OPT_UDP_LITE __OPT_UDP_LITE #endif #if defined(STRESS_UDP_FLOOD) OPT_UDP_FLOOD, OPT_UDP_FLOOD_OPS, OPT_UDP_FLOOD_DOMAIN, #endif #if defined(STRESS_UNSHARE) OPT_UNSHARE, OPT_UNSHARE_OPS, #endif #if defined(STRESS_URANDOM) OPT_URANDOM_OPS, #endif #if defined(STRESS_USERFAULTFD) OPT_USERFAULTFD, OPT_USERFAULTFD_OPS, OPT_USERFAULTFD_BYTES, #endif OPT_UTIME, OPT_UTIME_OPS, OPT_UTIME_FSYNC, #if defined(STRESS_VECMATH) OPT_VECMATH, OPT_VECMATH_OPS, #endif OPT_VERIFY, #if defined(STRESS_VFORK) 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(STRESS_VM_RW) OPT_VM_RW, OPT_VM_RW_OPS, OPT_VM_RW_BYTES, #endif #if defined(STRESS_VM_SPLICE) OPT_VM_SPLICE, OPT_VM_SPLICE_OPS, OPT_VM_SPLICE_BYTES, #endif #if defined(STRESS_WAIT) OPT_WAIT, OPT_WAIT_OPS, #endif OPT_WCS, OPT_WCS_OPS, OPT_WCS_METHOD, #if defined(STRESS_XATTR) OPT_XATTR, OPT_XATTR_OPS, #endif #if defined(STRESS_YIELD) OPT_YIELD_OPS, #endif OPT_ZERO, OPT_ZERO_OPS, #if defined(STRESS_ZLIB) OPT_ZLIB, OPT_ZLIB_OPS, #endif OPT_ZOMBIE, OPT_ZOMBIE_OPS, OPT_ZOMBIE_MAX, } 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 */ bool exclude; /* true if excluded */ } proc_info_t; typedef struct { const char ch; /* Scaling suffix */ const uint64_t scale; /* Amount to scale by */ } scale_t; #if defined(__linux__) typedef enum cache_type { CACHE_TYPE_UNKNOWN = 0, CACHE_TYPE_DATA, CACHE_TYPE_INSTRUCTION, CACHE_TYPE_UNIFIED, } cache_type_t; typedef struct cpu_cache { uint16_t level; cache_type_t type; uint64_t size; /* bytes */ uint32_t line_size; /* bytes */ uint32_t ways; } cpu_cache_t; struct generic_map { const char *name; uint32_t value; }; typedef struct cpu { uint32_t num; bool online; uint32_t cache_count; cpu_cache_t *caches; } cpu_t; typedef struct cpus { uint32_t count; cpu_t *cpus; } cpus_t; #endif /* 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 uint64_t opt_flags; /* option flags */ extern int32_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 */ extern pid_t pgrp; /* proceess group leader */ /* * 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 uint64_t uint64_zero(void); static volatile uint64_t uint64_val; static volatile double double_val; static inline void uint64_put(const uint64_t a) { uint64_val = a; } static inline void double_put(const double a) { double_val = a; } /* 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 WARN_UNUSED 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); extern void stress_cwd_readwriteable(void); extern const char *stress_strsignal(const int signum); #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) do { } while (0) /* No-op */ #define mfence() do { } while (0) /* No-op */ #endif /* * mwc_seed() * set mwc seeds */ static inline void mwc_seed(const uint32_t w, const uint32_t z) { __mwc.w = w; __mwc.z = z; } /* * mwc32() * Multiply-with-carry random numbers * fast pseudo random number generator, see * http://www.cse.yorku.ca/~oz/marsaglia-rng.html */ static inline uint32_t mwc32(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; } static inline uint64_t mwc64(void) { return (((uint64_t)mwc32()) << 32) | mwc32(); } static inline uint16_t mwc16(void) { return mwc32() & 0xffff; } static inline uint8_t mwc8(void) { return mwc32() & 0xff; } extern void mwc_seed(const uint32_t w, const uint32_t z); extern void mwc_reseed(void); /* Time handling */ /* * timeval_to_double() * convert timeval to seconds as a double */ static inline double timeval_to_double(const struct timeval *tv) { return (double)tv->tv_sec + ((double)tv->tv_usec / 1000000.0); } extern int stressor_instances(const stress_id id); #if defined(STRESS_PERF_STATS) /* Perf stats */ extern int perf_open(stress_perf_t *sp); extern int perf_enable(stress_perf_t *sp); extern int perf_disable(stress_perf_t *sp); extern int perf_close(stress_perf_t *sp); extern int perf_get_counter_by_index(const stress_perf_t *sp, const int index, uint64_t *counter, int *id); extern int perf_get_counter_by_id(const stress_perf_t *sp, int id, uint64_t *counter, int *index); extern bool perf_stat_succeeded(const stress_perf_t *sp); extern const char *perf_get_label_by_index(const int i); extern const char *perf_stat_scale(const uint64_t counter, const double duration); extern void perf_stat_dump(FILE *yaml, const stress_t stressors[], const proc_info_t procs[STRESS_MAX], const int32_t max_procs, const double duration); extern void perf_init(void); #endif extern double time_now(void); extern const char *duration_to_str(const double duration); /* Misc settings helpers */ extern void set_oom_adjustment(const char *name, const bool killable); extern void set_sched(const int32_t sched, const int32_t sched_priority); extern void set_iopriority(const int32_t class, const int32_t level); extern void set_proc_name(const char *name); /* Memory locking */ extern int stress_mlock_region(const void *addr_start, const void *addr_end); /* Argument parsing and range checking */ extern WARN_UNUSED int32_t get_opt_sched(const char *const str); extern WARN_UNUSED int32_t get_opt_ionice_class(const char *const str); extern WARN_UNUSED unsigned long get_unsigned_long(const char *const str); extern WARN_UNUSED int32_t get_int32(const char *const str); extern WARN_UNUSED uint64_t get_uint64(const char *const str); extern WARN_UNUSED uint64_t get_uint64_scale(const char *const str, const scale_t scales[], const char *const msg); extern WARN_UNUSED uint64_t get_uint64_byte(const char *const str); extern WARN_UNUSED uint64_t get_uint64_time(const char *const 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 int32_t stress_get_processors_online(void); extern int32_t stress_get_processors_configured(void); extern int32_t stress_get_ticks_per_second(void); extern ssize_t stress_get_stack_direction(const void *val1); extern void stress_get_memlimits(size_t *shmall, size_t *freemem, size_t *totalmem); extern WARN_UNUSED int stress_get_load_avg(double *min1, double *min5, double *min15); extern void set_max_limits(void); extern void stress_parent_died_alarm(void); extern int stress_process_dumpable(const bool dumpable); extern void stress_set_timer_slack_ns(const char *optarg); extern void stress_set_timer_slack(void); extern WARN_UNUSED int stress_set_temp_path(char *path); extern void stress_strnrnd(char *str, const size_t len); extern void stress_get_cache_size(uint64_t *l2, uint64_t *l3); extern WARN_UNUSED int stress_cache_alloc(const char *name); extern void stress_cache_free(void); extern void ignite_cpu_start(void); extern void ignite_cpu_stop(void); extern int system_write(const char *path, const char *buf, const size_t buf_len); extern WARN_UNUSED int system_read(const char *path, char *buf, const size_t buf_len); extern WARN_UNUSED uint64_t stress_get_prime64(const uint64_t n); extern WARN_UNUSED size_t stress_get_file_limit(void); extern WARN_UNUSED int stress_sighandler(const char *name, const int signum, void (*handler)(int), struct sigaction *orig_action); extern int stress_sigrestore(const char *name, const int signum, struct sigaction *orig_action); /* * Indicate a stress test failed because of limited resources * rather than a failure of the tests during execution. * err is the errno of the failure. */ static inline int exit_status(const int err) { return ((err == ENOMEM) || (err == ENOSPC)) ? EXIT_NO_RESOURCE : EXIT_FAILURE; } /* Memory tweaking */ extern int madvise_random(void *addr, const size_t length); extern int mincore_touch_pages(void *buf, const size_t buf_len); /* Mounts */ extern void mount_free(char *mnts[], const int n); extern WARN_UNUSED int mount_get(char *mnts[], const int max); #if defined(STRESS_THERMAL_ZONES) /* thermal zones */ extern int tz_init(tz_info_t **tz_info_list); extern void tz_free(tz_info_t **tz_info_list); extern int tz_get_temperatures(tz_info_t **tz_info_list, stress_tz_t *tz); extern void tz_dump(FILE *fp, const shared_t *shared, const stress_t stressors[], const proc_info_t procs[STRESS_MAX], const int32_t max_procs); #endif /* Network helpers */ extern void stress_set_net_port(const char *optname, const char *optarg, const int min_port, const int max_port, int *port); extern WARN_UNUSED int stress_set_net_domain(const int domain_mask, const char *name, const char *domain_name, int *domain); extern 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_set_sockaddr_port(const int domain, const int port, struct sockaddr *sockaddr); 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); /* CPU caches */ #if defined (__linux__) extern cpus_t *get_all_cpu_cache_details(void); extern uint16_t get_max_cache_level(const cpus_t *cpus); extern cpu_cache_t *get_cpu_cache(const cpus_t *cpus, const uint16_t cache_level); extern void free_cpu_caches(cpus_t *cpus); #endif /* Used to set options for specific stressors */ extern void stress_adjust_pthread_max(uint64_t max); extern void stress_adjust_sleep_max(uint64_t max); extern int stress_apparmor_supported(void); extern void stress_set_aio_requests(const char *optarg); extern void stress_set_aio_linux_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_clone_max(const char *optarg); extern void stress_set_copy_file_bytes(const char *optarg); extern void stress_set_cpu_load(const char *optarg); extern void stress_set_cpu_load_slice(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_exec_max(const char *optarg); extern void stress_set_fallocate_bytes(const char *optarg); extern void stress_set_fifo_readers(const char *optarg); extern int stress_filename_opts(const char *opt); 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_heapsort_size(const void *optarg); extern void stress_set_hsearch_size(const char *optarg); extern void stress_set_itimer_freq(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_malloc_threshold(const char *optarg); extern int stress_set_matrix_method(const char *name); extern void stress_set_matrix_size(const char *optarg); extern void stress_set_mergesort_size(const void *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_pipe_data_size(const char *optarg); extern void stress_set_pipe_size(const char *optarg); extern void stress_set_pthread_max(const char *optarg); extern void stress_set_qsort_size(const void *optarg); extern int stress_rdrand_supported(void); extern void stress_set_readahead_bytes(const char *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_posix_bytes(const char *optarg); extern void stress_set_shm_posix_objects(const char *optarg); extern void stress_set_shm_sysv_bytes(const char *optarg); extern void stress_set_shm_sysv_segments(const char *optarg); extern void stress_set_sleep_max(const char *optarg); extern int stress_set_socket_domain(const char *name); extern int stress_set_socket_opts(const char *optarg); extern void stress_set_socket_port(const char *optarg); extern void stress_set_splice_bytes(const char *optarg); extern int stress_set_str_method(const char *name); extern void stress_set_stream_L3_size(const char *optarg); extern void stress_set_sync_file_bytes(const char *optarg); extern int stress_set_wcs_method(const char *name); extern void stress_set_timer_freq(const char *optarg); extern void stress_set_timerfd_freq(const char *optarg); extern int stress_tsc_supported(void); 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 int stress_set_udp_flood_domain(const char *name); extern void stress_set_userfaultfd_bytes(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); extern void stress_set_zombie_max(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_af_alg); STRESS(stress_aio); STRESS(stress_aio_linux); STRESS(stress_apparmor); STRESS(stress_bigheap); STRESS(stress_bind_mount); STRESS(stress_brk); STRESS(stress_bsearch); STRESS(stress_cache); STRESS(stress_cap); STRESS(stress_chdir); STRESS(stress_chmod); STRESS(stress_clock); STRESS(stress_clone); STRESS(stress_context); STRESS(stress_copy_file); STRESS(stress_cpu); STRESS(stress_cpu_online); STRESS(stress_crypt); STRESS(stress_daemon); STRESS(stress_dentry); STRESS(stress_dir); STRESS(stress_dup); STRESS(stress_epoll); STRESS(stress_eventfd); STRESS(stress_exec); STRESS(stress_fallocate); STRESS(stress_fault); STRESS(stress_fcntl); STRESS(stress_fiemap); STRESS(stress_fifo); STRESS(stress_filename); STRESS(stress_flock); STRESS(stress_fork); STRESS(stress_fp_error); STRESS(stress_fstat); STRESS(stress_futex); STRESS(stress_get); STRESS(stress_getrandom); STRESS(stress_getdent); STRESS(stress_handle); STRESS(stress_hdd); STRESS(stress_heapsort); STRESS(stress_hsearch); STRESS(stress_icache); STRESS(stress_inotify); STRESS(stress_iosync); STRESS(stress_itimer); STRESS(stress_kcmp); STRESS(stress_key); STRESS(stress_kill); STRESS(stress_klog); STRESS(stress_lease); STRESS(stress_link); STRESS(stress_lockbus); STRESS(stress_lockf); STRESS(stress_longjmp); STRESS(stress_lsearch); STRESS(stress_malloc); STRESS(stress_matrix); STRESS(stress_membarrier); STRESS(stress_memcpy); STRESS(stress_memfd); STRESS(stress_mergesort); STRESS(stress_mincore); STRESS(stress_mknod); STRESS(stress_mlock); STRESS(stress_mmap); STRESS(stress_mmapfork); STRESS(stress_mmapmany); STRESS(stress_mremap); STRESS(stress_msg); STRESS(stress_mq); STRESS(stress_nice); STRESS(stress_noop); STRESS(stress_null); STRESS(stress_numa); STRESS(stress_oom_pipe); STRESS(stress_open); STRESS(stress_personality); STRESS(stress_pipe); STRESS(stress_poll); STRESS(stress_procfs); STRESS(stress_pthread); STRESS(stress_ptrace); STRESS(stress_qsort); STRESS(stress_quota); STRESS(stress_rdrand); STRESS(stress_readahead); STRESS(stress_remap_file_pages); STRESS(stress_rename); STRESS(stress_rlimit); STRESS(stress_seccomp); STRESS(stress_seek); STRESS(stress_sem_posix); STRESS(stress_sem_sysv); STRESS(stress_shm_posix); STRESS(stress_shm_sysv); STRESS(stress_sendfile); STRESS(stress_sigfd); STRESS(stress_sigfpe); STRESS(stress_sigpending); STRESS(stress_sigsegv); STRESS(stress_sigsuspend); STRESS(stress_sigq); STRESS(stress_sleep); STRESS(stress_socket); STRESS(stress_socket_fd); STRESS(stress_socket_pair); STRESS(stress_spawn); STRESS(stress_splice); STRESS(stress_stack); STRESS(stress_str); STRESS(stress_stream); STRESS(stress_switch); STRESS(stress_symlink); STRESS(stress_sync_file); STRESS(stress_sysinfo); STRESS(stress_sysfs); STRESS(stress_tee); STRESS(stress_timer); STRESS(stress_timerfd); STRESS(stress_tsc); STRESS(stress_tsearch); STRESS(stress_udp); STRESS(stress_udp_flood); STRESS(stress_unshare); STRESS(stress_urandom); STRESS(stress_userfaultfd); 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_wcs); STRESS(stress_xattr); STRESS(stress_yield); STRESS(stress_zero); STRESS(stress_zlib); STRESS(stress_zombie); #endif stress-ng-0.05.23/test-libpthread.c0000664000175000017500000000305112702231255015507 0ustar kingking/* * Copyright (C) 2013-2016 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. * */ #include #include /* The following functions from libpthread are used by stress-ng */ static void *pthread_funcs[] = { #if defined(__linux__) (void *)sem_init, (void *)sem_destroy, (void *)sem_post, (void *)sem_timedwait, (void *)pthread_create, (void *)pthread_join, (void *)pthread_mutex_lock, (void *)pthread_mutex_unlock, (void *)pthread_cond_wait, (void *)pthread_cond_broadcast, (void *)pthread_cond_destroy, (void *)pthread_mutex_destroy, #endif }; int main(void) { return 0; } stress-ng-0.05.23/stress-sigfd.c0000664000175000017500000000572412702231255015042 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SIGFD) #include #include #include #include #include #include #include #include /* * 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, SIGRTMIN); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { pr_fail_dbg(name, "sigprocmask"); return EXIT_FAILURE; } sfd = signalfd(-1, &mask, 0); if (sfd < 0) { pr_fail_dbg(name, "signalfd"); return EXIT_FAILURE; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); while (opt_do_run) { union sigval s; int ret; memset(&s, 0, sizeof(s)); s.sival_int = 0; ret = sigqueue(ppid, SIGRTMIN, s); if (ret < 0) break; } (void)close(sfd); _exit(0); } else { /* Parent */ int status; setpgid(pid, pgrp); do { int ret; struct signalfd_siginfo fdsi; ret = read(sfd, &fdsi, sizeof(fdsi)); if ((ret < 0) || (ret != sizeof(fdsi))) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_dbg(name, "signalfd read"); (void)close(sfd); _exit(EXIT_FAILURE); } continue; } if (ret == 0) break; if (opt_flags & OPT_FLAGS_VERIFY) { if (fdsi.ssi_signo != (uint32_t)SIGRTMIN) { 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.05.23/stress-mlock.c0000664000175000017500000001243312702231255015046 0ustar kingking/* * Copyright (C) 2013-2016 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 MLOCK_MAX (256*1024) #if defined(__NR_mlock2) #ifndef MLOCK_ONFAULT #define MLOCK_ONFAULT 1 #endif static int sys_mlock2(const void *addr, size_t len, int flags) { return (int)syscall(__NR_mlock2, addr, len, flags); } /* * mlock_shim() * if mlock2 is available, randonly exerise this * or mlock. If not available, just fallback to * mlock. Also, pick random mlock2 flags */ static int mlock_shim(const void *addr, size_t len) { static bool use_mlock2 = true; if (use_mlock2) { uint32_t rnd = mwc32() >> 5; /* Randomly use mlock2 or mlock */ if (rnd & 1) { const int flags = (rnd & 2) ? 0 : MLOCK_ONFAULT; int ret; ret = sys_mlock2(addr, len, flags); if (!ret) return 0; if (errno != ENOSYS) return ret; /* mlock2 not supported... */ use_mlock2 = false; } } /* Just do mlock */ return mlock(addr, len); } #else static inline int mlock_shim(const void *addr, size_t len) { return mlock(addr, len); } #endif /* * stress_mlock() * stress mlock with pages being locked/unlocked */ int stress_mlock( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const size_t page_size = stress_get_pagesize(); pid_t pid; size_t max = sysconf(_SC_MAPPED_FILES); max = max > MLOCK_MAX ? MLOCK_MAX : max; again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n", name, errno, strerror(errno)); } else if (pid > 0) { int status, ret; setpgid(pid, pgrp); stress_parent_died_alarm(); /* 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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) { uint8_t *mappings[max]; size_t i, n; setpgid(0, pgrp); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { for (n = 0; opt_do_run && (n < max); n++) { int ret; if (!opt_do_run || (max_ops && *counter >= max_ops)) break; mappings[n] = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (mappings[n] == MAP_FAILED) break; ret = mlock_shim(mappings[n] + page_size, page_size); if (ret < 0) { if (errno == EAGAIN) continue; if (errno == ENOMEM) break; pr_fail_err(name, "mlock"); break; } else { /* * Mappings are always page aligned so * we can use the bottom bit to * indicate if the page has been * mlocked or not */ mappings[n] = (uint8_t *) ((ptrdiff_t)mappings[n] | 1); (*counter)++; } } for (i = 0; i < n; i++) { ptrdiff_t addr = (ptrdiff_t)mappings[i]; ptrdiff_t mlocked = addr & 1; addr ^= mlocked; if (mlocked) (void)munlock((uint8_t *)addr + page_size, page_size); munmap((void *)addr, page_size * 3); } #if !defined(__gnu_hurd__) (void)mlockall(MCL_CURRENT); (void)mlockall(MCL_FUTURE); #if defined(MCL_ONFAULT) (void)mlockall(MCL_ONFAULT); #endif #endif for (n = 0; opt_do_run && (n < max); n++) { if (!opt_do_run || (max_ops && *counter >= max_ops)) break; mappings[n] = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (mappings[n] == MAP_FAILED) break; } #if !defined(__gnu_hurd__) (void)munlockall(); #endif for (i = 0; i < n; i++) munmap(mappings[i], page_size); } while (opt_do_run && (!max_ops || *counter < max_ops)); } return EXIT_SUCCESS; } stress-ng-0.05.23/stress-iosync.c0000664000175000017500000000366612702231255015255 0ustar kingking/* * Copyright (C) 2013-2016 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 #include #endif #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) { #if defined(__linux__) int fd; #endif (void)instance; #if !(defined(__linux__) && NEED_GLIBC(2,14,0)) (void)name; #endif #if defined(__linux__) fd = openat(AT_FDCWD, ".", O_RDONLY | O_NONBLOCK | O_DIRECTORY); #endif do { sync(); #if defined(__linux__) && NEED_GLIBC(2,14,0) if ((fd != -1) && (syncfs(fd) < 0)) pr_fail_err(name, "syncfs"); #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); #if defined(__linux__) if (fd != -1) (void)close(fd); #endif return EXIT_SUCCESS; } stress-ng-0.05.23/stress-mq.c0000664000175000017500000001257612702231255014366 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MQ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { uint64_t value; bool stop; } msg_t; static int opt_mq_size = DEFAULT_MQ_SIZE; static bool set_mq_size = false; void stress_set_mq_size(const char *optarg) { uint64_t sz; set_mq_size = true; sz = get_uint64_byte(optarg); opt_mq_size = (int)sz; check_range("mq-size", sz, MIN_MQ_SIZE, MAX_MQ_SIZE); } /* * 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, max_sz; FILE *fp; struct mq_attr attr; char mq_name[64]; if (!set_mq_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_mq_size = MAX_MQ_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_mq_size = MIN_MQ_SIZE; } sz = opt_mq_size; 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_fail_dbg(name, "mq_open"); return EXIT_FAILURE; } if (sz < opt_mq_size) { pr_inf(stdout, "%s: POSIX message queue requested " "size %d messages, maximum of %d allowed\n", name, opt_mq_size, sz); } pr_dbg(stderr, "POSIX message queue %s with %lu messages\n", mq_name, (unsigned long)attr.mq_maxmsg); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { time_t time_start; struct timespec abs_timeout; bool do_timedreceive; setpgid(0, pgrp); stress_parent_died_alarm(); if (time(&time_start) == ((time_t)-1)) { do_timedreceive = false; pr_fail_dbg(name, "mq_timedreceive skipped"); } else { do_timedreceive = true; abs_timeout.tv_sec = time_start + opt_timeout + 1; abs_timeout.tv_nsec = 0; } while (opt_do_run) { uint64_t i; for (i = 0; ; i++) { msg_t msg; /* * toggle between timedreceive and receive */ if (do_timedreceive && !(i & 1)) { if (mq_timedreceive(mq, (char *)&msg, sizeof(msg), NULL, &abs_timeout) < 0) { pr_fail_dbg(name, "mq_timedreceive"); break; } } else { if (mq_receive(mq, (char *)&msg, sizeof(msg), NULL) < 0) { pr_fail_dbg(name, "mq_receive"); break; } } if (msg.stop) break; if (opt_flags & OPT_FLAGS_VERIFY) { if (msg.value != i) { pr_fail(stderr, "%s: mq_receive: expected message " "containing 0x%" PRIx64 " but received 0x%" PRIx64 " instead\n", name, i, msg.value); } } } exit(EXIT_SUCCESS); } } else { int status; int attr_count = 0; msg_t msg; /* Parent */ setpgid(pid, pgrp); do { memset(&msg, 0, sizeof(msg)); msg.value = (*counter); msg.stop = false; if ((attr_count++ & 31) == 0) { struct mq_attr attr; if (mq_getattr(mq, &attr) < 0) pr_fail_dbg(name, "mq_getattr"); } if (mq_send(mq, (char *)&msg, sizeof(msg), 1) < 0) { if (errno != EINTR) pr_fail_dbg(name, "mq_send"); 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_fail_dbg(name, "termination mq_send"); } (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); if (mq_close(mq) < 0) pr_fail_dbg(name, "mq_close"); if (mq_unlink(mq_name) < 0) pr_fail_dbg(name, "mq_unlink"); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-hsearch.c0000664000175000017500000000651512702231255015362 0ustar kingking/* * Copyright (C) 2013-2016 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; static bool set_hsearch_size = false; /* * stress_set_hsearch_size() * set hsearch size from given option string */ void stress_set_hsearch_size(const char *optarg) { set_hsearch_size = true; 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) { size_t i, max; int ret = EXIT_FAILURE; char **keys; (void)instance; if (!set_hsearch_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_hsearch_size = MAX_HSEARCH_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_hsearch_size = MIN_HSEARCH_SIZE; } max = (size_t)opt_hsearch_size; /* Make hash table with 25% slack */ if (!hcreate(max + (max / 4))) { pr_fail_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, "%s: cannot find key %s\n", name, keys[i]); } else { if (i != (size_t)ep->data) { pr_fail(stderr, "%s: hash returned incorrect data %zd\n", name, 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.05.23/stress-kcmp.c0000664000175000017500000001212212702231255014666 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_KCMP) #include #include #include #include #include #include #include #include /* Urgh, should be from linux/kcmp.h */ enum { KCMP_FILE, KCMP_VM, KCMP_FILES, KCMP_FS, KCMP_SIGHAND, KCMP_IO, KCMP_SYSVSEM, KCMP_TYPES, }; /* * sys_kcmp() * kcmp syscall */ static inline long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) { #if defined(__NR_kcmp) errno = 0; return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); #else (void)pid1; (void)pid2; (void)type; (void)fd1; (void)fd2; errno = ENOSYS; return -1; #endif } #define KCMP(pid1, pid2, type, idx1, idx2) \ { \ int rc = sys_kcmp(pid1, pid2, type, idx1, idx2);\ \ if (rc < 0) { \ if (errno == EPERM) { \ pr_inf(stderr, capfail, name); \ break; \ } \ pr_fail_err(name, "kcmp: " # type); \ } \ if (!opt_do_run) \ break; \ } #define KCMP_VERIFY(pid1, pid2, type, idx1, idx2, res) \ { \ int rc = sys_kcmp(pid1, pid2, type, idx1, idx2);\ \ if (rc != res) { \ if (rc < 0) { \ if (errno == EPERM) { \ pr_inf(stderr, capfail, name); \ break; \ } \ pr_fail_err(name, "kcmp: " # type);\ } else { \ pr_fail(stderr, "%s: kcmp " # type \ " returned %d, expected: %d\n", \ name, rc, ret); \ } \ } \ if (!opt_do_run) \ break; \ } /* * stress_kcmp * stress sys_kcmp */ int stress_kcmp( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid1; int fd1; int ret = EXIT_SUCCESS; static const char *capfail = "%s: need CAP_SYS_PTRACE capability to run kcmp stressor, " "aborting stress test\n"; (void)instance; if ((fd1 = open("/dev/null", O_WRONLY)) < 0) { pr_fail_err(name, "open"); return EXIT_FAILURE; } again: pid1 = fork(); if (pid1 < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); (void)close(fd1); return EXIT_FAILURE; } else if (pid1 == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); /* Child */ while (opt_do_run) pause(); /* will never get here */ (void)close(fd1); exit(EXIT_SUCCESS); } else { /* Parent */ int fd2, status, pid2; setpgid(pid1, pgrp); pid2 = getpid(); if ((fd2 = open("/dev/null", O_WRONLY)) < 0) { pr_fail_err(name, "open"); ret = EXIT_FAILURE; goto reap; } do { KCMP(pid1, pid2, KCMP_FILE, fd1, fd2); KCMP(pid1, pid1, KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, KCMP_FILE, fd2, fd2); KCMP(pid1, pid2, KCMP_FILES, 0, 0); KCMP(pid1, pid1, KCMP_FILES, 0, 0); KCMP(pid2, pid2, KCMP_FILES, 0, 0); KCMP(pid1, pid2, KCMP_FS, 0, 0); KCMP(pid1, pid1, KCMP_FS, 0, 0); KCMP(pid2, pid2, KCMP_FS, 0, 0); KCMP(pid1, pid2, KCMP_IO, 0, 0); KCMP(pid1, pid1, KCMP_IO, 0, 0); KCMP(pid2, pid2, KCMP_IO, 0, 0); KCMP(pid1, pid2, KCMP_SIGHAND, 0, 0); KCMP(pid1, pid1, KCMP_SIGHAND, 0, 0); KCMP(pid2, pid2, KCMP_SIGHAND, 0, 0); KCMP(pid1, pid2, KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid1, KCMP_SYSVSEM, 0, 0); KCMP(pid2, pid2, KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid2, KCMP_VM, 0, 0); KCMP(pid1, pid1, KCMP_VM, 0, 0); KCMP(pid2, pid2, KCMP_VM, 0, 0); /* Same simple checks */ if (opt_flags & OPT_FLAGS_VERIFY) { KCMP_VERIFY(pid1, pid1, KCMP_FILE, fd1, fd1, 0); KCMP_VERIFY(pid1, pid1, KCMP_FILES, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_FS, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_IO, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_SIGHAND, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_SYSVSEM, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_VM, 0, 0, 0); KCMP_VERIFY(pid1, pid2, KCMP_SYSVSEM, 0, 0, 0); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); reap: if (fd2 >= 0) (void)close(fd2); (void)kill(pid1, SIGKILL); (void)waitpid(pid1, &status, 0); (void)close(fd1); } return ret; } #endif stress-ng-0.05.23/madvise.c0000664000175000017500000000506212702231255014050 0ustar kingking/* * Copyright (C) 2013-2016 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(__gnu_hurd__) 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_WILLNEED 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 /* * Don't use MADV_FREE 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_FREE MADV_FREE #endif */ }; #endif /* * madvise_random() * apply random madvise setting to a memory region */ int madvise_random(void *addr, const size_t length) { #if !defined(__gnu_hurd__) if (opt_flags & OPT_FLAGS_MMAP_MADVISE) { int i = (mwc32() >> 7) % SIZEOF_ARRAY(madvise_options); return madvise(addr, length, madvise_options[i]); } #else (void)addr; (void)length; #endif return 0; } stress-ng-0.05.23/stress-null.c0000664000175000017500000000366712702231255014724 0ustar kingking/* * Copyright (C) 2013-2016 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 writing to /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_fail_err(name, "open"); return EXIT_FAILURE; } memset(buffer, 0xff, sizeof(buffer)); do { ssize_t ret; ret = write(fd, buffer, sizeof(buffer)); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno) { pr_fail_err(name, "write"); (void)close(fd); return EXIT_FAILURE; } continue; } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); (void)close(fd); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-sigpending.c0000664000175000017500000000475212702231255016075 0ustar kingking/* * Copyright (C) 2013-2016 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" /* * stress_usr1_handler() * SIGUSR1 signal handler */ static void MLOCKED stress_usr1_handler(int dummy) { (void)dummy; } /* * stress_sigpending * stress sigpending system call */ int stress_sigpending( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { sigset_t sigset; const pid_t mypid = getpid(); (void)instance; if (stress_sighandler(name, SIGUSR1, stress_usr1_handler, NULL) < 0) return EXIT_FAILURE; do { sigemptyset(&sigset); sigaddset(&sigset, SIGUSR1); if (sigprocmask(SIG_SETMASK, &sigset, NULL) < 0) { pr_fail_err(name, "sigprocmask"); return EXIT_FAILURE; } (void)kill(mypid, SIGUSR1); if (sigpending(&sigset) < 0) { pr_fail_err(name, "sigpending"); continue; } /* We should get a SIGUSR1 here */ if (!sigismember(&sigset, SIGUSR1)) { pr_fail_err(name, "sigismember"); continue; } /* Unmask signal, signal is handled */ sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); /* And it is no longer pending */ if (sigpending(&sigset) < 0) { pr_fail_err(name, "sigpending"); continue; } if (sigismember(&sigset, SIGUSR1)) { pr_fail_err(name, "sigismember"); continue; } /* Success! */ (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } stress-ng-0.05.23/stress-stack.c0000664000175000017500000001106312702231255015044 0ustar kingking/* * Copyright (C) 2013-2016 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 sigjmp_buf jmp_env; /* * stress_segvhandler() * SEGV handler */ static void MLOCKED 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) { uint8_t stack[SIGSTKSZ]; stack_t ss; pid_t pid; /* * 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_fail_err(name, "sigaltstack"); return EXIT_FAILURE; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; 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 */ setpgid(pid, pgrp); 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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); setpgid(0, pgrp); stress_parent_died_alarm(); 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_fail_err(name, "sigaction"); return EXIT_FAILURE; } if (sigaction(SIGBUS, &new_action, NULL) < 0) { pr_fail_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() */ if (opt_flags & OPT_STACK_FILL) memset(ptr, 0, 256 * KB); else *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.05.23/stress-nice.c0000664000175000017500000000477312702231255014667 0ustar kingking/* * Copyright (C) 2013-2016 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 */ setpgid(0, pgrp); stress_parent_died_alarm(); 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; setpgid(pid, pgrp); /* 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.05.23/stress-pthread.c0000664000175000017500000001507012702231255015370 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_PTHREAD) #include #include #include #include #include #include #include #include #include #if defined(__linux__) /* For get_robust_list on Linux: */ #include #if defined(__NR_get_robust_list) #include #include #endif #endif static uint64_t opt_pthread_max = DEFAULT_PTHREAD; static bool set_pthread_max = false; 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) { set_pthread_max = true; opt_pthread_max = get_uint64_byte(optarg); check_range("pthread-max", opt_pthread_max, MIN_PTHREAD, MAX_PTHREAD); } void stress_adjust_pthread_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); } } #if defined(__linux__) && defined(__NR_get_robust_list) static inline long sys_get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr) { return syscall(__NR_get_robust_list, pid, head_ptr, len_ptr); } #endif /* * stress_pthread_func() * pthread that exits immediately */ static void *stress_pthread_func(void *ctxt) { uint8_t stack[SIGSTKSZ]; stack_t ss; static void *nowt = NULL; int ret; #if defined(__linux__) && defined(__NR_get_robust_list) struct robust_list_head *head_ptr; size_t len_ptr; #endif (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 totally unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_fail_err("pthread", "sigaltstack"); goto die; } #if defined(__linux__) && defined(__NR_get_robust_list) /* * Check that get_robust_list() works OK */ if (sys_get_robust_list(0, &head_ptr, &len_ptr) < 0) { if (errno != ENOSYS) { pr_fail_err("pthread", "get_robust_list"); goto die; } } #endif /* * Bump count of running threads */ ret = pthread_mutex_lock(&mutex); if (ret) { pr_fail_errno("pthread", "mutex lock", ret); goto die; } pthread_count++; ret = pthread_mutex_unlock(&mutex); if (ret) { pr_fail_errno("pthread", "mutex unlock", ret); goto die; } /* * Wait for controlling thread to * indicate it is time to die */ ret = pthread_mutex_lock(&mutex); if (ret) { pr_fail_errno("pthread", "mutex unlock", ret); goto die; } while (!thread_terminate) { ret = pthread_cond_wait(&cond, &mutex); if (ret) { pr_fail_errno("pthread", "pthread condition wait", ret); break; } } ret = pthread_mutex_unlock(&mutex); if (ret) pr_fail_errno("pthread", "mutex unlock", ret); 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; if (!set_pthread_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_pthread_max = MAX_PTHREAD; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_pthread_max = MIN_PTHREAD; } sigfillset(&set); do { uint64_t i, j; int ret; thread_terminate = false; pthread_count = 0; for (i = 0; (i < opt_pthread_max) && (!max_ops || *counter < max_ops); i++) { ret = pthread_create(&pthreads[i], NULL, stress_pthread_func, NULL); if (ret) { /* Out of resources, don't try any more */ if (ret == EAGAIN) { limited++; break; } /* Something really unexpected */ pr_fail_errno(name, "pthread create", ret); 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; ret = pthread_mutex_lock(&mutex); if (ret) { pr_fail_errno(name, "mutex lock", ret); ok = false; goto reap; } all_running = (pthread_count == i); ret = pthread_mutex_unlock(&mutex); if (ret) { pr_fail_errno(name, "mutex unlock", ret); ok = false; goto reap; } if (all_running) break; } ret = pthread_mutex_lock(&mutex); if (ret) { pr_fail_errno(name, "mutex lock", ret); ok = false; goto reap; } thread_terminate = true; ret = pthread_cond_broadcast(&cond); if (ret) { pr_fail_errno(name, "pthread condition broadcast", ret); ok = false; /* fall through and unlock */ } ret = pthread_mutex_unlock(&mutex); if (ret) { pr_fail_errno(name, "mutex unlock", ret); ok = false; } reap: for (j = 0; j < i; j++) { ret = pthread_join(pthreads[j], NULL); if (ret) { pr_fail_errno(name, "pthread join", ret); ok = false; } } } while (ok && opt_do_run && (!max_ops || *counter < max_ops)); if (limited) { pr_inf(stdout, "%s: %.2f%% of iterations could not reach " "requested %" PRIu64 " threads (instance %" PRIu32 ")\n", name, 100.0 * (double)limited / (double)attempted, opt_pthread_max, instance); } (void)pthread_cond_destroy(&cond); (void)pthread_mutex_destroy(&mutex); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-userfaultfd.c0000664000175000017500000001710212702231255016263 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_USERFAULTFD) #include #include #include #include #include #include #include #include #include #include #include #define STACK_SIZE (64 * 1024) /* Context for clone */ typedef struct { uint8_t *data; const char *name; uint64_t *counter; uint64_t max_ops; size_t page_size; size_t sz; pid_t parent; } context_t; static size_t opt_userfaultfd_bytes = DEFAULT_MMAP_BYTES; static bool set_userfaultfd_bytes = false; static int sys_userfaultfd(int flags) { return syscall(__NR_userfaultfd, flags); } void stress_set_userfaultfd_bytes(const char *optarg) { set_userfaultfd_bytes = true; opt_userfaultfd_bytes = (size_t)get_uint64_byte(optarg); check_range("userfaultfd-bytes", opt_userfaultfd_bytes, MIN_MMAP_BYTES, MAX_MMAP_BYTES); } /* * stress_userfaultfd_child() * generate page faults for parent to handle */ static int stress_userfaultfd_child(void *arg) { context_t *c = (context_t *)arg; do { uint8_t *ptr, *end = c->data + c->sz; /* hint we don't need these pages */ if (madvise(c->data, c->sz, MADV_DONTNEED) < 0) { pr_fail_err(c->name, "userfaultfd madvise failed"); (void)kill(c->parent, SIGALRM); return -1; } /* and trigger some page faults */ for (ptr = c->data; ptr < end; ptr += c->page_size) *ptr = 0xff; } while (opt_do_run && (!c->max_ops || *c->counter < c->max_ops)); return 0; } /* * handle_page_fault() * handle a write page fault caused by child */ static inline int handle_page_fault( const char *name, int fd, uint8_t *addr, void *zero_page, uint8_t *data_start, uint8_t *data_end, size_t page_size) { struct uffdio_copy copy; if ((addr < data_start) || (addr >= data_end)) { pr_fail_err(name, "userfaultfd page fault address out of range"); return -1; } copy.copy = 0; copy.mode = 0; copy.dst = (unsigned long)addr; copy.src = (unsigned long)zero_page; copy.len = page_size; if (ioctl(fd, UFFDIO_COPY, ©) < 0) { pr_fail_err(name, "userfaultfd page fault copy ioctl failed"); return -1; } return 0; } /* * stress_userfaultfd() * stress userfaultfd */ int stress_userfaultfd( 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; uint8_t *data; void *zero_page = NULL; int fd, status, rc = EXIT_SUCCESS; const unsigned int uffdio_copy = 1 << _UFFDIO_COPY; pid_t pid; struct uffdio_api api; struct uffdio_register reg; context_t c; /* Child clone stack */ static uint8_t stack[STACK_SIZE]; const ssize_t stack_offset = stress_get_stack_direction(&fd) * (STACK_SIZE - 64); uint8_t *stack_top = stack + stack_offset; (void)instance; if (!set_userfaultfd_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_userfaultfd_bytes = MAX_MMAP_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_userfaultfd_bytes = MIN_MMAP_BYTES; } sz = opt_userfaultfd_bytes & ~(page_size - 1); if (posix_memalign(&zero_page, page_size, page_size)) { rc = exit_status(errno); pr_err(stderr, "%s: zero page allocation failed\n", name); return rc; } data = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (data == MAP_FAILED) { rc = exit_status(errno); pr_err(stderr, "%s: mmap failed\n", name); goto free_zeropage; } /* Get userfault fd */ if ((fd = sys_userfaultfd(0)) < 0) { rc = exit_status(errno); pr_err(stderr, "%s: userfaultfd failed, errno = %d (%s)\n", name, errno, strerror(errno)); goto unmap_data; } /* API sanity check */ memset(&api, 0, sizeof(api)); api.api = UFFD_API; api.features = 0; if (ioctl(fd, UFFDIO_API, &api) < 0) { pr_err(stderr, "%s: ioctl UFFDIO_API failed, errno = %d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto unmap_data; } if (api.api != UFFD_API) { pr_err(stderr, "%s: ioctl UFFDIO_API API check failed\n", name); rc = EXIT_FAILURE; goto unmap_data; } /* Register fault handling mode */ memset(®, 0, sizeof(reg)); reg.range.start = (unsigned long)data; reg.range.len = sz; reg.mode = UFFDIO_REGISTER_MODE_MISSING; if (ioctl(fd, UFFDIO_REGISTER, ®) < 0) { pr_err(stderr, "%s: ioctl UFFDIO_REGISTER failed, errno = %d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto unmap_data; } /* OK, so do we have copy supported? */ if ((reg.ioctls & uffdio_copy) != uffdio_copy) { pr_err(stderr, "%s: ioctl UFFDIO_REGISTER did not support _UFFDIO_COPY\n", name); rc = EXIT_FAILURE; goto unmap_data; } /* Set up context for child */ c.name = name; c.data = data; c.sz = sz; c.max_ops = max_ops; c.page_size = page_size; c.counter = counter; c.parent = getpid(); /* * We need to clone the child and share the same VM address space * as parent so we can perform the page fault handling */ pid = clone(stress_userfaultfd_child, stack_top, SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_VM, &c); if (pid < 0) { pr_err(stderr, "%s: fork failed, errno = %d (%s)\n", name, errno, strerror(errno)); goto unreg; } /* Parent */ do { struct uffd_msg msg; ssize_t ret; /* check we should break out before we block on the read */ if (!opt_do_run) break; if ((ret = read(fd, &msg, sizeof(msg))) < 0) { if (errno == EINTR) continue; pr_fail_err(name, "read userfaultfd"); if (!opt_do_run) break; continue; } /* We only expect a page fault event */ if (msg.event != UFFD_EVENT_PAGEFAULT) { pr_fail_err(name, "userfaultfd msg not pagefault event"); continue; } /* We only expect a write fault */ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)) { pr_fail_err(name, "userfaultfd msg not write pahge fault event"); continue; } /* Go handle the page fault */ if (handle_page_fault(name, fd, (uint8_t *)(ptrdiff_t)msg.arg.pagefault.address, zero_page, data, data + sz, page_size) < 0) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Run it over, zap child */ (void)kill(pid, SIGKILL); if (waitpid(pid, &status, 0) < 0) { pr_dbg(stderr, "%s: waitpid failed, errno = %d (%s)\n", name, errno, strerror(errno)); } unreg: if (ioctl(fd, UFFDIO_UNREGISTER, ®) < 0) { pr_err(stderr, "%s: ioctl UFFDIO_UNREGISTER failed, errno = %d (%s)\n", name, errno, strerror(errno)); rc = EXIT_FAILURE; goto unmap_data; } unmap_data: (void)munmap(data, sz); free_zeropage: free(zero_page); return rc; } #endif stress-ng-0.05.23/stress-fallocate.c0000664000175000017500000001137312702231255015675 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_FALLOCATE) #include #include #include #include #include #include #include #include static off_t opt_fallocate_bytes = DEFAULT_FALLOCATE_BYTES; static bool set_fallocate_bytes = false; void stress_set_fallocate_bytes(const char *optarg) { set_fallocate_bytes = true; opt_fallocate_bytes = (off_t)get_uint64_byte(optarg); check_range("fallocate-bytes", opt_fallocate_bytes, MIN_FALLOCATE_BYTES, MAX_FALLOCATE_BYTES); } #if defined(__linux__) static const int modes[] = { 0, #if defined(FALLOC_FL_KEEP_SIZE) FALLOC_FL_KEEP_SIZE, #endif #if defined(FALLOC_FL_KEEP_SIZE) && defined(FALLOC_FL_PUNCH_HOLE) FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, #endif #if defined(FALLOC_FL_ZERO_RANGE) FALLOC_FL_ZERO_RANGE, #endif #if defined(FALLOC_FL_COLLAPSE_RANGE) FALLOC_FL_COLLAPSE_RANGE, #endif #if defined(FALLOC_FL_INSERT_RANGE) FALLOC_FL_INSERT_RANGE, #endif }; #endif /* * 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, ret; char filename[PATH_MAX]; uint64_t ftrunc_errs = 0; if (!set_fallocate_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_fallocate_bytes = MAX_FALLOCATE_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_fallocate_bytes = MIN_FALLOCATE_BYTES; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); (void)umask(0077); if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { ret = exit_status(errno); pr_fail_err(name, "open"); (void)stress_temp_dir_rm(name, pid, instance); return ret; } (void)unlink(filename); do { (void)posix_fallocate(fd, (off_t)0, opt_fallocate_bytes); if (!opt_do_run) break; (void)fsync(fd); if (opt_flags & OPT_FLAGS_VERIFY) { struct stat buf; if (fstat(fd, &buf) < 0) pr_fail(stderr, "%s: fstat on file failed", name); else if (buf.st_size != opt_fallocate_bytes) pr_fail(stderr, "%s: file size %jd does not match size the expected file size of %jd\n", name, (intmax_t)buf.st_size, (intmax_t)opt_fallocate_bytes); } if (ftruncate(fd, 0) < 0) ftrunc_errs++; if (!opt_do_run) break; (void)fsync(fd); if (opt_flags & OPT_FLAGS_VERIFY) { struct stat buf; if (fstat(fd, &buf) < 0) pr_fail(stderr, "%s: fstat on file failed", name); else if (buf.st_size != (off_t)0) pr_fail(stderr, "%s: file size %jd does not match size the expected file size of 0\n", name, (intmax_t)buf.st_size); } if (ftruncate(fd, opt_fallocate_bytes) < 0) ftrunc_errs++; (void)fsync(fd); if (ftruncate(fd, 0) < 0) ftrunc_errs++; (void)fsync(fd); #if defined(__linux__) if (SIZEOF_ARRAY(modes) > 1) { /* * non-portable Linux fallocate() */ int i; (void)fallocate(fd, 0, (off_t)0, opt_fallocate_bytes); if (!opt_do_run) break; (void)fsync(fd); for (i = 0; i < 64; i++) { off_t offset = (mwc64() % opt_fallocate_bytes) & ~0xfff; int j = (mwc32() >> 8) % SIZEOF_ARRAY(modes); (void)fallocate(fd, modes[j], offset, 64 * KB); if (!opt_do_run) break; (void)fsync(fd); } if (ftruncate(fd, 0) < 0) ftrunc_errs++; (void)fsync(fd); } #endif (*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.05.23/stress-vm.c0000664000175000017500000012506012702231255014364 0ustar kingking/* * Copyright (C) 2013-2016 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) #define VM_ROWHAMMER_LOOPS (1000000) #define NO_MEM_RETRIES_MAX (100) /* * 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 bool set_vm_bytes = false; static int opt_vm_flags = 0; /* VM mmap flags */ static const stress_vm_stressor_info_t *opt_vm_stressor; static const 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) { set_vm_bytes = true; 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 = mwc64(); z = mwc64(); mwc_seed(w, z); for (ptr = (uint64_t *)buf; ptr < buf_end; ) { *(ptr++) = mwc64(); } mwc_seed(w, z); for (bit_errors = 0, ptr = (uint64_t *)buf; ptr < buf_end; ) { uint64_t val = mwc64(); 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 = mwc64(); 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 = mwc64(); 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 = mwc64(); 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 = mwc64(); 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 = mwc8(); 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 = mwc64(); w1 = mwc64(); if ((swaps = calloc(chunks, sizeof(size_t))) == NULL) { pr_fail_dbg("stress-vm", "calloc"); return 0; } for (i = 0; i < chunks; i++) { swaps[i] = (mwc64() % chunks) * chunk_sz; } mwc_seed(w1, z1); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc8(); 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 = mwc8(); 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 = mwc64(); z = mwc64(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc8(); *(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 = mwc8(); 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 = mwc64(); z = mwc64(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc8(); *(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 = mwc8(); 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 = mwc64(); z = mwc64(); mwc_seed(w, z); for (ptr = buf; ptr < buf_end; ptr += chunk_sz) { uint8_t val = mwc8(); *(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 = mwc8(); 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 = mwc64() % sz; uint8_t bit = mwc32() & 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 = mwc64() % sz; uint8_t bit = mwc32() & 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 = mwc64(); z = mwc64(); mwc_seed(w, z); for (ptr = (uint64_t *)buf; ptr < buf_end; ptr += chunk_sz) { *(ptr + 0) = mwc64(); *(ptr + 1) = mwc64(); *(ptr + 2) = mwc64(); *(ptr + 3) = mwc64(); *(ptr + 4) = mwc64(); *(ptr + 5) = mwc64(); *(ptr + 6) = mwc64(); *(ptr + 7) = mwc64(); 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) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 1) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 2) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 3) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 4) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 5) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 6) ^ mwc64()); bit_errors += stress_vm_count_bits(*(ptr + 7) ^ mwc64()); 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_rowhammer() * */ static size_t stress_vm_rowhammer( uint8_t *buf, const size_t sz, uint64_t *counter, const uint64_t max_ops) { size_t bit_errors = 0; uint32_t *buf32 = (uint32_t *)buf; static uint32_t val = 0xff5a00a5; const size_t n = sz / sizeof(uint32_t); register size_t j; (void)max_ops; if (!n) { pr_dbg(stderr, "rowhammer: zero uint32_t integers could " "be hammered, aborting\n"); return 0; } (void)mincore_touch_pages(buf, sz); for (j = 0; j < n; j++) buf32[j] = val; register volatile uint32_t *addr0, *addr1; register size_t errors = 0; /* Pick two random addresses */ addr0 = &buf32[(mwc64() << 12) % n]; addr1 = &buf32[(mwc64() << 12) % n]; /* Hammer the rows */ for (j = VM_ROWHAMMER_LOOPS / 4; j; j--) { *addr0; *addr1; clflush(addr0); clflush(addr1); *addr0; *addr1; clflush(addr0); clflush(addr1); *addr0; *addr1; clflush(addr0); clflush(addr1); *addr0; *addr1; clflush(addr0); clflush(addr1); } for (j = 0; j < n; j++) if (buf32[j] != val) errors++; if (errors) { bit_errors += errors; pr_dbg(stderr, "rowhammer: %zu errors on addresses " "%p and %p\n", errors, addr0, addr1); } (*counter) += VM_ROWHAMMER_LOOPS; val = (val >> 31) | (val << 1); stress_vm_check("rowhammer", bit_errors); return bit_errors; } /* * 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 const 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 }, { "rowhammer", stress_vm_rowhammer }, { "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 const *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(); size_t buf_sz; if (!set_vm_bytes) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_vm_bytes = MAX_VM_BYTES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_vm_bytes = MIN_VM_BYTES; } buf_sz = opt_vm_bytes & ~(page_size - 1); again: if (!opt_do_run) return EXIT_SUCCESS; pid = fork(); if (pid < 0) { if (errno == EAGAIN) goto again; 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 */ setpgid(pid, pgrp); 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); (void)waitpid(pid, &status, 0); } else if (WIFSIGNALED(status)) { pr_dbg(stderr, "%s: child died: %s (instance %d)\n", name, stress_strsignal(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) { int no_mem_retries = 0; setpgid(0, pgrp); stress_parent_died_alarm(); /* Make sure this is killable by OOM killer */ set_oom_adjustment(name, true); do { if (no_mem_retries >= NO_MEM_RETRIES_MAX) { pr_err(stderr, "%s: gave up trying to mmap, no available memory\n", name); break; } if (!keep || (buf == NULL)) { if (!opt_do_run) return EXIT_SUCCESS; buf = mmap(NULL, buf_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | opt_vm_flags, -1, 0); if (buf == MAP_FAILED) { buf = NULL; no_mem_retries++; usleep(100000); continue; /* Try again */ } (void)madvise_random(buf, buf_sz); } no_mem_retries = 0; (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.05.23/stress-udp.c0000664000175000017500000001440512702231255014532 0ustar kingking/* * Copyright (C) 2013-2016 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" /* See bugs section of udplite(7) */ #if !defined(SOL_UDPLITE) #define SOL_UDPLITE (136) #endif #if !defined(UDPLITE_SEND_CSCOV) #define UDPLITE_SEND_CSCOV (10) #endif #if !defined(UDPLITE_RECV_CSCOV) #define UDPLITE_RECV_CSCOV (11) #endif 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(DOMAIN_ALL, "udp-domain", name, &opt_udp_domain); } /* * handle_udp_sigalrm() * catch SIGALRM */ static void MLOCKED 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; #if defined(OPT_UDP_LITE) int proto = (opt_flags & OPT_FLAGS_UDP_LITE) ? IPPROTO_UDPLITE : IPPROTO_UDP; #else int proto = 0; #endif #if defined(OPT_UDP_LITE) if ((proto == IPPROTO_UDPLITE) && (opt_udp_domain == AF_UNIX)) { proto = 0; if (instance == 0) { pr_inf(stderr, "%s: disabling UDP-Lite as it is not " "available for UNIX domain UDP\n", name); } } #endif pr_dbg(stderr, "%s: process [%d] using udp port %d\n", name, getpid(), opt_udp_port + instance); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { /* Child, client */ struct sockaddr *addr = NULL; setpgid(0, pgrp); stress_parent_died_alarm(); do { char buf[UDP_BUF]; socklen_t len; int fd; int j = 0; #if defined(OPT_UDP_LITE) int val; #endif if ((fd = socket(opt_udp_domain, SOCK_DGRAM, proto)) < 0) { pr_fail_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); #if defined(OPT_UDP_LITE) if (proto == IPPROTO_UDPLITE) { val = 8; /* Just the 8 byte header */ if (setsockopt(fd, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int)) < 0) { pr_fail_dbg(name, "setsockopt"); (void)close(fd); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } } #endif 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_fail_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) && addr) { 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; #if defined(OPT_UDP_LITE) int val; #endif socklen_t addr_len = 0; struct sockaddr *addr = NULL; setpgid(pid, pgrp); if (stress_sighandler(name, SIGALRM, handle_udp_sigalrm, NULL) < 0) { rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_udp_domain, SOCK_DGRAM, proto)) < 0) { pr_fail_dbg(name, "socket"); rc = EXIT_FAILURE; goto die; } stress_set_sockaddr(name, instance, ppid, opt_udp_domain, opt_udp_port, &addr, &addr_len); #if defined(OPT_UDP_LITE) if (proto == IPPROTO_UDPLITE) { val = 8; /* Just the 8 byte header */ if (setsockopt(fd, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &val, sizeof(int)) < 0) { pr_fail_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } } #endif if (bind(fd, addr, addr_len) < 0) { pr_fail_dbg(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_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_fail_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) && addr) { 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.05.23/stress-dup.c0000664000175000017500000000404712702231255014533 0ustar kingking/* * Copyright (C) 2013-2016 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_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]; const size_t max_fd = stress_get_file_limit(); size_t i; (void)instance; fds[0] = open("/dev/zero", O_RDONLY); if (fds[0] < 0) { pr_fail_dbg(name, "open on /dev/zero"); return EXIT_FAILURE; } do { for (i = 1; i < max_fd; i++) { fds[i] = dup(fds[0]); if (fds[i] < 0) break; fds[i] = dup2(fds[0], fds[i]); if (fds[i] < 0) break; if (!opt_do_run) break; (*counter)++; } for (i = 1; i < max_fd; 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.05.23/stress-ptrace.c0000664000175000017500000000703112702231255015215 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_PTRACE) #include #include #include #include #include #include #include #include #include #include #include /* * main syscall ptrace loop */ static inline bool stress_syscall_wait( const char *name, const pid_t pid) { while (opt_do_run) { int status; if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { pr_fail_dbg(name, "ptrace"); return true; } if (waitpid(pid, &status, 0) < 0) { pr_fail_dbg(name, "waitpid"); return true; } if (WIFSTOPPED(status) && (WSTOPSIG(status) & 0x80)) return false; if (WIFEXITED(status)) return true; } return true; } /* * stress_ptrace() * stress ptracing */ int stress_ptrace( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; (void)instance; pid = fork(); if (pid < 0) { pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); /* * Child to be traced, we abort if we detect * we are already being traced by someone else * as this makes life way too complex */ if (ptrace(PTRACE_TRACEME) != 0) { pr_fail(stderr, "%s: ptrace child being traced " "already, aborting\n", name); _exit(0); } /* Wait for parent to start tracing me */ kill(getpid(), SIGSTOP); /* * A simple mix of system calls */ while (opt_do_run) { (void)getppid(); (void)getgid(); (void)getegid(); (void)getuid(); (void)geteuid(); (void)getpgrp(); (void)time(NULL); } _exit(0); } else { /* Parent to do the tracing */ int status; setpgid(pid, pgrp); if (waitpid(pid, &status, 0) < 0) { pr_fail_dbg(name, "waitpid"); return EXIT_FAILURE; } if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { pr_fail_dbg(name, "ptrace"); return EXIT_FAILURE; } do { /* * We do two of the following per syscall, * one at the start, and one at the end to catch * the return. In this stressor we don't really * care which is which, we just care about counting * them */ if (stress_syscall_wait(name, pid)) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Terminate child */ (void)kill(pid, SIGKILL); if (waitpid(pid, &status, 0) < 0) pr_fail_dbg(name, "waitpid"); } return EXIT_SUCCESS; } #endif stress-ng-0.05.23/COPYING0000664000175000017500000004325412702231255013314 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.05.23/stress-cpu-online.c0000664000175000017500000000740312702231255016013 0ustar kingking/* * Copyright (C) 2016 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(STRESS_CPU_ONLINE) #include #include #include #include #include #include #include /* * stress_cpu_online_set() * set a specified CPUs online or offline */ int stress_cpu_online_set( const char *name, const int32_t cpu, const int setting) { char filename[PATH_MAX]; char data[3]; ssize_t ret; int fd, rc = EXIT_SUCCESS; snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%" PRId32 "/online", cpu); fd = open(filename, O_WRONLY); if (fd < 0) { pr_fail_err(name, "open"); return EXIT_FAILURE; } data[0] = '0' + setting; data[1] = '\n'; data[2] = '\0'; ret = write(fd, data, 3); if (ret != 3) { if ((errno != EAGAIN) && (errno != EINTR)) { pr_fail_err(name, "write"); rc = EXIT_FAILURE; } } (void)close(fd); return rc; } /* * stress_cpu_online * stress twiddling CPUs online/offline */ int stress_cpu_online( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const int32_t cpus = stress_get_processors_configured(); int32_t i, cpu_online_count = 0; bool *cpu_online; int rc = EXIT_SUCCESS; (void)instance; if (geteuid() != 0) { if (instance == 0) pr_inf(stderr, "%s: need root privilege to run " "this stressor\n", name); /* Not strictly a test failure */ return EXIT_SUCCESS; } if ((cpus < 1) || (cpus > 65536)) { pr_inf(stderr, "%s: too few or too many CPUs (found %" PRId32 ")\n", name, cpus); return EXIT_FAILURE; } cpu_online = calloc(cpus, sizeof(bool)); if (!cpu_online) { pr_err(stderr, "%s: out of memory\n", name); return EXIT_FAILURE; } /* * Determine how many CPUs we can online/offline via * the online sys interface */ for (i = 0; i < cpus; i++) { char filename[PATH_MAX]; int ret; snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%" PRId32 "/online", i); ret = access(filename, O_RDWR); if (ret == 0) { cpu_online[i] = true; cpu_online_count++; } } if (cpu_online_count == 0) { pr_inf(stderr, "%s: no CPUs can be set online/offline\n", name); free(cpu_online); return EXIT_FAILURE; } /* * Now randomly offline/online them all */ do { unsigned long cpu = mwc32() % cpus; if (cpu_online[cpu]) { rc = stress_cpu_online_set(name, cpu, 0); if (rc != EXIT_SUCCESS) break; rc = stress_cpu_online_set(name, cpu, 1); if (rc != EXIT_SUCCESS) break; (*counter)++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); /* * Force CPUs all back online */ for (i = 0; i < cpus; i++) { if (cpu_online[i]) (void)stress_cpu_online_set(name, i, 1); } free(cpu_online); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/README0000664000175000017500000000310412702231255013127 0ustar kingkingstress-ng 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 features: * over 130 stress tests * over 50 CPU specific stress tests that exercise floating point, integer, bit manipulation and control flow * over 20 virtual memory stress tests 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. 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. 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. To build, the following libraries are required: libattr1-dev, libkeyutils-dev, libbsd-dev To build on BSD systems, one requires GNU make For more information, see: http://kernel.ubuntu.com/~cking/stress-ng/ stress-ng-0.05.23/stress-clone.c0000664000175000017500000001341212702231255015037 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_CLONE) #include #include #include #include #include #include #define CLONE_STACK_SIZE (16*1024) static uint64_t opt_clone_max = DEFAULT_ZOMBIES; static bool set_clone_max = false; typedef struct clone { pid_t pid; struct clone *next; char stack[CLONE_STACK_SIZE]; } clone_t; typedef struct { clone_t *head; /* Head of clone procs list */ clone_t *tail; /* Tail of clone procs list */ clone_t *free; /* List of free'd clones */ uint64_t length; /* Length of list */ } clone_list_t; static clone_list_t clones; /* * A random selection of clone flags that are worth exercising */ static const int flags[] = { 0, #if defined(CLONE_FILES) CLONE_FILES, #endif #if defined(CLONE_FS) CLONE_FS, #endif #if defined(CLONE_IO) CLONE_IO, #endif #if defined(CLONE_NEWIPC) CLONE_NEWIPC, #endif #if defined(CLONE_NEWNET) CLONE_NEWNET, #endif #if defined(CLONE_NEWNS) CLONE_NEWNS, #endif #if defined(CLONE_NEWUSER) CLONE_NEWUSER, #endif #if defined(CLONE_NEWUTS) CLONE_NEWUTS, #endif #if defined(CLONE_SIGHAND) CLONE_SIGHAND, #endif #if defined(CLONE_SYSVSEM) CLONE_SYSVSEM, #endif #if defined(CLONE_UNTRACED) CLONE_UNTRACED, #endif }; static const int unshare_flags[] = { #if defined(CLONE_FILES) CLONE_FILES, #endif #if defined(CLONE_FS) CLONE_FS, #endif #if defined(CLONE_NEWIPC) CLONE_NEWIPC, #endif #if defined(CLONE_NEWNET) CLONE_NEWNET, #endif #if defined(CLONE_NEWNS) CLONE_NEWNS, #endif #if defined(CLONE_NEWUTS) CLONE_NEWUTS, #endif #if defined(CLONE_SYSVSEM) CLONE_SYSVSEM, #endif }; /* * stress_clone_new() * allocate a new clone, add to end of list */ static clone_t *stress_clone_new(void) { clone_t *new; if (clones.free) { /* Pop an old one off the free list */ new = clones.free; clones.free = new->next; new->next = NULL; } else { new = calloc(1, sizeof(*new)); if (!new) return NULL; } if (clones.head) clones.tail->next = new; else clones.head = new; clones.tail = new; clones.length++; return new; } /* * stress_clone_head_remove * reap a clone and remove a clone from head of list, put it onto * the free clone list */ void stress_clone_head_remove(void) { if (clones.head) { int status; clone_t *head = clones.head; (void)waitpid(clones.head->pid, &status, __WCLONE); if (clones.tail == clones.head) { clones.tail = NULL; clones.head = NULL; } else { clones.head = head->next; } /* Shove it on the free list */ head->next = clones.free; clones.free = head; clones.length--; } } /* * stress_clone_free() * free the clones off the clone free lists */ void stress_clone_free(void) { while (clones.head) { clone_t *next = clones.head->next; free(clones.head); clones.head = next; } while (clones.free) { clone_t *next = clones.free->next; free(clones.free); clones.free = next; } } /* * stress_set_clone_max() * set maximum number of clones allowed */ void stress_set_clone_max(const char *optarg) { set_clone_max = true; opt_clone_max = get_uint64_byte(optarg); check_range("clone-max", opt_clone_max, MIN_ZOMBIES, MAX_ZOMBIES); } /* * clone_func() * clone thread just returns immediately */ static int clone_func(void *arg) { size_t i; (void)arg; for (i = 0; i < SIZEOF_ARRAY(unshare_flags); i++) { (void)unshare(unshare_flags[i]); } return 0; } /* * stress_clone() * stress by cloning and exiting */ int stress_clone( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint64_t max_clones = 0; const ssize_t stack_offset = stress_get_stack_direction(&max_clones) * (CLONE_STACK_SIZE - 64); (void)instance; if (!set_clone_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_clone_max = MAX_ZOMBIES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_clone_max = MIN_ZOMBIES; } do { if (clones.length < opt_clone_max) { clone_t *clone_info; char *stack_top; int flag = flags[mwc32() % SIZEOF_ARRAY(flags)]; clone_info = stress_clone_new(); if (!clone_info) break; stack_top = clone_info->stack + stack_offset; clone_info->pid = clone(clone_func, stack_top, flag, NULL); if (clone_info->pid == -1) { /* * Reached max forks or error * (e.g. EPERM)? .. then reap */ stress_clone_head_remove(); continue; } if (max_clones < clones.length) max_clones = clones.length; (*counter)++; } else { stress_clone_head_remove(); } } while (opt_do_run && (!max_ops || *counter < max_ops)); pr_inf(stderr, "%s: created a maximum of %" PRIu64 " clones\n", name, max_clones); /* And reap */ while (clones.head) { stress_clone_head_remove(); } /* And free */ stress_clone_free(); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-cap.c0000664000175000017500000000551512702231255014507 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_CAP) #include #include #include #include #include #include #include #include static int stress_capget_pid( const char *name, const pid_t pid, uint64_t *counter, const bool exists) { int ret; struct __user_cap_header_struct uch; struct __user_cap_data_struct ucd; uch.version = _LINUX_CAPABILITY_VERSION_3; uch.pid = pid; memset(&ucd, 0, sizeof ucd); ret = capget(&uch, &ucd); if (ret < 0) { if (((errno == ESRCH) && exists) || (errno != ESRCH)) { pr_fail(stderr, "%s: capget on pid %d failed: errno=%d (%s)\n", name, pid, errno, strerror(errno)); } } (*counter)++; return ret; } /* * stress_cap * stress capabilities (trivial) */ int stress_cap( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); const pid_t ppid = getppid(); (void)instance; do { DIR *dir; stress_capget_pid(name, 1, counter, true); if (!opt_do_run || (max_ops && *counter >= max_ops)) break; stress_capget_pid(name, pid, counter, true); if (!opt_do_run || (max_ops && *counter >= max_ops)) break; stress_capget_pid(name, ppid, counter, false); if (!opt_do_run || (max_ops && *counter >= max_ops)) break; dir = opendir("/proc"); if (dir) { struct dirent *d; while ((d = readdir(dir)) != NULL) { pid_t p; if (!isdigit(d->d_name[0])) continue; if (sscanf(d->d_name, "%u", &p) != 1) continue; stress_capget_pid(name, p, counter, false); if (!opt_do_run || (max_ops && *counter >= max_ops)) break; } (void)closedir(dir); } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-key.c0000664000175000017500000001006512702231255014530 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_KEY) #include #include #include #include #include #include #include #define MAX_KEYS (256) static long sys_keyctl(int cmd, ...) { va_list args; long int arg0, arg1, arg2, ret; va_start(args, cmd); arg0 = va_arg(args, long int); arg1 = va_arg(args, long int); arg2 = va_arg(args, long int); ret = syscall(__NR_keyctl, cmd, arg0, arg1, arg2); va_end(args); return ret; } static key_serial_t sys_add_key( const char *type, const char *description, const void *payload, size_t plen, key_serial_t keyring) { return (key_serial_t)syscall(__NR_add_key, type, description, payload, plen, keyring); } /* * stress_key * stress key operations */ int stress_key( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { key_serial_t keys[MAX_KEYS]; pid_t ppid = getppid(); do { size_t i, n = 0; char description[64]; char payload[64]; /* Add as many keys as we are allowed */ for (n = 0; n < MAX_KEYS; n++) { snprintf(description, sizeof(description), "stress-ng-key-%u-%" PRIu32 "-%zu", ppid, instance, n); snprintf(payload, sizeof(payload), "somedata-%zu", n); keys[n] = sys_add_key("user", description, payload, strlen(payload), KEY_SPEC_PROCESS_KEYRING); if (keys[n] < 0) { if ((errno != ENOMEM) && (errno != EDQUOT)) pr_fail_err(name, "add_key"); break; } #if defined(KEYCTL_SET_TIMEOUT) if (sys_keyctl(KEYCTL_SET_TIMEOUT, keys[n], 1) < 0) pr_fail_err(name, "keyctl KEYCTL_SET_TIMEOUT"); #endif } /* And manipulate the keys */ for (i = 0; i < n; i++) { snprintf(description, sizeof(description), "stress-ng-key-%u-%" PRIu32 "-%zu", ppid, instance, i); #if defined(KEYCTL_DESCRIBE) if (sys_keyctl(KEYCTL_DESCRIBE, keys[i], description) < 0) pr_fail_err(name, "keyctl KEYCTL_DESCRIBE"); if (!opt_do_run) break; #endif snprintf(payload, sizeof(payload), "somedata-%zu", n); #if defined(KEYCTL_UPDATE) if (sys_keyctl(KEYCTL_UPDATE, keys[i], payload, strlen(payload)) < 0) { if ((errno != ENOMEM) && (errno != EDQUOT)) pr_fail_err(name, "keyctl KEYCTL_UPDATE"); } if (!opt_do_run) break; #endif #if defined(KEYCTL_READ) memset(payload, 0, sizeof(payload)); if (sys_keyctl(KEYCTL_READ, keys[i], payload, sizeof(payload)) < 0) pr_fail_err(name, "keyctl KEYCTL_READ"); if (!opt_do_run) break; #endif #if defined(KEYCTL_CLEAR) (void)sys_keyctl(KEYCTL_CLEAR, keys[i]); #endif #if defined(KEYCTL_INVALIDATE) (void)sys_keyctl(KEYCTL_INVALIDATE, keys[i]); #endif (*counter)++; } /* If we hit too many errors and bailed out early, clean up */ while (i < n) { #if defined(KEYCTL_CLEAR) (void)sys_keyctl(KEYCTL_CLEAR, keys[i]); #endif #if defined(KEYCTL_INVALIDATE) (void)sys_keyctl(KEYCTL_INVALIDATE, keys[i]); #endif i++; } } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-dentry.c0000664000175000017500000001150012702231255015240 0ustar kingking/* * Copyright (C) 2013-2016 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_RANDOM, ORDER_NONE, } dentry_order_t; typedef struct { const char *name; const dentry_order_t order; } dentry_removal_t; static const dentry_removal_t dentry_removals[] = { { "forward", ORDER_FORWARD }, { "reverse", ORDER_REVERSE }, { "stride", ORDER_STRIDE }, { "random", ORDER_RANDOM }, { NULL, ORDER_NONE }, }; static dentry_order_t order = ORDER_RANDOM; static uint64_t opt_dentries = DEFAULT_DENTRIES; static bool set_dentries = false; void stress_set_dentries(const char *optarg) { set_dentries = true; 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) { const 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(); uint64_t prime; dentry_order_t ord; ord = (order == ORDER_RANDOM) ? mwc32() % 3 : order; switch (ord) { 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: prime = stress_get_prime64(n); 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(); int ret; if (!set_dentries) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_dentries = MAX_DENTRIES; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_dentries = MIN_DENTRIES; } ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); 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) { if (errno != ENOSPC) pr_fail_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.05.23/stress-yield.c0000664000175000017500000000721412702231255015050 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_YIELD) #include #include #include #include #include #include #include #include /* * 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) { uint64_t *counters; uint64_t max_ops_per_yielder; size_t counters_sz, yielders_sz; int32_t cpus = stress_get_processors_configured(); size_t instances = stressor_instances(STRESS_YIELD); size_t yielders = 2; pid_t *pids; size_t i; /* * Ensure we always have at least 2 yielders per * CPU available to force context switching on yields */ if (cpus > 0) { if (!instances) { /* Should not happen, but avoids division by zero */ instances = 1; } cpus *= 2; yielders = cpus / instances; if (yielders < 1) yielders = 1; if (!instance) { int32_t residual = cpus - (yielders * instances); if (residual > 0) yielders += residual; } } max_ops_per_yielder = max_ops / yielders; yielders_sz = yielders * sizeof(pid_t); pids = alloca(yielders_sz); memset(pids, 0, yielders_sz); counters_sz = yielders * sizeof(uint64_t); counters = mmap(NULL, counters_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (counters == MAP_FAILED) { int rc = exit_status(errno); pr_err(stderr, "%s: mmap failed: errno=%d (%s)\n", name, errno, strerror(errno)); return rc; } memset(counters, 0, counters_sz); for (i = 0; opt_do_run && (i < yielders); i++) { pids[i] = fork(); if (pids[i] < 0) { pr_dbg(stderr, "%s: fork failed (instance %" PRIu32 ", yielder %zd): errno=%d (%s)\n", name, instance, i, errno, strerror(errno)); } else if (pids[i] == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); do { int ret; ret = sched_yield(); if ((ret < 0) && (opt_flags & OPT_FLAGS_VERIFY)) pr_fail(stderr, "%s: sched_yield failed: errno=%d (%s)\n", name, errno, strerror(errno)); counters[i]++; } while (opt_do_run && (!max_ops_per_yielder || *counter < max_ops_per_yielder)); _exit(EXIT_SUCCESS); } } do { *counter = 0; pause(); for (i = 0; i < yielders; i++) *counter += counters[i]; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Parent, wait for children */ for (i = 0; i < yielders; i++) { if (pids[i] > 0) { int status; (void)kill(pids[i], SIGKILL); (void)waitpid(pids[i], &status, 0); *counter += counters[i]; } } (void)munmap(counters, counters_sz); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-sendfile.c0000664000175000017500000000631712702231255015536 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SENDFILE) #include #include #include #include #include #include #include #include #include static int64_t opt_sendfile_size = DEFAULT_SENDFILE_SIZE; static bool set_sendfile_size = false; void stress_set_sendfile_size(const char *optarg) { set_sendfile_size = true; 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, rc = EXIT_SUCCESS; size_t sz; const pid_t pid = getpid(); if (!set_sendfile_size) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_sendfile_size = MAX_SENDFILE_SIZE; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_sendfile_size = MIN_SENDFILE_SIZE; } sz = (size_t)opt_sendfile_size; ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)umask(0077); (void)stress_temp_filename(filename, sizeof(filename), name, pid, instance, mwc32()); if ((fdin = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto dir_out; } ret = posix_fallocate(fdin, (off_t)0, (off_t)sz); if (ret < 0) { rc = exit_status(errno); pr_fail_err(name, "open"); goto dir_out; } if ((fdout = open("/dev/null", O_WRONLY)) < 0) { pr_fail_err(name, "open"); rc = EXIT_FAILURE; goto close_in; } do { off_t offset = 0; if (sendfile(fdout, fdin, &offset, sz) < 0) { if (errno == EINTR) continue; pr_fail_err(name, "sendfile"); rc = 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 rc; } #endif stress-ng-0.05.23/stress-sleep.c0000664000175000017500000001200512702231255015044 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_SLEEP) #include #include #include #include #include #include #include #include #include #include #include static uint64_t opt_sleep_max = DEFAULT_SLEEP; static bool set_sleep_max = false; static bool thread_terminate; static sigset_t set; void stress_set_sleep_max(const char *optarg) { set_sleep_max = true; opt_sleep_max = get_uint64_byte(optarg); check_range("sleep-max", opt_sleep_max, MIN_SLEEP, MAX_SLEEP); } void stress_adjust_sleep_max(uint64_t max) { if (opt_sleep_max > max) { opt_sleep_max = max; pr_inf(stdout, "re-adjusting maximum threads to " "soft limit f %" PRIu64 "\n", opt_sleep_max); } } /* * stress_pthread_func() * pthread that performs different ranges of sleeps */ static void *stress_pthread_func(void *ctxt) { uint8_t stack[SIGSTKSZ]; stack_t ss; static void *nowt = NULL; uint64_t *counter = (uint64_t *)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 totally unncessary. */ ss.ss_sp = (void *)stack; ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { pr_fail_err("pthread", "sigaltstack"); goto die; } while (!thread_terminate) { struct timespec tv; struct timeval timeout; tv.tv_sec = 0; tv.tv_nsec = 1; if (nanosleep(&tv, NULL) < 0) break; tv.tv_sec = 0; tv.tv_nsec = 10; if (nanosleep(&tv, NULL) < 0) break; tv.tv_sec = 0; tv.tv_nsec = 100; if (nanosleep(&tv, NULL) < 0) break; if (usleep(1) < 0) break; if (usleep(10) < 0) break; if (usleep(100) < 0) break; if (usleep(1000) < 0) break; if (usleep(10000) < 0) break; timeout.tv_sec = 0; timeout.tv_usec = 10; if (select(0, NULL, NULL, NULL, &timeout) < 0) break; timeout.tv_sec = 0; timeout.tv_usec = 100; if (select(0, NULL, NULL, NULL, &timeout) < 0) break; timeout.tv_sec = 0; timeout.tv_usec = 1000; if (select(0, NULL, NULL, NULL, &timeout) < 0) break; timeout.tv_sec = 0; timeout.tv_usec = 10000; if (select(0, NULL, NULL, NULL, &timeout) < 0) break; (*counter)++; } die: return &nowt; } /* * stress_sleep() * stress by many sleeping threads */ int stress_sleep( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { uint64_t i, n, c, limited = 0; uint64_t counters[MAX_SLEEP]; pthread_t pthreads[MAX_SLEEP]; int ret = EXIT_SUCCESS; bool ok = true; if (!set_sleep_max) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_sleep_max = MAX_SLEEP; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_sleep_max = MIN_SLEEP; } memset(pthreads, 0, sizeof(pthreads)); memset(counters, 0, sizeof(counters)); sigfillset(&set); for (n = 0; n < opt_sleep_max; n++) { ret = pthread_create(&pthreads[n], NULL, stress_pthread_func, &counters[n]); if (ret) { /* Out of resources, don't try any more */ if (ret == EAGAIN) { limited++; break; } /* Something really unexpected */ pr_fail_errno(name, "pthread create", ret); ret = EXIT_NO_RESOURCE; goto tidy; } /* Timed out? abort! */ if (!opt_do_run) goto tidy; } do { c = 0; usleep(10000); for (i = 0; i < n; i++) c += counters[i]; } while (ok && opt_do_run && (!max_ops || c < max_ops)); *counter = c; ret = EXIT_SUCCESS; tidy: thread_terminate = true; for (i = 0; i < n; i++) { ret = pthread_join(pthreads[i], NULL); if (ret) pr_dbg(stderr, "pthread join, ret=%d", ret); } if (limited) { pr_inf(stdout, "%s: %.2f%% of iterations could not reach " "requested %" PRIu64 " threads (instance %" PRIu32 ")\n", name, 100.0 * (double)limited / (double)opt_sleep_max, opt_sleep_max, instance); } return ret; } #endif stress-ng-0.05.23/stress-ng.c0000664000175000017500000032113412702231255014346 0ustar kingking/* * Copyright (C) 2013-2016 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 #include "stress-ng.h" #if defined(STRESS_AFFINITY) #include #endif static proc_info_t procs[STRESS_MAX]; /* Per stressor process information */ /* Various option settings and flags */ int32_t opt_sequential = DEFAULT_SEQUENTIAL; /* Number of sequential workers */ int32_t opt_all = 0; /* Number of concurrent workers */ uint64_t opt_timeout = 0; /* timeout in seconds */ uint64_t opt_flags = PR_ERROR | PR_INFO | OPT_FLAGS_MMAP_MADVISE; volatile bool opt_do_run = true; /* false to exit stressor */ volatile bool opt_do_wait = true; /* false to exit run waiter loop */ volatile bool opt_sigint = false; /* true if stopped by SIGINT */ pid_t pgrp; /* proceess group leader */ /* Scheduler options */ 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 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(STRESS_AFFINITY) STRESSOR(affinity, AFFINITY, CLASS_SCHEDULER), #endif #if defined(STRESS_AF_ALG) STRESSOR(af_alg, AF_ALG, CLASS_CPU | CLASS_OS), #endif #if defined(STRESS_AIO) STRESSOR(aio, AIO, CLASS_IO | CLASS_INTERRUPT | CLASS_OS), #endif #if defined(STRESS_AIO_LINUX) STRESSOR(aio_linux, AIO_LINUX, CLASS_IO | CLASS_INTERRUPT | CLASS_OS), #endif #if defined(STRESS_APPARMOR) STRESSOR(apparmor, APPARMOR, CLASS_OS | CLASS_SECURITY), #endif STRESSOR(bigheap, BIGHEAP, CLASS_OS | CLASS_VM), #if defined(STRESS_BIND_MOUNT) STRESSOR(bind_mount, BIND_MOUNT, CLASS_FILESYSTEM | CLASS_OS | CLASS_PATHOLOGICAL), #endif STRESSOR(brk, BRK, CLASS_OS | CLASS_VM), STRESSOR(bsearch, BSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(cache, CACHE, CLASS_CPU_CACHE), #if defined(STRESS_CAP) STRESSOR(cap, CAP, CLASS_OS), #endif STRESSOR(chdir, CHDIR, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(chmod, CHMOD, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_CLOCK) STRESSOR(clock, CLOCK, CLASS_INTERRUPT | CLASS_OS), #endif #if defined(STRESS_CLONE) STRESSOR(clone, CLONE, CLASS_SCHEDULER | CLASS_OS), #endif #if defined(STRESS_CONTEXT) STRESSOR(context, CONTEXT, CLASS_MEMORY | CLASS_CPU), #endif #if defined(STRESS_COPY_FILE) STRESSOR(copy_file, COPY_FILE, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(cpu, CPU, CLASS_CPU), #if defined(STRESS_CPU_ONLINE) STRESSOR(cpu_online, CPU_ONLINE, CLASS_CPU | CLASS_OS), #endif #if defined(STRESS_CRYPT) STRESSOR(crypt, CRYPT, CLASS_CPU), #endif STRESSOR(daemon, DAEMON, CLASS_SCHEDULER | CLASS_OS), STRESSOR(dentry, DENTRY, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(dir, DIR, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(dup, DUP, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_EPOLL) STRESSOR(epoll, EPOLL, CLASS_NETWORK | CLASS_OS), #endif #if defined(STRESS_EVENTFD) STRESSOR(eventfd, EVENTFD, CLASS_FILESYSTEM | CLASS_SCHEDULER | CLASS_OS), #endif #if defined(STRESS_EXEC) STRESSOR(exec, EXEC, CLASS_SCHEDULER | CLASS_OS), #endif #if defined(STRESS_FALLOCATE) STRESSOR(fallocate, FALLOCATE, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(fault, FAULT, CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS), STRESSOR(fcntl, FCNTL, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_FIEMAP) STRESSOR(fiemap, FIEMAP, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(fifo, FIFO, CLASS_PIPE_IO | CLASS_OS | CLASS_SCHEDULER), STRESSOR(filename, FILENAME, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(flock, FLOCK, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(fork, FORK, CLASS_SCHEDULER | CLASS_OS), STRESSOR(fp_error, FP_ERROR, CLASS_CPU), STRESSOR(fstat, FSTAT, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_FUTEX) STRESSOR(futex, FUTEX, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(get, GET, CLASS_OS), #if defined(STRESS_GETRANDOM) STRESSOR(getrandom, GETRANDOM, CLASS_OS | CLASS_CPU), #endif #if defined(STRESS_GETDENT) STRESSOR(getdent, GETDENT, CLASS_FILESYSTEM | CLASS_OS), #endif #if defined(STRESS_HANDLE) STRESSOR(handle, HANDLE, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(hdd, HDD, CLASS_IO | CLASS_OS), #if defined(STRESS_HEAPSORT) STRESSOR(heapsort, HEAPSORT, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), #endif STRESSOR(hsearch, HSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), #if defined(STRESS_ICACHE) STRESSOR(icache, ICACHE, CLASS_CPU_CACHE), #endif STRESSOR(iosync, IOSYNC, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_INOTIFY) STRESSOR(inotify, INOTIFY, CLASS_FILESYSTEM | CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(itimer, ITIMER, CLASS_INTERRUPT | CLASS_OS), #if defined(STRESS_KCMP) STRESSOR(kcmp, KCMP, CLASS_OS), #endif #if defined(STRESS_KEY) STRESSOR(key, KEY, CLASS_OS), #endif STRESSOR(kill, KILL, CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS), #if defined(STRESS_KLOG) STRESSOR(klog, KLOG, CLASS_OS), #endif #if defined(STRESS_LEASE) STRESSOR(lease, LEASE, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(link, LINK, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_LOCKBUS) STRESSOR(lockbus, LOCKBUS, CLASS_CPU_CACHE | CLASS_MEMORY), #endif #if defined(STRESS_LOCKF) STRESSOR(lockf, LOCKF, CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(longjmp, LONGJMP, CLASS_CPU), STRESSOR(lsearch, LSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(malloc, MALLOC, CLASS_CPU_CACHE | CLASS_MEMORY | CLASS_VM | CLASS_OS), STRESSOR(matrix, MATRIX, CLASS_CPU | CLASS_CPU_CACHE | CLASS_MEMORY | CLASS_CPU), #if defined(STRESS_MEMBARRIER) STRESSOR(membarrier, MEMBARRIER, CLASS_CPU_CACHE | CLASS_MEMORY), #endif STRESSOR(memcpy, MEMCPY, CLASS_CPU_CACHE | CLASS_MEMORY), #if defined(STRESS_MEMFD) STRESSOR(memfd, MEMFD, CLASS_OS | CLASS_MEMORY), #endif #if defined(STRESS_MERGESORT) STRESSOR(mergesort, MERGESORT, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), #endif #if defined(STRESS_MINCORE) STRESSOR(mincore, MINCORE, CLASS_OS | CLASS_MEMORY), #endif STRESSOR(mknod, MKNOD, CLASS_FILESYSTEM | CLASS_OS), STRESSOR(mlock, MLOCK, CLASS_VM | CLASS_OS), STRESSOR(mmap, MMAP, CLASS_VM | CLASS_OS), #if defined(STRESS_MMAPFORK) STRESSOR(mmapfork, MMAPFORK, CLASS_SCHEDULER | CLASS_VM | CLASS_OS), #endif STRESSOR(mmapmany, MMAPMANY, CLASS_VM | CLASS_OS), #if defined(STRESS_MREMAP) STRESSOR(mremap, MREMAP, CLASS_VM | CLASS_OS), #endif #if defined(STRESS_MSG) STRESSOR(msg, MSG, CLASS_SCHEDULER | CLASS_OS), #endif #if defined(STRESS_MQ) STRESSOR(mq, MQ, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(nice, NICE, CLASS_SCHEDULER | CLASS_OS), STRESSOR(null, NULL, CLASS_DEV | CLASS_MEMORY | CLASS_OS), #if defined(STRESS_NUMA) STRESSOR(numa, NUMA, CLASS_CPU | CLASS_MEMORY | CLASS_OS), #endif #if defined(STRESS_OOM_PIPE) STRESSOR(oom_pipe, OOM_PIPE, CLASS_MEMORY | CLASS_OS), #endif STRESSOR(open, OPEN, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_PERSONALITY) STRESSOR(personality, PERSONALITY, CLASS_OS), #endif STRESSOR(pipe, PIPE, CLASS_PIPE_IO | CLASS_MEMORY | CLASS_OS), STRESSOR(poll, POLL, CLASS_SCHEDULER | CLASS_OS), #if defined(STRESS_PROCFS) STRESSOR(procfs, PROCFS, CLASS_FILESYSTEM | CLASS_OS), #endif #if defined(STRESS_PTHREAD) STRESSOR(pthread, PTHREAD, CLASS_SCHEDULER | CLASS_OS), #endif #if defined(STRESS_PTRACE) STRESSOR(ptrace, PTRACE, CLASS_OS), #endif STRESSOR(qsort, QSORT, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), #if defined(STRESS_QUOTA) STRESSOR(quota, QUOTA, CLASS_OS), #endif #if defined(STRESS_RDRAND) STRESSOR(rdrand, RDRAND, CLASS_CPU), #endif #if defined(STRESS_READAHEAD) STRESSOR(readahead, READAHEAD, CLASS_IO | CLASS_OS), #endif #if defined(STRESS_REMAP_FILE_PAGES) STRESSOR(remap_file_pages, REMAP_FILE_PAGES, CLASS_MEMORY | CLASS_OS), #endif STRESSOR(rename, RENAME, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_RLIMIT) STRESSOR(rlimit, RLIMIT, CLASS_OS), #endif #if defined(STRESS_SECCOMP) STRESSOR(seccomp, SECCOMP, CLASS_OS), #endif STRESSOR(seek, SEEK, CLASS_IO | CLASS_OS), #if defined(STRESS_SEMAPHORE_POSIX) STRESSOR(sem_posix, SEMAPHORE_POSIX, CLASS_OS | CLASS_SCHEDULER), #endif #if defined(STRESS_SEMAPHORE_SYSV) STRESSOR(sem_sysv, SEMAPHORE_SYSV, CLASS_OS | CLASS_SCHEDULER), #endif #if defined(STRESS_SHM_POSIX) STRESSOR(shm_posix, SHM_POSIX, CLASS_VM | CLASS_OS), #endif STRESSOR(shm_sysv, SHM_SYSV, CLASS_VM | CLASS_OS), #if defined(STRESS_SENDFILE) STRESSOR(sendfile, SENDFILE, CLASS_PIPE_IO | CLASS_OS), #endif #if defined(STRESS_SIGFD) STRESSOR(sigfd, SIGFD, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(sigfpe, SIGFPE, CLASS_INTERRUPT | CLASS_OS), STRESSOR(sigpending, SIGPENDING, CLASS_INTERRUPT | CLASS_OS), #if defined(STRESS_SIGQUEUE) STRESSOR(sigq, SIGQUEUE, CLASS_INTERRUPT | CLASS_OS), #endif STRESSOR(sigsegv, SIGSEGV, CLASS_INTERRUPT | CLASS_OS), STRESSOR(sigsuspend, SIGSUSPEND, CLASS_INTERRUPT | CLASS_OS), #if defined(STRESS_SLEEP) STRESSOR(sleep, SLEEP, CLASS_INTERRUPT | CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(socket, SOCKET, CLASS_NETWORK | CLASS_OS), #if defined(STRESS_SOCKET_FD) STRESSOR(socket_fd, SOCKET_FD, CLASS_NETWORK | CLASS_OS), #endif STRESSOR(socket_pair, SOCKET_PAIR, CLASS_NETWORK | CLASS_OS), STRESSOR(spawn, SPAWN, CLASS_SCHEDULER | CLASS_OS), #if defined(STRESS_SPLICE) STRESSOR(splice, SPLICE, CLASS_PIPE_IO | CLASS_OS), #endif STRESSOR(stack, STACK, CLASS_VM | CLASS_MEMORY), STRESSOR(str, STR, CLASS_CPU | CLASS_CPU_CACHE | CLASS_MEMORY), STRESSOR(stream, STREAM, CLASS_CPU | CLASS_CPU_CACHE | CLASS_MEMORY), STRESSOR(switch, SWITCH, CLASS_SCHEDULER | CLASS_OS), STRESSOR(symlink, SYMLINK, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_SYNC_FILE) STRESSOR(sync_file, SYNC_FILE, CLASS_IO | CLASS_FILESYSTEM | CLASS_OS), #endif STRESSOR(sysinfo, SYSINFO, CLASS_OS), #if defined(STRESS_SYSFS) STRESSOR(sysfs, SYSFS, CLASS_OS), #endif #if defined(STRESS_TEE) STRESSOR(tee, TEE, CLASS_PIPE_IO | CLASS_OS | CLASS_SCHEDULER), #endif #if defined(STRESS_TIMER) STRESSOR(timer, TIMER, CLASS_INTERRUPT | CLASS_OS), #endif #if defined(STRESS_TIMERFD) STRESSOR(timerfd, TIMERFD, CLASS_INTERRUPT | CLASS_OS), #endif #if defined(STRESS_TSC) STRESSOR(tsc, TSC, CLASS_CPU), #endif STRESSOR(tsearch, TSEARCH, CLASS_CPU_CACHE | CLASS_CPU | CLASS_MEMORY), STRESSOR(udp, UDP, CLASS_NETWORK | CLASS_OS), #if defined(STRESS_UDP_FLOOD) STRESSOR(udp_flood, UDP_FLOOD, CLASS_NETWORK | CLASS_OS), #endif #if defined(STRESS_UNSHARE) STRESSOR(unshare, UNSHARE, CLASS_OS), #endif #if defined(STRESS_URANDOM) STRESSOR(urandom, URANDOM, CLASS_DEV | CLASS_OS), #endif #if defined(STRESS_USERFAULTFD) STRESSOR(userfaultfd, USERFAULTFD, CLASS_VM | CLASS_OS), #endif STRESSOR(utime, UTIME, CLASS_FILESYSTEM | CLASS_OS), #if defined(STRESS_VECMATH) STRESSOR(vecmath, VECMATH, CLASS_CPU | CLASS_CPU_CACHE), #endif #if defined(STRESS_VFORK) STRESSOR(vfork, VFORK, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(vm, VM, CLASS_VM | CLASS_MEMORY | CLASS_OS), #if defined(STRESS_VM_RW) STRESSOR(vm_rw, VM_RW, CLASS_VM | CLASS_MEMORY | CLASS_OS), #endif #if defined(STRESS_VM_SPLICE) STRESSOR(vm_splice, VM_SPLICE, CLASS_VM | CLASS_PIPE_IO | CLASS_OS), #endif #if defined(STRESS_WAIT) STRESSOR(wait, WAIT, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(wcs, WCS, CLASS_CPU | CLASS_CPU_CACHE | CLASS_MEMORY), #if defined(STRESS_XATTR) STRESSOR(xattr, XATTR, CLASS_FILESYSTEM | CLASS_OS), #endif #if defined(STRESS_YIELD) STRESSOR(yield, YIELD, CLASS_SCHEDULER | CLASS_OS), #endif STRESSOR(zero, ZERO, CLASS_DEV | CLASS_MEMORY | CLASS_OS), #if defined(STRESS_ZLIB) STRESSOR(zlib, ZLIB, CLASS_CPU | CLASS_CPU_CACHE | CLASS_MEMORY), #endif STRESSOR(zombie, ZOMBIE, CLASS_SCHEDULER | CLASS_OS), { stress_noop, STRESS_MAX, 0, 0, NULL, 0 } }; STRESS_ASSERT(SIZEOF_ARRAY(stressors) != STRESS_MAX) /* Different stress classes */ static const class_t classes[] = { { CLASS_CPU, "cpu" }, { CLASS_CPU_CACHE, "cpu-cache" }, { CLASS_DEV, "device" }, { CLASS_IO, "io" }, { CLASS_INTERRUPT, "interrupt" }, { CLASS_FILESYSTEM, "filesystem" }, { CLASS_MEMORY, "memory" }, { CLASS_NETWORK, "network" }, { CLASS_OS, "os" }, { CLASS_PIPE_IO, "pipe" }, { CLASS_SCHEDULER, "scheduler" }, { CLASS_SECURITY, "security" }, { CLASS_VM, "vm" }, { 0, NULL } }; static const struct option long_options[] = { #if defined(STRESS_AFFINITY) { "affinity", 1, 0, OPT_AFFINITY }, { "affinity-ops",1, 0, OPT_AFFINITY_OPS }, { "affinity-rand",0, 0, OPT_AFFINITY_RAND }, #endif #if defined(STRESS_AF_ALG) { "af-alg", 1, 0, OPT_AF_ALG }, { "af-alg-ops", 1, 0, OPT_AF_ALG_OPS }, #endif { "aggressive", 0, 0, OPT_AGGRESSIVE }, #if defined(STRESS_AIO) { "aio", 1, 0, OPT_AIO }, { "aio-ops", 1, 0, OPT_AIO_OPS }, { "aio-requests",1, 0, OPT_AIO_REQUESTS }, #endif #if defined(STRESS_AIO_LINUX) { "aiol", 1, 0, OPT_AIO_LINUX }, { "aiol-ops", 1, 0, OPT_AIO_LINUX_OPS }, { "aiol-requests",1, 0, OPT_AIO_LINUX_REQUESTS }, #endif { "all", 1, 0, OPT_ALL }, #if defined(STRESS_APPARMOR) { "apparmor", 1, 0, OPT_APPARMOR }, { "apparmor-ops",1, 0, OPT_APPARMOR_OPS }, #endif { "backoff", 1, 0, OPT_BACKOFF }, { "bigheap", 1, 0, OPT_BIGHEAP }, { "bigheap-ops",1, 0, OPT_BIGHEAP_OPS }, { "bigheap-growth",1, 0, OPT_BIGHEAP_GROWTH }, #if defined(STRESS_BIND_MOUNT) { "bind-mount", 1, 0, OPT_BIND_MOUNT }, { "bind-mount-ops",1, 0, OPT_BIND_MOUNT_OPS }, #endif { "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 }, { "cache-prefetch",0, 0, OPT_CACHE_PREFETCH }, { "cache-flush",0, 0, OPT_CACHE_FLUSH }, { "cache-fence",0, 0, OPT_CACHE_FENCE }, { "cache-level",1, 0, OPT_CACHE_LEVEL}, { "cache-ways",1, 0, OPT_CACHE_WAYS}, { "cache-no-affinity",0, 0, OPT_CACHE_NO_AFFINITY }, #if defined(STRESS_CAP) { "cap", 1, 0, OPT_CAP }, { "cap-ops", 1, 0, OPT_CAP_OPS }, #endif { "chdir", 1, 0, OPT_CHDIR }, { "chdir-ops", 1, 0, OPT_CHDIR_OPS }, { "chmod", 1, 0, OPT_CHMOD }, { "chmod-ops", 1, 0, OPT_CHMOD_OPS }, { "class", 1, 0, OPT_CLASS }, #if defined(STRESS_CLOCK) { "clock", 1, 0, OPT_CLOCK }, { "clock-ops", 1, 0, OPT_CLOCK_OPS }, #endif #if defined(STRESS_CLONE) { "clone", 1, 0, OPT_CLONE }, { "clone-ops", 1, 0, OPT_CLONE_OPS }, { "clone-max", 1, 0, OPT_CLONE_MAX }, #endif #if defined(STRESS_CONTEXT) { "context", 1, 0, OPT_CONTEXT }, { "context-ops",1, 0, OPT_CONTEXT_OPS }, #endif #if defined(STRESS_COPY_FILE) { "copy-file", 1, 0, OPT_COPY_FILE }, { "copy-file-ops", 1, 0, OPT_COPY_FILE_OPS }, { "copy-file-bytes", 1, 0, OPT_COPY_FILE_BYTES }, #endif { "cpu", 1, 0, OPT_CPU }, { "cpu-ops", 1, 0, OPT_CPU_OPS }, { "cpu-load", 1, 0, OPT_CPU_LOAD }, { "cpu-load-slice",1, 0, OPT_CPU_LOAD_SLICE }, { "cpu-method", 1, 0, OPT_CPU_METHOD }, #if defined(STRESS_CPU_ONLINE) { "cpu-online", 1, 0, OPT_CPU_ONLINE }, { "cpu-online-ops",1, 0, OPT_CPU_ONLINE_OPS }, #endif #if defined(STRESS_CRYPT) { "crypt", 1, 0, OPT_CRYPT }, { "crypt-ops", 1, 0, OPT_CRYPT_OPS }, #endif { "daemon", 1, 0, OPT_DAEMON }, { "daemon-ops", 1, 0, OPT_DAEMON_OPS }, { "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(STRESS_EPOLL) { "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(STRESS_EVENTFD) { "eventfd", 1, 0, OPT_EVENTFD }, { "eventfd-ops",1, 0, OPT_EVENTFD_OPS }, #endif { "exclude", 1, 0, OPT_EXCLUDE }, #if defined(STRESS_EXEC) { "exec", 1, 0, OPT_EXEC }, { "exec-ops", 1, 0, OPT_EXEC_OPS }, { "exec-max", 1, 0, OPT_EXEC_MAX }, #endif #if defined(STRESS_FALLOCATE) { "fallocate", 1, 0, OPT_FALLOCATE }, { "fallocate-ops",1, 0, OPT_FALLOCATE_OPS }, { "fallocate-bytes",1, 0, OPT_FALLOCATE_BYTES }, #endif { "fault", 1, 0, OPT_FAULT }, { "fault-ops", 1, 0, OPT_FAULT_OPS }, { "fcntl", 1, 0, OPT_FCNTL}, { "fcntl-ops", 1, 0, OPT_FCNTL_OPS }, #if defined(STRESS_FIEMAP) { "fiemap", 1, 0, OPT_FIEMAP }, { "fiemap-ops", 1, 0, OPT_FIEMAP_OPS }, #endif { "fifo", 1, 0, OPT_FIFO }, { "fifo-ops", 1, 0, OPT_FIFO_OPS }, { "fifo-readers",1, 0, OPT_FIFO_READERS }, { "filename", 1, 0, OPT_FILENAME }, { "filename-ops",1, 0, OPT_FILENAME_OPS }, { "filename-opts",1, 0, OPT_FILENAME_OPTS }, { "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 }, { "fp-error", 1, 0, OPT_FP_ERROR}, { "fp-error-ops",1, 0, OPT_FP_ERROR_OPS }, { "fstat", 1, 0, OPT_FSTAT }, { "fstat-ops", 1, 0, OPT_FSTAT_OPS }, { "fstat-dir", 1, 0, OPT_FSTAT_DIR }, #if defined(STRESS_FUTEX) { "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 }, #if defined(STRESS_GETRANDOM) { "getrandom", 1, 0, OPT_GETRANDOM }, { "getrandom-ops",1, 0, OPT_GETRANDOM_OPS }, #endif #if defined(STRESS_GETDENT) { "getdent", 1, 0, OPT_GETDENT }, { "getdent-ops",1, 0, OPT_GETDENT_OPS }, #endif #if defined(STRESS_HANDLE) { "handle", 1, 0, OPT_HANDLE }, { "handle-ops", 1, 0, OPT_HANDLE_OPS }, #endif { "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 }, #if defined(STRESS_HEAPSORT) { "heapsort", 1, 0, OPT_HEAPSORT }, { "heapsort-ops",1, 0, OPT_HEAPSORT_OPS }, { "heapsort-size",1, 0, OPT_HEAPSORT_INTEGERS }, #endif { "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(STRESS_ICACHE) { "icache", 1, 0, OPT_ICACHE }, { "icache-ops", 1, 0, OPT_ICACHE_OPS }, #endif { "ignite-cpu", 0, 0, OPT_IGNITE_CPU }, #if defined(STRESS_INOTIFY) { "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(STRESS_IONICE) { "ionice-class",1, 0, OPT_IONICE_CLASS }, { "ionice-level",1, 0, OPT_IONICE_LEVEL }, #endif { "itimer", 1, 0, OPT_ITIMER }, { "itimer-ops", 1, 0, OPT_ITIMER_OPS }, { "itimer-freq",1, 0, OPT_ITIMER_FREQ }, #if defined(STRESS_KCMP) { "kcmp", 1, 0, OPT_KCMP }, { "kcmp-ops", 1, 0, OPT_KCMP_OPS }, #endif #if defined(STRESS_KEY) { "key", 1, 0, OPT_KEY }, { "key-ops", 1, 0, OPT_KEY_OPS }, #endif { "keep-name", 0, 0, OPT_KEEP_NAME }, { "kill", 1, 0, OPT_KILL }, { "kill-ops", 1, 0, OPT_KILL_OPS }, #if defined(STRESS_KLOG) { "klog", 1, 0, OPT_KLOG }, {" klog-ops", 1, 0, OPT_KLOG_OPS }, #endif #if defined(STRESS_LEASE) { "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 defined(STRESS_LOCKBUS) { "lockbus", 1, 0, OPT_LOCKBUS }, { "lockbus-ops",1, 0, OPT_LOCKBUS_OPS }, #endif #if defined(STRESS_LOCKF) { "lockf", 1, 0, OPT_LOCKF }, { "lockf-ops", 1, 0, OPT_LOCKF_OPS }, { "lockf-nonblock", 0, 0, OPT_LOCKF_NONBLOCK }, #endif { "log-brief", 0, 0, OPT_LOG_BRIEF }, { "log-file", 1, 0, OPT_LOG_FILE }, { "longjmp", 1, 0, OPT_LONGJMP }, { "longjmp-ops",1, 0, OPT_LONGJMP_OPS }, { "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 }, #if defined(STRESS_MALLOPT) { "malloc-thresh",1, 0, OPT_MALLOC_THRESHOLD }, #endif { "matrix", 1, 0, OPT_MATRIX }, { "matrix-ops", 1, 0, OPT_MATRIX_OPS }, { "matrix-method",1, 0, OPT_MATRIX_METHOD }, { "matrix-size",1, 0, OPT_MATRIX_SIZE }, { "maximize", 0, 0, OPT_MAXIMIZE }, #if defined(STRESS_MEMBARRIER) { "membarrier", 1, 0, OPT_MEMBARRIER }, { "membarrier-ops",1, 0, OPT_MEMBARRIER_OPS }, #endif { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy", 1, 0, OPT_MEMCPY }, { "memcpy-ops", 1, 0, OPT_MEMCPY_OPS }, #if defined(STRESS_MEMFD) { "memfd", 1, 0, OPT_MEMFD }, { "memfd-ops", 1, 0, OPT_MEMFD_OPS }, #endif #if defined(STRESS_MERGESORT) { "mergesort", 1, 0, OPT_MERGESORT }, { "mergesort-ops",1, 0, OPT_MERGESORT_OPS }, { "mergesort-size",1, 0, OPT_MERGESORT_INTEGERS }, #endif { "metrics", 0, 0, OPT_METRICS }, { "metrics-brief",0, 0, OPT_METRICS_BRIEF }, #if defined(STRESS_MINCORE) { "mincore", 1, 0, OPT_MINCORE }, { "mincore-ops",1, 0, OPT_MINCORE_OPS }, { "mincore-random",0, 0, OPT_MINCORE_RAND }, #endif { "minimize", 0, 0, OPT_MINIMIZE }, { "mknod", 1, 0, OPT_MKNOD }, { "mknod-ops", 1, 0, OPT_MKNOD_OPS }, #if defined(STRESS_MLOCK) { "mlock", 1, 0, OPT_MLOCK }, { "mlock-ops", 1, 0, OPT_MLOCK_OPS }, #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(STRESS_MMAPFORK) { "mmapfork", 1, 0, OPT_MMAPFORK }, { "mmapfork-ops",1, 0, OPT_MMAPFORK_OPS }, #endif { "mmapmany", 1, 0, OPT_MMAPMANY }, { "mmapmany-ops",1, 0, OPT_MMAPMANY_OPS }, #if defined(STRESS_MREMAP) { "mremap", 1, 0, OPT_MREMAP }, { "mremap-ops", 1, 0, OPT_MREMAP_OPS }, { "mremap-bytes",1, 0, OPT_MREMAP_BYTES }, #endif #if defined(STRESS_MSG) { "msg", 1, 0, OPT_MSG }, { "msg-ops", 1, 0, OPT_MSG_OPS }, #endif #if defined(STRESS_MQ) { "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 }, #if defined(STRESS_NUMA) { "numa", 1, 0, OPT_NUMA }, { "numa-ops", 1, 0, OPT_NUMA_OPS }, #endif #if defined(STRESS_OOM_PIPE) { "oom-pipe", 1, 0, OPT_OOM_PIPE }, { "oom-pipe-ops",1, 0, OPT_OOM_PIPE_OPS }, #endif { "open", 1, 0, OPT_OPEN }, { "open-ops", 1, 0, OPT_OPEN_OPS }, #if defined(STRESS_PAGE_IN) { "page-in", 0, 0, OPT_PAGE_IN }, #endif { "pathological",0, 0, OPT_PATHOLOGICAL }, #if defined(STRESS_PERF_STATS) { "perf", 0, 0, OPT_PERF_STATS }, #endif #if defined(STRESS_PERSONALITY) { "personality",1, 0, OPT_PERSONALITY }, { "personality-ops",1, 0, OPT_PERSONALITY_OPS }, #endif { "pipe", 1, 0, OPT_PIPE }, { "pipe-ops", 1, 0, OPT_PIPE_OPS }, { "pipe-data-size",1, 0, OPT_PIPE_DATA_SIZE }, #if defined(F_SETPIPE_SZ) { "pipe-size", 1, 0, OPT_PIPE_SIZE }, #endif { "poll", 1, 0, OPT_POLL }, { "poll-ops", 1, 0, OPT_POLL_OPS }, #if defined(STRESS_PROCFS) { "procfs", 1, 0, OPT_PROCFS }, { "procfs-ops", 1, 0, OPT_PROCFS_OPS }, #endif #if defined(STRESS_PTHREAD) { "pthread", 1, 0, OPT_PTHREAD }, { "pthread-ops",1, 0, OPT_PTHREAD_OPS }, { "pthread-max",1, 0, OPT_PTHREAD_MAX }, #endif #if defined(STRESS_PTRACE) { "ptrace", 1, 0, OPT_PTRACE }, { "ptrace-ops",1, 0, OPT_PTRACE_OPS }, #endif { "qsort", 1, 0, OPT_QSORT }, { "qsort-ops", 1, 0, OPT_QSORT_OPS }, { "qsort-size", 1, 0, OPT_QSORT_INTEGERS }, { "quiet", 0, 0, OPT_QUIET }, #if defined(STRESS_QUOTA) { "quota", 1, 0, OPT_QUOTA }, { "quota-ops", 1, 0, OPT_QUOTA_OPS }, #endif { "random", 1, 0, OPT_RANDOM }, #if defined(STRESS_RDRAND) { "rdrand", 1, 0, OPT_RDRAND }, { "rdrand-ops", 1, 0, OPT_RDRAND_OPS }, #endif #if defined(STRESS_READAHEAD) { "readahead", 1, 0, OPT_READAHEAD }, { "readahead-ops",1, 0, OPT_READAHEAD_OPS }, { "readahead-bytes",1, 0, OPT_READAHEAD_BYTES }, #endif #if defined(STRESS_REMAP_FILE_PAGES) { "remap", 1, 0, OPT_REMAP_FILE_PAGES }, { "remap-ops", 1, 0, OPT_REMAP_FILE_PAGES_OPS }, #endif { "rename", 1, 0, OPT_RENAME }, { "rename-ops", 1, 0, OPT_RENAME_OPS }, #if defined(STRESS_RLIMIT) { "rlimit", 1, 0, OPT_RLIMIT }, { "rlimit-ops", 1, 0, OPT_RLIMIT_OPS }, #endif { "sched", 1, 0, OPT_SCHED }, { "sched-prio", 1, 0, OPT_SCHED_PRIO }, #if defined(STRESS_SECCOMP) { "seccomp", 1, 0, OPT_SECCOMP }, { "seccomp-ops",1, 0, OPT_SECCOMP_OPS }, #endif { "seek", 1, 0, OPT_SEEK }, { "seek-ops", 1, 0, OPT_SEEK_OPS }, #if defined(OPT_SEEK_PUNCH) { "seek-punch", 0, 0, OPT_SEEK_PUNCH }, #endif { "seek-size", 1, 0, OPT_SEEK_SIZE }, #if defined(STRESS_SEMAPHORE_POSIX) { "sem", 1, 0, OPT_SEMAPHORE_POSIX }, { "sem-ops", 1, 0, OPT_SEMAPHORE_POSIX_OPS }, { "sem-procs", 1, 0, OPT_SEMAPHORE_POSIX_PROCS }, #endif #if defined(STRESS_SEMAPHORE_SYSV) { "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(STRESS_SENDFILE) { "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 }, #if defined(STRESS_SHM_POSIX) { "shm", 1, 0, OPT_SHM_POSIX }, { "shm-ops", 1, 0, OPT_SHM_POSIX_OPS }, { "shm-bytes", 1, 0, OPT_SHM_POSIX_BYTES }, { "shm-objs", 1, 0, OPT_SHM_POSIX_OBJECTS }, #endif { "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(STRESS_SIGFD) { "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 }, { "sigsuspend", 1, 0, OPT_SIGSUSPEND}, { "sigsuspend-ops",1, 0, OPT_SIGSUSPEND_OPS}, { "sigpending", 1, 0, OPT_SIGPENDING}, { "sigpending-ops",1, 0, OPT_SIGPENDING_OPS }, #if defined(STRESS_SIGQUEUE) { "sigq", 1, 0, OPT_SIGQUEUE }, { "sigq-ops", 1, 0, OPT_SIGQUEUE_OPS }, #endif #if defined(STRESS_SLEEP) { "sleep", 1, 0, OPT_SLEEP }, { "sleep-ops", 1, 0, OPT_SLEEP_OPS }, { "sleep-max", 1, 0, OPT_SLEEP_MAX }, #endif { "sock", 1, 0, OPT_SOCKET }, { "sock-domain",1, 0, OPT_SOCKET_DOMAIN }, { "sock-nodelay",0, 0, OPT_SOCKET_NODELAY }, { "sock-ops", 1, 0, OPT_SOCKET_OPS }, { "sock-opts", 1, 0, OPT_SOCKET_OPTS }, { "sock-port", 1, 0, OPT_SOCKET_PORT }, #if defined(STRESS_SOCKET_FD) { "sockfd", 1, 0, OPT_SOCKET_FD }, { "sockfd-ops",1, 0, OPT_SOCKET_FD_OPS }, #endif { "sockpair", 1, 0, OPT_SOCKET_PAIR }, { "sockpair-ops",1, 0, OPT_SOCKET_PAIR_OPS }, { "spawn", 1, 0, OPT_SPAWN }, { "spawn-ops", 1, 0, OPT_SPAWN_OPS }, #if defined(STRESS_SPLICE) { "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-fill", 0, 0, OPT_STACK_FILL }, { "stack-ops", 1, 0, OPT_STACK_OPS }, { "str", 1, 0, OPT_STR }, { "str-ops", 1, 0, OPT_STR_OPS }, { "str-method", 1, 0, OPT_STR_METHOD }, { "stream", 1, 0, OPT_STREAM }, { "stream-ops", 1, 0, OPT_STREAM_OPS }, { "stream-l3-size" ,1, 0, OPT_STREAM_L3_SIZE }, { "switch", 1, 0, OPT_SWITCH }, { "switch-ops", 1, 0, OPT_SWITCH_OPS }, { "symlink", 1, 0, OPT_SYMLINK }, { "symlink-ops",1, 0, OPT_SYMLINK_OPS }, #if defined(STRESS_SYNC_FILE) { "sync-file", 1, 0, OPT_SYNC_FILE }, { "sync-file-ops", 1, 0, OPT_SYNC_FILE_OPS }, { "sync-file-bytes", 1, 0, OPT_SYNC_FILE_BYTES }, #endif { "sysinfo", 1, 0, OPT_SYSINFO }, { "sysinfo-ops",1, 0, OPT_SYSINFO_OPS }, #if defined(STRESS_SYSFS) { "sysfs", 1, 0, OPT_SYSFS }, { "sysfs-ops",1, 0, OPT_SYSFS_OPS }, #endif { "syslog", 0, 0, OPT_SYSLOG }, { "timeout", 1, 0, OPT_TIMEOUT }, #if defined(STRESS_TEE) { "tee", 1, 0, OPT_TEE }, { "tee-ops", 1, 0, OPT_TEE_OPS }, #endif { "temp-path", 1, 0, OPT_TEMP_PATH }, #if defined(STRESS_TIMER) { "timer", 1, 0, OPT_TIMER }, { "timer-ops", 1, 0, OPT_TIMER_OPS }, { "timer-freq", 1, 0, OPT_TIMER_FREQ }, { "timer-rand", 0, 0, OPT_TIMER_RAND }, #endif #if defined(STRESS_TIMERFD) { "timerfd", 1, 0, OPT_TIMERFD }, { "timerfd-ops",1, 0, OPT_TIMERFD_OPS }, { "timerfd-freq",1, 0, OPT_TIMERFD_FREQ }, { "timerfd-rand",0, 0, OPT_TIMERFD_RAND }, #endif #if defined(PRCTL_TIMER_SLACK) { "timer-slack",1, 0, OPT_TIMER_SLACK }, #endif #if defined(STRESS_TSC) { "tsc", 1, 0, OPT_TSC }, { "tsc-ops", 1, 0, OPT_TSC_OPS }, #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 }, #if defined(STRESS_THERMAL_ZONES) { "tz", 0, 0, OPT_THERMAL_ZONES }, #endif { "udp", 1, 0, OPT_UDP }, { "udp-ops", 1, 0, OPT_UDP_OPS }, { "udp-domain",1, 0, OPT_UDP_DOMAIN }, #if defined(OPT_UDP_LITE) { "udp-lite", 0, 0, OPT_UDP_LITE }, #endif { "udp-port", 1, 0, OPT_UDP_PORT }, #if defined(STRESS_UDP_FLOOD) { "udp-flood", 1, 0, OPT_UDP_FLOOD }, { "udp-flood-domain",1, 0, OPT_UDP_FLOOD_DOMAIN }, { "udp-flood-ops",1, 0, OPT_UDP_FLOOD_OPS }, #endif #if defined(STRESS_USERFAULTFD) { "userfaultfd",1, 0, OPT_USERFAULTFD }, { "userfaultfd-ops",1, 0, OPT_USERFAULTFD_OPS }, { "userfaultfd-bytes",1,0, OPT_USERFAULTFD_BYTES }, #endif { "utime", 1, 0, OPT_UTIME }, { "utime-ops", 1, 0, OPT_UTIME_OPS }, { "utime-fsync",0, 0, OPT_UTIME_FSYNC }, #if defined(STRESS_UNSHARE) { "unshare", 1, 0, OPT_UNSHARE }, { "unshare-ops",1, 0, OPT_UNSHARE_OPS }, #endif #if defined(STRESS_URANDOM) { "urandom", 1, 0, OPT_URANDOM }, { "urandom-ops",1, 0, OPT_URANDOM_OPS }, #endif #if defined(STRESS_VECMATH) { "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 defined(STRESS_VFORK) { "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(STRESS_VM_RW) { "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(STRESS_VM_SPLICE) { "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 { "wcs", 1, 0, OPT_WCS}, { "wcs-ops", 1, 0, OPT_WCS_OPS }, { "wcs-method", 1, 0, OPT_WCS_METHOD }, #if defined(STRESS_WAIT) { "wait", 1, 0, OPT_WAIT }, { "wait-ops", 1, 0, OPT_WAIT_OPS }, #endif #if defined(STRESS_XATTR) { "xattr", 1, 0, OPT_XATTR }, { "xattr-ops", 1, 0, OPT_XATTR_OPS }, #endif { "yaml", 1, 0, OPT_YAML }, #if defined(STRESS_YIELD) { "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 }, #if defined(STRESS_ZLIB) { "zlib", 1, 0, OPT_ZLIB }, { "zlib-ops", 1, 0, OPT_ZLIB_OPS }, #endif { "zombie", 1, 0, OPT_ZOMBIE }, { "zombie-ops", 1, 0, OPT_ZOMBIE_OPS }, { "zombie-max", 1, 0, OPT_ZOMBIE_MAX }, { NULL, 0, 0, 0 } }; /* * Generic help options */ static const help_t help_generic[] = { { NULL, "aggressive", "enable all aggressive options" }, { "a N", "all N", "start N workers of each stress test" }, { "b N", "backoff N", "wait of N microseconds before work starts" }, { NULL, "class name", "specify a class of stressors, use with --sequential" }, { "n", "dry-run", "do not run" }, { "h", "help", "show help" }, { NULL, "ignite-cpu", "alter kernel controls to make CPU run hot" }, { "k", "keep-name", "keep stress worker names to be 'stress-ng'" }, { NULL, "log-brief", "less verbose log messages" }, { NULL, "log-file filename", "log messages to a log file" }, { NULL, "maximize", "enable maximum stress options" }, { "M", "metrics", "print pseudo metrics of activity" }, { NULL, "metrics-brief", "enable metrics and only show non-zero results" }, { NULL, "minimize", "enable minimal stress options" }, { NULL, "no-madvise", "don't use random madvise options for each mmap" }, #if defined(STRESS_PAGE_IN) { NULL, "page-in", "touch allocated pages that are not in core" }, #endif { NULL, "pathological", "enable stressors that are known to hang a machine" }, #if defined(STRESS_PERF_STATS) { NULL, "perf", "display perf statistics" }, #endif { "q", "quiet", "quiet output" }, { "r", "random N", "start N random workers" }, { NULL, "sched type", "set scheduler type" }, { NULL, "sched-prio N", "set scheduler priority level N" }, { NULL, "sequential N", "run all stressors one by one, invoking N of them" }, { NULL, "syslog", "log messages to the syslog" }, { NULL, "temp-path", "specify path for temporary directories and files" }, { "t N", "timeout N", "timeout after N seconds" }, { NULL, "timer-slack", "enable timer slack mode" }, { NULL, "times", "show run time summary at end of the run" }, #if defined(STRESS_THERMAL_ZONES) { NULL, "tz", "collect temperatures from thermal zones (Linux only)" }, #endif { "v", "verbose", "verbose output" }, { NULL, "verify", "verify results (not available on all tests)" }, { "V", "version", "show version" }, { "Y", "yaml", "output results to YAML formatted filed" }, { "x", "exclude", "list of stressors to exclude (not run)" }, { NULL, NULL, NULL } }; /* * Stress test specific options */ static const help_t help_stressors[] = { #if defined(STRESS_AFFINITY) { NULL, "affinity N", "start N workers that rapidly change CPU affinity" }, { NULL, "affinity-ops N", "stop after N affinity bogo operations" }, { NULL, "affinity-rand", "change affinity randomly rather than sequentially" }, #endif #if defined(STRESS_AF_ALG) { NULL, "af-alg N", "start N workers that stress AF_ALG socket domain" }, { NULL, "af-alg-ops N", "stop after N af-alg bogo operations" }, #endif #if defined(STRESS_AIO) { NULL, "aio N", "start N workers that issue async I/O requests" }, { NULL, "aio-ops N", "stop after N bogo async I/O requests" }, { NULL, "aio-requests N", "number of async I/O requests per worker" }, #endif #if defined(STRESS_AIO_LINUX) { NULL, "aiol N", "start N workers that issue async I/O requests via Linux aio" }, { NULL, "aiol-ops N", "stop after N bogo Linux aio async I/O requests" }, { NULL, "aiol-requests N", "number of Linux aio async I/O requests per worker" }, #endif #if defined(STRESS_APPARMOR) { NULL, "apparmor", "start N workers exercising AppArmor interfaces" }, { NULL, "apparmor-ops", "stop after N bogo AppArmor worker bogo operations" }, #endif { "B N", "bigheap N", "start N workers that grow the heap using calloc()" }, { NULL, "bigheap-ops N", "stop after N bogo bigheap operations" }, { NULL, "bigheap-growth N", "grow heap by N bytes per iteration" }, #if defined(STRESS_BIND_MOUNT) { NULL, "bind-mount N", "start N workers exercising bind mounts" }, { NULL, "bind-mount-ops N", "stop after N bogo bind mount operations" }, #endif { NULL, "brk N", "start N workers performing rapid brk calls" }, { NULL, "brk-ops N", "stop after N brk bogo operations" }, { NULL, "brk-notouch", "don't touch (page in) new data segment page" }, { NULL, "bsearch N", "start N workers that exercise a binary search" }, { NULL, "bsearch-ops N", "stop after N binary search bogo operations" }, { NULL, "bsearch-size N", "number of 32 bit integers to bsearch" }, { "C N", "cache N", "start N CPU cache thrashing workers" }, { NULL, "cache-ops N", "stop after N cache bogo operations" }, { NULL, "cache-prefetch", "prefetch on memory reads/writes" }, { NULL, "cache-flush", "flush cache after every memory write (x86 only)" }, { NULL, "cache-fence", "serialize stores (x86 only)" }, { NULL, "cache-level N", "only exercise specified cache" }, { NULL, "cache-ways N", "only fill specified number of cache ways" }, #if defined(STRESS_CAP) { NULL, "cap N", "start N workers exercsing capget" }, { NULL, "cap-ops N", "stop cap workers after N bogo capget operations" }, #endif { NULL, "chdir N", "start N workers thrashing chdir on many paths" }, { NULL, "chdir-ops N", "stop chdir workers after N bogo chdir operations" }, { NULL, "chmod N", "start N workers thrashing chmod file mode bits " }, { NULL, "chmod-ops N", "stop chmod workers after N bogo operations" }, #if defined(STRESS_CLOCK) { NULL, "clock N", "start N workers thrashing clocks and POSIX timers" }, { NULL, "clock-ops N", "stop clock workers after N bogo operations" }, #endif #if defined(STRESS_CLONE) { NULL, "clone N", "start N workers that rapidly create and reap clones" }, { NULL, "clone-ops N", "stop after N bogo clone operations" }, { NULL, "clone-max N", "set upper limit of N clones per worker" }, #endif #if defined(STRESS_CONTEXT) { NULL, "context N", "start N workers exercising user context" }, { NULL, "context-ops N", "stop context workers after N bogo operations" }, #endif #if defined(STRESS_COPY_FILE) { NULL, "copy-file N", "start N workers that copy file data" }, { NULL, "copy-file-ops N", "stop after N copy bogo operations" }, { NULL, "copy-file-bytes N", "specify size of file to be copied" }, #endif { "c N", "cpu N", "start N workers spinning on sqrt(rand())" }, { NULL, "cpu-ops N", "stop after N cpu bogo operations" }, { "l P", "cpu-load P", "load CPU by P %%, 0=sleep, 100=full load (see -c)" }, { NULL, "cpu-load-slice S", "specify time slice during busy load" }, { NULL, "cpu-method m", "specify stress cpu method m, default is all" }, #if defined(STRESS_CPU_ONLINE) { NULL, "cpu-online N", "start N workers offlining/onlining the CPUs" }, { NULL, "cpu-online-ops N", "stop after N offline/online operations" }, #endif #if defined(STRESS_CRYPT) { NULL, "crypt N", "start N workers performing password encryption" }, { NULL, "crypt-ops N", "stop after N bogo crypt operations" }, #endif { NULL, "daemon N", "start N workers creating multiple daemons" }, { NULL, "daemon-ops N", "stop when N daemons have been created" }, { "D N", "dentry N", "start N dentry thrashing stressors" }, { NULL, "dentry-ops N", "stop after N dentry bogo operations" }, { 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 after N directory bogo operations" }, { NULL, "dup N", "start N workers exercising dup/close" }, { NULL, "dup-ops N", "stop after N dup/close bogo operations" }, #if defined(STRESS_EPOLL) { NULL, "epoll N", "start N workers doing epoll handled socket activity" }, { NULL, "epoll-ops N", "stop after N epoll bogo operations" }, { NULL, "epoll-port P", "use socket ports P upwards" }, { NULL, "epoll-domain D", "specify socket domain, default is unix" }, #endif #if defined(STRESS_EVENTFD) { NULL, "eventfd N", "start N workers stressing eventfd read/writes" }, { NULL, "eventfd-ops N", "stop eventfd workers after N bogo operations" }, #endif #if defined(STRESS_EXEC) { NULL, "exec N", "start N workers spinning on fork() and exec()" }, { NULL, "exec-ops N", "stop after N exec bogo operations" }, { NULL, "exec-max P", "create P workers per iteration, default is 1" }, #endif #if defined(STRESS_FALLOCATE) { NULL, "fallocate N", "start N workers fallocating 16MB files" }, { NULL, "fallocate-ops N", "stop after N fallocate bogo operations" }, { NULL, "fallocate-bytes N", "specify size of file to allocate" }, #endif { NULL, "fault N", "start N workers producing page faults" }, { NULL, "fault-ops N", "stop after N page fault bogo operations" }, #if defined(STRESS_FIEMAP) { NULL, "fiemap N", "start N workers exercising the FIEMAP ioctl" }, { NULL, "fiemap-ops N", "stop after N FIEMAP ioctl bogo operations" }, #endif { NULL, "fifo N", "start N workers exercising fifo I/O" }, { NULL, "fifo-ops N", "stop after N fifo bogo operations" }, { NULL, "fifo-readers N", "number of fifo reader stessors to start" }, { NULL, "filename N", "start N workers exercising filenames" }, { NULL, "filename-ops N", "stop after N filename bogo operations" }, { NULL, "filename-opts opt", "specify allowed filename options" }, { NULL, "fcntl N", "start N workers exercising fcntl commands" }, { NULL, "fcntl-ops N", "stop after N fcntl bogo operations" }, { NULL, "flock N", "start N workers locking a single file" }, { NULL, "flock-ops N", "stop after N flock bogo operations" }, { "f N", "fork N", "start N workers spinning on fork() and exit()" }, { NULL, "fork-ops N", "stop after N fork bogo operations" }, { NULL, "fork-max P", "create P workers per iteration, default is 1" }, { NULL, "fp-error N", "start N workers exercising floating point errors" }, { NULL, "fp-error-ops N", "stop after N fp-error bogo operations" }, { NULL, "fstat N", "start N workers exercising fstat on files" }, { NULL, "fstat-ops N", "stop after N fstat bogo operations" }, { NULL, "fstat-dir path", "fstat files in the specified directory" }, #if defined(STRESS_FUTEX) { NULL, "futex N", "start N workers exercising a fast mutex" }, { NULL, "futex-ops N", "stop after N fast mutex bogo operations" }, #endif { NULL, "get N", "start N workers exercising the get*() system calls" }, { NULL, "get-ops N", "stop after N get bogo operations" }, #if defined(STRESS_GETDENT) { NULL, "getdent N", "start N workers reading directories using getdents" }, { NULL, "getdent-ops N", "stop after N getdents bogo operations" }, #endif #if defined(STRESS_GETRANDOM) { NULL, "getrandom N", "start N workers fetching random data via getrandom()" }, { NULL, "getrandom-ops N", "stop after N getrandom bogo operations" }, #endif #if defined(STRESS_HANDLE) { NULL, "handle N", "start N workers exercising name_to_handle_at" }, { NULL, "handle-ops N", "stop after N handle bogo operations" }, #endif { "d N", "hdd N", "start N workers spinning on write()/unlink()" }, { NULL, "hdd-ops N", "stop after N hdd bogo operations" }, { 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" }, #if defined(STRESS_HEAPSORT) { NULL, "heapsort N", "start N workers heap sorting 32 bit random integers" }, { NULL, "heapsort-ops N", "stop after N heap sort bogo operations" }, { NULL, "heapsort-size N", "number of 32 bit integers to sort" }, #endif { NULL, "hsearch N", "start N workers that exercise a hash table search" }, { NULL, "hsearch-ops N", "stop afer N hash search bogo operations" }, { NULL, "hsearch-size N", "number of integers to insert into hash table" }, #if defined(STRESS_ICACHE) { NULL, "icache N", "start N CPU instruction cache thrashing workers" }, { NULL, "icache-ops N", "stop after N icache bogo operations" }, #endif #if defined(STRESS_INOTIFY) { 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 after N io bogo operations" }, #if defined(STRESS_IONICE) { NULL, "ionice-class C", "specify ionice class (idle, besteffort, realtime)" }, { NULL, "ionice-level L", "specify ionice level (0 max, 7 min)" }, #endif { NULL, "itimer N", "start N workers exercising interval timers" }, { NULL, "itimer-ops N", "stop after N interval timer bogo operations" }, #if defined(STRESS_KCMP) { NULL, "kcmp N", "start N workers exercising kcmp" }, { NULL, "kcmp-ops N", "stop after N kcmp bogo operations" }, #endif #if defined(STRESS_KEY) { NULL, "key N", "start N workers exercising key operations" }, { NULL, "key-ops N", "stop after N key bogo operations" }, #endif { NULL, "kill N", "start N workers killing with SIGUSR1" }, { NULL, "kill-ops N", "stop after N kill bogo operations" }, #if defined(STRESS_KLOG) { NULL, "klog N", "start N workers exercising kernel syslog interface" }, { NULL, "klog -ops N", "stop after N klog bogo operations" }, #endif #if defined(STRESS_LEASE) { NULL, "lease N", "start N workers holding and breaking a lease" }, { NULL, "lease-ops N", "stop after N lease bogo operations" }, { NULL, "lease-breakers N", "number of lease breaking workers to start" }, #endif { NULL, "link N", "start N workers creating hard links" }, { NULL, "link-ops N", "stop after N link bogo operations" }, #if defined(STRESS_LOCKBUS) { NULL, "lockbus N", "start N workers locking a memory increment" }, { NULL, "lockbus-ops N", "stop after N lockbus bogo operations" }, #endif #if defined(STRESS_LOCKF) { NULL, "lockf N", "start N workers locking a single file via lockf" }, { NULL, "lockf-ops N", "stop after N lockf bogo operations" }, { NULL, "lockf-nonblock", "don't block if lock cannot be obtained, re-try" }, #endif { NULL, "longjmp N", "start N workers exercising setjmp/longjmp" }, { NULL, "longjmp-ops N", "stop after N longjmp bogo operations" }, { NULL, "lsearch N", "start N workers that exercise a linear search" }, { NULL, "lsearch-ops N", "stop after N linear search bogo operations" }, { NULL, "lsearch-size N", "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 after N malloc bogo operations" }, #if defined(STRESS_MALLOPT) { NULL, "malloc-thresh N", "threshold where malloc uses mmap instead of sbrk" }, #endif { NULL, "matrix N", "start N workers exercising matrix operations" }, { NULL, "matrix-ops N", "stop after N maxtrix bogo operations" }, { NULL, "matrix-method m", "specify matrix stress method m, default is all" }, { NULL, "matrix-size N", "specify the size of the N x N matrix" }, #if defined(STRESS_MEMBARRIER) { NULL, "membarrier N", "start N workers performing membarrier system calls" }, { NULL, "membarrier-ops N", "stop after N membarrier bogo operations" }, #endif { NULL, "memcpy N", "start N workers performing memory copies" }, { NULL, "memcpy-ops N", "stop after N memcpy bogo operations" }, #if defined(STRESS_MEMFD) { NULL, "memfd N", "start N workers allocating memory with memfd_create" }, { NULL, "memfd-ops N", "stop after N memfd bogo operations" }, #endif #if defined(STRESS_MERGESORT) { NULL, "mergesort N", "start N workers merge sorting 32 bit random integers" }, { NULL, "mergesort-ops N", "stop after N merge sort bogo operations" }, { NULL, "mergesort-size N", "number of 32 bit integers to sort" }, #endif #if defined(STRESS_MINCORE) { NULL, "mincore N", "start N workers exercising mincore" }, { NULL, "mincore-ops N", "stop after N mincore bogo operations" }, { NULL, "mincore-random", "randomly select pages rather than linear scan" }, #endif { NULL, "mknod N", "start N workers that exercise mknod" }, { NULL, "mknod-ops N", "stop after N mknod bogo operations" }, #if defined(STRESS_MLOCK) { NULL, "mlock N", "start N workers exercising mlock/munlock" }, { NULL, "mlock-ops N", "stop after N mlock bogo operations" }, #endif { NULL, "mmap N", "start N workers stressing mmap and munmap" }, { NULL, "mmap-ops N", "stop after N mmap bogo operations" }, { 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(STRESS_MMAPFORK) { NULL, "mmapfork N", "start N workers stressing many forked mmaps/munmaps" }, { NULL, "mmapfork-ops N", "stop after N mmapfork bogo operations" }, #endif { NULL, "mmapmany N", "start N workers stressing many mmaps and munmaps" }, { NULL, "mmapmany-ops N", "stop after N mmapmany bogo operations" }, #if defined(STRESS_MREMAP) { NULL, "mremap N", "start N workers stressing mremap" }, { NULL, "mremap-ops N", "stop after N mremap bogo operations" }, { NULL, "mremap-bytes N", "mremap N bytes maximum for each stress iteration" }, #endif #if defined(STRESS_MSG) { NULL, "msg N", "start N workers stressing System V messages" }, { NULL, "msg-ops N", "stop msg workers after N bogo messages" }, #endif #if defined(STRESS_MQ) { NULL, "mq N", "start N workers passing messages using POSIX messages" }, { NULL, "mq-ops N", "stop mq workers after N bogo messages" }, { 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 after N nice bogo operations" }, { NULL, "null N", "start N workers writing to /dev/null" }, { NULL, "null-ops N", "stop after N /dev/null bogo write operations" }, #if defined(STRESS_NUMA) { NULL, "numa N", "start N workers stressing NUMA interfaces" }, { NULL, "numa-ops N", "stop after N NUMA bogo operations" }, #endif #if defined(STRESS_OOM_PIPE) { NULL, "oom-pipe N", "start N workers exercising large pipes" }, { NULL, "oom-pipe-ops N", "stop after N oom-pipe bogo operations" }, #endif { "o", "open N", "start N workers exercising open/close" }, { NULL, "open-ops N", "stop after N open/close bogo operations" }, #if defined(STRESS_PERSONALITY) { NULL, "personality N", "start N workers that change their personality" }, { NULL, "personality-ops N", "stop after N bogo personality calls" }, #endif { "p N", "pipe N", "start N workers exercising pipe I/O" }, { NULL, "pipe-ops N", "stop after N pipe I/O bogo operations" }, { NULL, "pipe-data-size N", "set pipe size of each pipe write to N bytes" }, #if defined(F_SETPIPE_SZ) { NULL, "pipe-size N", "set pipe size to N bytes" }, #endif { "P N", "poll N", "start N workers exercising zero timeout polling" }, { NULL, "poll-ops N", "stop after N poll bogo operations" }, #if defined(STRESS_PROCFS) { NULL, "procfs N", "start N workers reading portions of /proc" }, { NULL, "procfs-ops N", "stop procfs workers after N bogo read operations" }, #endif #if defined(STRESS_PTHREAD) { 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" }, #endif #if defined(STRESS_PTRACE) { NULL, "ptrace N", "start N workers that trace a child using ptrace" }, { NULL, "ptrace-ops N", "stop ptrace workers after N system calls are traced" }, #endif { "Q", "qsort N", "start N workers qsorting 32 bit random integers" }, { NULL, "qsort-ops N", "stop after N qsort bogo operations" }, { NULL, "qsort-size N", "number of 32 bit integers to sort" }, #if defined(STRESS_QUOTA) { NULL, "quota N", "start N workers exercising quotactl commands" }, { NULL, "quota -ops N", "stop after N quotactl bogo operations" }, #endif #if defined(STRESS_RDRAND) { NULL, "rdrand N", "start N workers exercising rdrand (x86 only)" }, { NULL, "rdrand-ops N", "stop after N rdrand bogo operations" }, #endif #if defined(STRESS_READAHEAD) { NULL, "readahead N", "start N workers exercising file readahead" }, { NULL, "readahead-bytes N", "size of file to readahead on (default is 1GB)" }, { NULL, "readahead-ops N", "stop after N readahead bogo operations" }, #endif #if defined(STRESS_REMAP_FILE_PAGES) { NULL, "remap N", "start N workers exercising page remappings" }, { NULL, "remap-ops N", "stop after N remapping bogo operations" }, #endif { "R", "rename N", "start N workers exercising file renames" }, { NULL, "rename-ops N", "stop after N rename bogo operations" }, #if defined(STRESS_RLIMIT) { NULL, "rlimit N", "start N workers that exceed rlimits" }, { NULL, "rlimit-ops N", "stop after N rlimit bogo operations" }, #endif { NULL, "seek N", "start N workers performing random seek r/w IO" }, { NULL, "seek-ops N", "stop after N seek bogo operations" }, #if defined(OPT_SEEK_PUNCH) { NULL, "seek-punch", "punch random holes in file to stress extents" }, #endif { NULL, "seek-size N", "length of file to do random I/O upon" }, #if defined(STRESS_SEMAPHORE_POSIX) { NULL, "sem N", "start N workers doing semaphore operations" }, { NULL, "sem-ops N", "stop after N semaphore bogo operations" }, { NULL, "sem-procs N", "number of processes to start per worker" }, #endif #if defined(STRESS_SEMAPHORE_SYSV) { NULL, "sem-sysv N", "start N workers doing System V semaphore operations" }, { NULL, "sem-sysv-ops N", "stop after N System V sem bogo operations" }, { NULL, "sem-sysv-procs N", "number of processes to start per worker" }, #endif #if defined(STRESS_SENDFILE) { 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 #if defined(STRESS_SHM_POSIX) { NULL, "shm N", "start N workers that exercise POSIX shared memory" }, { NULL, "shm-ops N", "stop after N POSIX shared memory bogo operations" }, { NULL, "shm-bytes N", "allocate and free N bytes of POSIX shared memory per loop" }, { NULL, "shm-segs N", "allocate N POSIX shared memory segments per iteration" }, #endif { 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 loop" }, { NULL, "shm-sysv-segs N", "allocate N shared memory segments per iteration" }, #if defined(STRESS_SIGFD) { NULL, "sigfd N", "start N workers reading signals via signalfd reads " }, { NULL, "sigfd-ops N", "stop after N bogo signalfd reads" }, #endif { NULL, "sigfpe N", "start N workers generating floating point math faults" }, { NULL, "sigfpe-ops N", "stop after N bogo floating point math faults" }, { NULL, "sigpending N", "start N workers exercising sigpending" }, { NULL, "sigpending-ops N", "stop after N sigpending bogo operations" }, #if defined(STRESS_SIGQUEUE) { NULL, "sigq N", "start N workers sending sigqueue signals" }, { NULL, "sigq-ops N", "stop after N siqqueue bogo operations" }, #endif { NULL, "sigsegv N", "start N workers generating segmentation faults" }, { NULL, "sigsegv-ops N", "stop after N bogo segmentation faults" }, { NULL, "sigsuspend N", "start N workers exercising sigsuspend" }, { NULL, "sigsuspend-ops N", "stop after N bogo sigsuspend wakes" }, #if defined(STRESS_SLEEP) { NULL, "sleep N", "start N workers performing various duration sleeps" }, { NULL, "sleep-ops N", "stop after N bogo sleep operations" }, { NULL, "sleep-max P", "create P threads at a time by each worker" }, #endif { "S N", "sock N", "start N workers exercising socket I/O" }, { NULL, "sock-domain D", "specify socket domain, default is ipv4" }, { NULL, "sock-nodelay", "disable Nagle algorithm, send data immediately" }, { NULL, "sock-ops N", "stop after N socket bogo operations" }, { NULL, "sock-opts option", "socket options [send|sendmsg|sendmmsg]" }, { NULL, "sock-port P", "use socket ports P to P + number of workers - 1" }, #if defined(STRESS_SOCKET_FD) { NULL, "sockfd N", "start N workers sending file descriptors over sockets" }, { NULL, "sockfd-ops N", "stop after N sockfd bogo operations" }, #endif { NULL, "sockpair N", "start N workers exercising socket pair I/O activity" }, { NULL, "sockpair-ops N", "stop after N socket pair bogo operations" }, { NULL, "spawn", "start N workers spawning stress-ng using posix_spawn" }, #if defined(STRESS_SPLICE) { NULL, "spawn-ops N", "stop after N spawn bogo operations" }, { NULL, "splice N", "start N workers reading/writing using splice" }, { NULL, "splice-ops N", "stop after N bogo splice operations" }, { 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 after N bogo stack overflows" }, { NULL, "stack-fill", "fill stack, touches all new pages " }, { NULL, "str N", "start N workers exercising lib C string functions" }, { NULL, "str-method func", "specify the string function to stress" }, { NULL, "str-ops N", "stop after N bogo string operations" }, { NULL, "stream N", "start N workers exercising memory bandwidth" }, { NULL, "stream-ops N", "stop after N bogo stream operations" }, { NULL, "stream-l3-size N", "specify the L3 cache size of the CPU" }, { "s N", "switch N", "start N workers doing rapid context switches" }, { NULL, "switch-ops N", "stop after N context switch bogo operations" }, { NULL, "symlink N", "start N workers creating symbolic links" }, { NULL, "symlink-ops N", "stop after N symbolic link bogo operations" }, #if defined(STRESS_SYNC_FILE) { NULL, "sync-file N", "start N workers exercise sync_file_range" }, { NULL, "sync-file-ops N", "stop after N sync_file_range bogo operations" }, { NULL, "sync-file-bytes N", "size of file to be sync'd" }, #endif { NULL, "sysinfo N", "start N workers reading system information" }, { NULL, "sysinfo-ops N", "stop after sysinfo bogo operations" }, #if defined(STRESS_SYSFS) { NULL, "sysfs N", "start N workers reading files from /sys" }, { NULL, "sysfs-ops N", "stop after sysfs bogo operations" }, #endif #if defined(STRESS_TEE) { NULL, "tee N", "start N workers exercising the tee system call" }, { NULL, "tee-ops N", "stop after N tee bogo operations" }, #endif #if defined(STRESS_TIMER) { "T N", "timer N", "start N workers producing timer events" }, { NULL, "timer-ops N", "stop after N timer bogo events" }, { NULL, "timer-freq F", "run timer(s) at F Hz, range 1 to 1000000000" }, { NULL, "timer-rand", "enable random timer frequency" }, #endif #if defined(STRESS_TIMERFD) { NULL, "timerfd N", "start N workers producing timerfd events" }, { NULL, "timerfd-ops N", "stop after N timerfd bogo events" }, { NULL, "timerfd-freq F", "run timer(s) at F Hz, range 1 to 1000000000" }, { NULL, "timerfd-rand", "enable random timerfd frequency" }, #endif #if defined(STRESS_TSC) { NULL, "tsc N", "start N workers reading the TSC (x86 only)" }, { NULL, "tsc-ops N", "stop after N TSC bogo operations" }, #endif { NULL, "tsearch N", "start N workers that exercise a tree search" }, { NULL, "tsearch-ops N", "stop after N tree search bogo operations" }, { NULL, "tsearch-size N", "number of 32 bit integers to tsearch" }, { NULL, "udp N", "start N workers performing UDP send/receives " }, { NULL, "udp-ops N", "stop after N udp bogo operations" }, { NULL, "udp-domain D", "specify domain, default is ipv4" }, #if defined(OPT_UDP_LITE) { NULL, "udp-lite", "use the UDP-Lite (RFC 3828) protocol" }, #endif { NULL, "udp-port P", "use ports P to P + number of workers - 1" }, #if defined(STRESS_UDP_FLOOD) { NULL, "udp-flood N", "start N workers that performs a UDP flood attack" }, { NULL, "udp-flood-ops N", "stop after N udp flood bogo operations" }, { NULL, "udp-flood-domain D", "specify domain, default is ipv4" }, #endif #if defined(STRESS_UNSHARE) { NULL, "unshare N", "start N workers exercising resource unsharing" }, { NULL, "unshare-ops N", "stop after N bogo unshare operations" }, #endif #if defined(STRESS_URANDOM) { "u N", "urandom N", "start N workers reading /dev/urandom" }, { NULL, "urandom-ops N", "stop after N urandom bogo read operations" }, #endif #if defined(STRESS_USERFAULTFD) { NULL, "userfaultfd N", "start N page faulting workers with userspace handling" }, { NULL, "userfaultfd-ops N", "stop after N page faults have been handled" }, #endif { NULL, "utime N", "start N workers updating file timestamps" }, { NULL, "utime-ops N", "stop after N utime bogo operations" }, { NULL, "utime-fsync", "force utime meta data sync to the file system" }, #if defined(STRESS_VECMATH) { NULL, "vecmath N", "start N workers performing vector math ops" }, { NULL, "vecmath-ops N", "stop after N vector math bogo operations" }, #endif #if defined(STRESS_VFORK) { NULL, "vfork N", "start N workers spinning on vfork() and exit()" }, { NULL, "vfork-ops N", "stop after N vfork bogo operations" }, { 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 after N vm bogo operations" }, #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(STRESS_VM_RW) { 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(STRESS_VM_SPLICE) { NULL, "vm-splice N", "start N workers reading/writing using vmsplice" }, { NULL, "vm-splice-ops N", "stop after N bogo splice operations" }, { NULL, "vm-splice-bytes N", "number of bytes to transfer per vmsplice call" }, #endif { NULL, "wcs N", "start N workers on lib C wide character string functions" }, { NULL, "wcs-method func", "specify the wide character string function to stress" }, { NULL, "wcs-ops N", "stop after N bogo wide character string operations" }, #if defined(STRESS_WAIT) { NULL, "wait N", "start N workers waiting on child being stop/resumed" }, { NULL, "wait-ops N", "stop after N bogo wait operations" }, #endif #if defined(STRESS_YIELD) { "y N", "yield N", "start N workers doing sched_yield() calls" }, { NULL, "yield-ops N", "stop after N bogo yield operations" }, #endif #if defined(STRESS_XATTR) { NULL, "xattr N", "start N workers stressing file extended attributes" }, { NULL, "xattr-ops N", "stop after N bogo xattr operations" }, #endif { NULL, "zero N", "start N workers reading /dev/zero" }, { NULL, "zero-ops N", "stop after N /dev/zero bogo read operations" }, #if defined(STRESS_ZLIB) { NULL, "zlib N", "start N workers compressing data with zlib" }, { NULL, "zlib-ops N", "stop after N zlib bogo compression operations" }, #endif { NULL, "zombie N", "start N workers that rapidly create and reap zombies" }, { NULL, "zombie-ops N", "stop after N bogo zombie fork operations" }, { NULL, "zombie-max N", "set upper limit of N zombies per worker" }, { NULL, NULL, NULL } }; /* * stressor_id_find() * Find index into stressors by id */ static inline int32_t stressor_id_find(const stress_id id) { int32_t i; for (i = 0; stressors[i].name; i++) { if (stressors[i].id == id) break; } return i; /* End of array is a special "NULL" entry */ } /* * stressor_name_find() * Find index into stressors by name */ static inline int32_t stressor_name_find(const char *name) { int32_t i; char *tmp, *munged_name; size_t len; tmp = munge_underscore((char *)name); len = strlen(tmp) + 1; munged_name = alloca(len); strncpy(munged_name, tmp, len); for (i = 0; stressors[i].name; i++) { const char *munged_stressor_name = munge_underscore((char *)stressors[i].name); if (!strcmp(munged_stressor_name, munged_name)) break; } return i; /* End of array is a special "NULL" entry */ } /* * stressor_instances() * return the number of instances for a specific stress test */ int stressor_instances(const stress_id id) { int32_t i = stressor_id_find(id); return procs[i].num_procs; } /* * get_class() * parse for allowed class types, return bit mask of types, 0 if error */ static uint32_t get_class(char *const class_str) { char *str, *token; uint32_t class = 0; for (str = class_str; (token = strtok(str, ",")) != NULL; str = NULL) { int i; uint32_t cl = 0; for (i = 0; classes[i].class; i++) { if (!strcmp(classes[i].name, token)) { cl = classes[i].class; break; } } if (!cl) { fprintf(stderr, "Unknown class: '%s', available classes:", token); for (i = 0; classes[i].class; i++) fprintf(stderr, " %s", classes[i].name); fprintf(stderr, "\n"); return 0; } class |= cl; } return class; } /* * stress_exclude() * parse -x --exlude exclude list */ static int stress_exclude(char *const opt_exclude) { char *str, *token; if (!opt_exclude) return 0; for (str = opt_exclude; (token = strtok(str, ",")) != NULL; str = NULL) { uint32_t i = stressor_name_find(token); if (!stressors[i].name) { fprintf(stderr, "Unknown stressor: '%s', invalid exclude option\n", token); return -1; } procs[i].exclude = true; procs[i].num_procs = 0; } return 0; } /* * Catch signals and set flag to break out of stress loops */ static void MLOCKED stress_sigint_handler(int dummy) { (void)dummy; opt_sigint = true; opt_do_run = false; opt_do_wait = false; } static void MLOCKED stress_sigalrm_child_handler(int dummy) { (void)dummy; opt_do_run = false; } static void MLOCKED stress_sigalrm_parent_handler(int dummy) { (void)dummy; opt_do_wait = false; } /* * stress_sethandler() * set signal handler to catch SIGINT and SIGALRM */ static int stress_sethandler(const char *stress, const bool child) { if (stress_sighandler(stress, SIGINT, stress_sigint_handler, NULL) < 0) return -1; if (stress_sighandler(stress, SIGALRM, child ? stress_sigalrm_child_handler : stress_sigalrm_parent_handler, NULL) < 0) return -1; return 0; } /* * version() * print program version info */ static void version(void) { printf("%s, version " VERSION "\n", app_name); } /* * usage_help() * show generic help information */ static void usage_help(const help_t help_info[]) { size_t i; for (i = 0; help_info[i].description; i++) { char opt_s[10] = ""; if (help_info[i].opt_s) snprintf(opt_s, sizeof(opt_s), "-%s,", help_info[i].opt_s); printf("%-6s--%-19s%s\n", opt_s, help_info[i].opt_l, help_info[i].description); } } /* * usage() * print some help */ static void usage(void) { version(); printf("\nUsage: %s [OPTION [ARG]]\n", app_name); printf("\nGeneral control options:\n"); usage_help(help_generic); printf("\nStressor specific options:\n"); usage_help(help_stressors); 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(const 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 ""; } /* * stress_get_processors() * get number of processors, set count if <=0 as: * count = 0 -> number of CPUs in system * count < 9 -> number of CPUs online */ void stress_get_processors(int32_t *count) { if (*count == 0) *count = stress_get_processors_configured(); else if (*count < 0) *count = stress_get_processors_online(); } /* * 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(const int sig) { static int count = 0; int i, signum = sig; /* multiple calls will always fallback to SIGKILL */ count++; if (count > 5) signum = SIGKILL; killpg(pgrp, sig); 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], signum); } } } /* * wait_procs() * wait for procs */ static void MLOCKED wait_procs(bool *success, bool *resource_success) { int i; if (opt_flags & OPT_FLAGS_IGNITE_CPU) ignite_cpu_start(); #if defined(STRESS_AFFINITY) /* * On systems that support changing CPU affinity * we keep on moving processed between processors * to impact on memory locality (e.g. NUMA) to * try to thrash the system when in aggressive mode */ if (opt_flags & OPT_FLAGS_AGGRESSIVE) { unsigned long int cpu = 0; const uint32_t ticks_per_sec = stress_get_ticks_per_second() * 5; const useconds_t usec_sleep = ticks_per_sec ? 1000000 / ticks_per_sec : 1000000 / 250; while (opt_do_wait) { const int32_t cpus = stress_get_processors_configured(); for (i = 0; i < STRESS_MAX; i++) { int j; for (j = 0; j < procs[i].started_procs; j++) { const pid_t pid = procs[i].pids[j]; if (pid) { int32_t cpu_num = mwc32() % cpus; cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(cpu_num, &mask); if (sched_setaffinity(pid, sizeof(mask), &mask) < 0) goto do_wait; } } } usleep(usec_sleep); cpu++; } } do_wait: #endif 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 (WIFSIGNALED(status)) { #if defined(WTERMSIG) #if NEED_GLIBC(2,1,0) const char *signame = strsignal(WTERMSIG(status)); pr_dbg(stderr, "process %d (stress-ng-%s) terminated on signal: %d (%s)\n", ret, stressors[i].name, WTERMSIG(status), signame); #else pr_dbg(stderr, "process %d (stress-ng-%s) terminated on signal: %d\n", ret, stressors[i].name, WTERMSIG(status)); #endif #else pr_dbg(stderr, "process %d (stress-ng-%s) terminated on signal\n", ret, stressors[i].name); #endif *success = false; } switch (WEXITSTATUS(status)) { case EXIT_SUCCESS: break; case EXIT_NO_RESOURCE: pr_err(stderr, "process %d (stress-ng-%s) aborted early, out of system resources\n", ret, stressors[i].name); *resource_success = false; break; default: pr_err(stderr, "process %d (stress-ng-%s) terminated with an error, exit status=%d\n", ret, stressors[i].name, WEXITSTATUS(status)); *success = false; break; } 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]); } } } } if (opt_flags & OPT_FLAGS_IGNITE_CPU) ignite_cpu_stop(); } /* * handle_sigint() * catch SIGINT */ static void MLOCKED handle_sigint(int dummy) { (void)dummy; opt_do_run = false; kill_procs(SIGALRM); } /* * 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 */ static void MLOCKED stress_run( const int total_procs, const int32_t max_procs, const uint64_t opt_backoff, const int32_t opt_ionice_class, const int32_t opt_ionice_level, proc_stats_t stats[], double *duration, bool *success, bool *resource_success ) { double time_start, time_finish; int32_t n_procs, i, j, n; opt_do_wait = true; 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; pid_t pid; char name[64]; again: if (!opt_do_run) break; pid = fork(); switch (pid) { case -1: if (errno == EAGAIN) { usleep(100000); goto again; } pr_err(stderr, "Cannot fork: errno=%d (%s)\n", errno, strerror(errno)); kill_procs(SIGALRM); goto wait_for_procs; case 0: /* Child */ setpgid(0, pgrp); free_procs(); if (stress_sethandler(name, true) < 0) exit(EXIT_FAILURE); stress_parent_died_alarm(); stress_process_dumpable(false); if (opt_flags & OPT_FLAGS_TIMER_SLACK) stress_set_timer_slack(); (void)alarm(opt_timeout); mwc_reseed(); snprintf(name, sizeof(name), "%s-%s", app_name, munge_underscore((char *)stressors[i].name)); set_oom_adjustment(name, false); set_max_limits(); 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(); #if defined(STRESS_PERF_STATS) if (opt_flags & OPT_FLAGS_PERF_STATS) (void)perf_open(&stats[n].sp); #endif (void)usleep(opt_backoff * n_procs); #if defined(STRESS_PERF_STATS) if (opt_flags & OPT_FLAGS_PERF_STATS) (void)perf_enable(&stats[n].sp); #endif if (opt_do_run && !(opt_flags & OPT_FLAGS_DRY_RUN)) rc = stressors[i].stress_func(&stats[n].counter, j, procs[i].bogo_ops, name); #if defined(STRESS_PERF_STATS) if (opt_flags & OPT_FLAGS_PERF_STATS) { (void)perf_disable(&stats[n].sp); (void)perf_close(&stats[n].sp); } #endif #if defined(STRESS_THERMAL_ZONES) if (opt_flags & OPT_FLAGS_THERMAL_ZONES) (void)tz_get_temperatures(&shared->tz_info, &stats[n].tz); #endif 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); #if defined(STRESS_THERMAL_ZONES) tz_free(&shared->tz_info); #endif exit(rc); default: if (pid > -1) { setpgid(pid, pgrp); 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; } } } } (void)stress_sethandler("stress-ng", false); (void)alarm(opt_timeout); abort: pr_dbg(stderr, "%d stressor%s spawned\n", n_procs, n_procs == 1 ? "" : "s"); wait_for_procs: wait_procs(success, resource_success); time_finish = time_now(); *duration += time_finish - time_start; } /* * show_hogs() * show names of stressors that are going to be run */ static int show_hogs(const uint32_t opt_class) { char *newstr, *str = NULL; ssize_t len = 0; char buffer[64]; bool previous = false; int i; for (i = 0; i < STRESS_MAX; i++) { int32_t n; if (procs[i].exclude) { n = 0; } else { if (opt_flags & OPT_FLAGS_SEQUENTIAL) { if (opt_class) { n = (stressors[i].class & opt_class) ? opt_sequential : 0; } else { n = opt_sequential; } } else { n = procs[i].num_procs; } } if (n) { ssize_t buffer_len; buffer_len = snprintf(buffer, sizeof(buffer), "%s %" PRId32 " %s", previous ? "," : "", n, munge_underscore((char *)stressors[i].name)); previous = true; if (buffer_len >= 0) { newstr = realloc(str, len + buffer_len + 1); if (!newstr) { pr_err(stderr, "Cannot allocate temporary buffer\n"); free(str); return -1; } str = newstr; strncpy(str + len, buffer, buffer_len + 1); } len += buffer_len; } } pr_inf(stdout, "dispatching hogs:%s\n", str ? str : ""); free(str); fflush(stdout); return 0; } /* * metrics_dump() * output metrics */ static void metrics_dump( FILE *yaml, const int32_t max_procs, const int32_t ticks_per_sec) { int32_t i; 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)"); pr_yaml(yaml, "metrics:\n"); 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 j, n = (i * max_procs); char *munged = munge_underscore((char *)stressors[i].name); double u_time, s_time, bogo_rate_r_time, bogo_rate; 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; u_time = (ticks_per_sec > 0) ? (double)u_total / (double)ticks_per_sec : 0.0; s_time = (ticks_per_sec > 0) ? (double)s_total / (double)ticks_per_sec : 0.0; bogo_rate_r_time = (r_total > 0.0) ? (double)c_total / r_total : 0.0; bogo_rate = (us_total > 0) ? (double)c_total / ((double)us_total / (double)ticks_per_sec) : 0.0; pr_inf(stdout, "%-12s %9" PRIu64 " %9.2f %9.2f %9.2f %12.2f %12.2f\n", munged, /* stress test name */ c_total, /* op count */ r_total, /* average real (wall) clock time */ u_time, /* actual user time */ s_time, /* actual system time */ bogo_rate_r_time, /* bogo ops on wall clock time */ bogo_rate); /* bogo ops per second */ pr_yaml(yaml, " - stressor: %s\n", munged); pr_yaml(yaml, " bogo-ops: %" PRIu64 "\n", c_total); pr_yaml(yaml, " bogo-ops-per-second-usr-sys-time: %f\n", bogo_rate); pr_yaml(yaml, " bogo-ops-per-second-real-time: %f\n", bogo_rate_r_time); pr_yaml(yaml, " wall-clock-time: %f\n", r_total); pr_yaml(yaml, " user-time: %f\n", u_time); pr_yaml(yaml, " system-time: %f\n", s_time); pr_yaml(yaml, "\n"); } } /* * times_dump() * output the run times */ static void times_dump( FILE *yaml, const int32_t ticks_per_sec, const double duration) { struct tms buf; double total_cpu_time = stress_get_processors_configured() * duration; double u_time, s_time, t_time, u_pc, s_pc, t_pc; double min1, min5, min15; int rc; if (times(&buf) == (clock_t)-1) { pr_err(stderr, "cannot get run time information: errno=%d (%s)\n", errno, strerror(errno)); return; } rc = stress_get_load_avg(&min1, &min5, &min15); u_time = (float)buf.tms_cutime / (float)ticks_per_sec; s_time = (float)buf.tms_cstime / (float)ticks_per_sec; t_time = ((float)buf.tms_cutime + (float)buf.tms_cstime) / (float)ticks_per_sec; u_pc = (total_cpu_time > 0.0) ? 100.0 * u_time / total_cpu_time : 0.0; s_pc = (total_cpu_time > 0.0) ? 100.0 * s_time / total_cpu_time : 0.0; t_pc = (total_cpu_time > 0.0) ? 100.0 * t_time / total_cpu_time : 0.0; 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", u_time, u_pc); pr_inf(stdout, " %8.2fs system time (%6.2f%%)\n", s_time, s_pc); pr_inf(stdout, " %8.2fs total time (%6.2f%%)\n", t_time, t_pc); if (!rc) { pr_inf(stdout, "load average: %.2f %.2f %.2f\n", min1, min5, min15); } pr_yaml(yaml, "times:\n"); pr_yaml(yaml, " run-time: %f\n", duration); pr_yaml(yaml, " available-cpu-time: %f\n", total_cpu_time); pr_yaml(yaml, " user-time: %f\n", u_time); pr_yaml(yaml, " system-time: %f\n", s_time); pr_yaml(yaml, " total-time: %f\n", t_time); pr_yaml(yaml, " user-time-percent: %f\n", u_pc); pr_yaml(yaml, " system-time-percent: %f\n", s_pc); pr_yaml(yaml, " total-time-percent: %f\n", t_pc); if (!rc) { pr_yaml(yaml, " load-average-1-minute: %f\n", min1); pr_yaml(yaml, " load-average-5-minute: %f\n", min5); pr_yaml(yaml, " load-average-15-minute: %f\n", min15); } } int main(int argc, char **argv) { double duration = 0.0; /* stressor run time in secs */ size_t len; bool success = true, resource_success = true; char *opt_exclude = NULL; /* List of stressors to exclude */ char *yamlfile = NULL; /* YAML filename */ FILE *yaml = NULL; /* YAML output file */ char *logfile = NULL; /* log filename */ int64_t opt_backoff = DEFAULT_BACKOFF; /* child delay */ int32_t id; /* stressor id */ int32_t ticks_per_sec; /* clock ticks per second (jiffies) */ int32_t opt_sched = UNDEFINED; /* sched policy */ int32_t opt_sched_priority = UNDEFINED; /* sched priority */ int32_t opt_ionice_class = UNDEFINED; /* ionice class */ int32_t opt_ionice_level = UNDEFINED; /* ionice level */ uint32_t opt_class = 0; /* Which kind of class is specified */ int32_t opt_random = 0, i; int32_t total_procs = 0, max_procs = 0; int mem_cache_level = DEFAULT_CACHE_LEVEL; int mem_cache_ways = 0; /* --exec stressor uses this to exec itself and then exit early */ if ((argc == 2) && !strcmp(argv[1], "--exec-exit")) exit(EXIT_SUCCESS); memset(procs, 0, sizeof(procs)); mwc_reseed(); (void)stress_get_pagesize(); (void)stress_set_cpu_method("all"); (void)stress_set_str_method("all"); (void)stress_set_wcs_method("all"); (void)stress_set_matrix_method("all"); (void)stress_set_vm_method("all"); pgrp = getpid(); if (stress_get_processors_configured() < 0) { pr_err(stderr, "sysconf failed, number of cpus configured 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 s_id; next_opt: if ((c = getopt_long(argc, argv, "?khMVvqnt:b:c:i:m:d:f:s:l:p:P:C:S:a:y:F:D:T:u:o:r:B:R:Y:x:", long_options, &option_index)) == -1) break; for (s_id = 0; stressors[s_id].id != STRESS_MAX; s_id++) { if (stressors[s_id].short_getopt == c) { const char *name = opt_name(c); opt_flags |= OPT_FLAGS_SET; procs[s_id].num_procs = get_int32(optarg); stress_get_processors(&procs[s_id].num_procs); check_value(name, procs[s_id].num_procs); goto next_opt; } if (stressors[s_id].op == (stress_op)c) { procs[s_id].bogo_ops = get_uint64(optarg); check_range(opt_name(c), procs[s_id].bogo_ops, MIN_OPS, MAX_OPS); goto next_opt; } } switch (c) { #if defined(STRESS_AIO) case OPT_AIO_REQUESTS: stress_set_aio_requests(optarg); break; #endif #if defined(STRESS_AIO_LINUX) case OPT_AIO_LINUX_REQUESTS: stress_set_aio_linux_requests(optarg); break; #endif case OPT_ALL: opt_flags |= (OPT_FLAGS_SET | OPT_FLAGS_ALL); opt_all = get_int32(optarg); stress_get_processors(&opt_all); check_value("all", opt_all); break; #if defined(STRESS_AFFINITY) case OPT_AFFINITY_RAND: opt_flags |= OPT_FLAGS_AFFINITY_RAND; break; #endif case OPT_AGGRESSIVE: opt_flags |= OPT_FLAGS_AGGRESSIVE_MASK; break; case OPT_BACKOFF: opt_backoff = get_uint64(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_PREFETCH: opt_flags |= OPT_FLAGS_CACHE_PREFETCH; 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_CACHE_LEVEL: mem_cache_level = atoi(optarg); /* Overly high values will be caught in the * caching code. */ if (mem_cache_level <= 0) mem_cache_level = DEFAULT_CACHE_LEVEL; break; case OPT_CACHE_NO_AFFINITY: opt_flags |= OPT_FLAGS_CACHE_NOAFF; break; case OPT_CACHE_WAYS: mem_cache_ways = atoi(optarg); if (mem_cache_ways <= 0) mem_cache_ways = 0; break; case OPT_CLASS: opt_class = get_class(optarg); if (!opt_class) exit(EXIT_FAILURE); break; #if defined(STRESS_CLONE) case OPT_CLONE_MAX: stress_set_clone_max(optarg); break; #endif #if defined(STRESS_COPY_FILE) case OPT_COPY_FILE_BYTES: stress_set_copy_file_bytes(optarg); break; #endif case OPT_CPU_LOAD: stress_set_cpu_load(optarg); break; case OPT_CPU_LOAD_SLICE: stress_set_cpu_load_slice(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(STRESS_EPOLL) 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_EXCLUDE: opt_exclude = optarg; break; #if defined(STRESS_EXEC) case OPT_EXEC_MAX: stress_set_exec_max(optarg); break; #endif #if defined(STRESS_FALLOCATE) case OPT_FALLOCATE_BYTES: stress_set_fallocate_bytes(optarg); break; #endif case OPT_FIFO_READERS: stress_set_fifo_readers(optarg); break; case OPT_FILENAME_OPTS: if (stress_filename_opts(optarg) < 0) exit(EXIT_FAILURE); 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; #if defined(STRESS_HEAPSORT) case OPT_HEAPSORT_INTEGERS: stress_set_heapsort_size(optarg); break; #endif case OPT_HSEARCH_SIZE: stress_set_hsearch_size(optarg); break; case OPT_IGNITE_CPU: opt_flags |= OPT_FLAGS_IGNITE_CPU; break; #if defined(STRESS_IONICE) case OPT_IONICE_CLASS: opt_ionice_class = get_opt_ionice_class(optarg); break; case OPT_IONICE_LEVEL: opt_ionice_level = get_int32(optarg); break; #endif case OPT_ITIMER_FREQ: stress_set_itimer_freq(optarg); break; case OPT_KEEP_NAME: opt_flags |= OPT_FLAGS_KEEP_NAME; break; #if defined(STRESS_LEASE) case OPT_LEASE_BREAKERS: stress_set_lease_breakers(optarg); break; #endif #if defined(STRESS_LOCKF) case OPT_LOCKF_NONBLOCK: opt_flags |= OPT_FLAGS_LOCKF_NONBLK; break; #endif case OPT_LOG_BRIEF: opt_flags |= OPT_FLAGS_LOG_BRIEF; break; case OPT_LOG_FILE: logfile = optarg; break; 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; #if defined(STRESS_MALLOPT) case OPT_MALLOC_THRESHOLD: stress_set_malloc_threshold(optarg); break; #endif case OPT_MATRIX_METHOD: if (stress_set_matrix_method(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_MATRIX_SIZE: stress_set_matrix_size(optarg); break; case OPT_MAXIMIZE: opt_flags |= OPT_FLAGS_MAXIMIZE; 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 defined(STRESS_MERGESORT) case OPT_MERGESORT_INTEGERS: stress_set_mergesort_size(optarg); break; #endif #if defined(STRESS_MINCORE) case OPT_MINCORE_RAND: opt_flags |= OPT_FLAGS_MINCORE_RAND; break; #endif case OPT_MINIMIZE: opt_flags |= OPT_FLAGS_MINIMIZE; break; 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(STRESS_MREMAP) case OPT_MREMAP_BYTES: stress_set_mremap_bytes(optarg); break; #endif #if defined(STRESS_MQ) case OPT_MQ_SIZE: stress_set_mq_size(optarg); break; #endif case OPT_NO_MADVISE: opt_flags &= ~OPT_FLAGS_MMAP_MADVISE; break; #if defined(STRESS_PAGE_IN) case OPT_PAGE_IN: opt_flags |= OPT_FLAGS_MMAP_MINCORE; break; #endif case OPT_PATHOLOGICAL: opt_flags |= OPT_FLAGS_PATHOLOGICAL; break; #if defined(STRESS_PERF_STATS) case OPT_PERF_STATS: opt_flags |= OPT_FLAGS_PERF_STATS; break; #endif case OPT_PIPE_DATA_SIZE: stress_set_pipe_data_size(optarg); break; #if defined(F_SETPIPE_SZ) case OPT_PIPE_SIZE: stress_set_pipe_size(optarg); break; #endif #if defined(STRESS_PTHREAD) case OPT_PTHREAD_MAX: stress_set_pthread_max(optarg); break; #endif 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 = get_int32(optarg); stress_get_processors(&opt_random); check_value("random", opt_random); break; #if defined(STRESS_READAHEAD) case OPT_READAHEAD_BYTES: stress_set_readahead_bytes(optarg); break; #endif case OPT_SCHED: opt_sched = get_opt_sched(optarg); break; case OPT_SCHED_PRIO: opt_sched_priority = get_int32(optarg); break; #if defined(OPT_SEEK_PUNCH) case OPT_SEEK_PUNCH: opt_flags |= OPT_FLAGS_SEEK_PUNCH; break; #endif case OPT_SEEK_SIZE: stress_set_seek_size(optarg); break; #if defined(STRESS_SEMAPHORE_POSIX) case OPT_SEMAPHORE_POSIX_PROCS: stress_set_semaphore_posix_procs(optarg); break; #endif #if defined(STRESS_SEMAPHORE_SYSV) case OPT_SEMAPHORE_SYSV_PROCS: stress_set_semaphore_sysv_procs(optarg); break; #endif #if defined(STRESS_SENDFILE) case OPT_SENDFILE_SIZE: stress_set_sendfile_size(optarg); break; #endif case OPT_SEQUENTIAL: opt_flags |= OPT_FLAGS_SEQUENTIAL; opt_sequential = get_int32(optarg); stress_get_processors(&opt_sequential); check_range("sequential", opt_sequential, MIN_SEQUENTIAL, MAX_SEQUENTIAL); break; #if defined(STRESS_SHM_POSIX) case OPT_SHM_POSIX_BYTES: stress_set_shm_posix_bytes(optarg); break; case OPT_SHM_POSIX_OBJECTS: stress_set_shm_posix_objects(optarg); break; #endif case OPT_SHM_SYSV_BYTES: stress_set_shm_sysv_bytes(optarg); break; case OPT_SHM_SYSV_SEGMENTS: stress_set_shm_sysv_segments(optarg); break; #if defined(STRESS_SLEEP) case OPT_SLEEP_MAX: stress_set_sleep_max(optarg); break; #endif case OPT_SOCKET_DOMAIN: if (stress_set_socket_domain(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_SOCKET_NODELAY: opt_flags |= OPT_FLAGS_SOCKET_NODELAY; break; case OPT_SOCKET_OPTS: if (stress_set_socket_opts(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_SOCKET_PORT: stress_set_socket_port(optarg); break; #if defined(STRESS_SPLICE) case OPT_SPLICE_BYTES: stress_set_splice_bytes(optarg); break; #endif case OPT_STACK_FILL: opt_flags |= OPT_FLAGS_STACK_FILL; break; case OPT_STR_METHOD: if (stress_set_str_method(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_STREAM_L3_SIZE: stress_set_stream_L3_size(optarg); break; #if defined(STRESS_SYNC_FILE) case OPT_SYNC_FILE_BYTES: stress_set_sync_file_bytes(optarg); break; #endif case OPT_SYSLOG: opt_flags |= OPT_FLAGS_SYSLOG; break; case OPT_TEMP_PATH: if (stress_set_temp_path(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_TIMEOUT: opt_timeout = get_uint64_time(optarg); break; #if defined(STRESS_TIMER) case OPT_TIMER_FREQ: stress_set_timer_freq(optarg); break; case OPT_TIMER_RAND: opt_flags |= OPT_FLAGS_TIMER_RAND; break; #endif #if defined(STRESS_TIMERFD) case OPT_TIMERFD_FREQ: stress_set_timerfd_freq(optarg); break; case OPT_TIMERFD_RAND: opt_flags |= OPT_FLAGS_TIMERFD_RAND; break; #endif #if defined(PRCTL_TIMER_SLACK) case OPT_TIMER_SLACK: opt_flags |= OPT_FLAGS_TIMER_SLACK; stress_set_timer_slack_ns(optarg); break; #endif case OPT_TIMES: opt_flags |= OPT_FLAGS_TIMES; break; case OPT_TSEARCH_SIZE: stress_set_tsearch_size(optarg); break; #if defined(STRESS_THERMAL_ZONES) case OPT_THERMAL_ZONES: opt_flags |= OPT_FLAGS_THERMAL_ZONES; break; #endif 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; #if defined(OPT_UDP_LITE) case OPT_UDP_LITE: #endif opt_flags |= OPT_FLAGS_UDP_LITE; break; #if defined(STRESS_UDP_FLOOD) case OPT_UDP_FLOOD_DOMAIN: if (stress_set_udp_flood_domain(optarg) < 0) exit(EXIT_FAILURE); break; #endif #if defined(STRESS_USERFAULTFD) case OPT_USERFAULTFD_BYTES: stress_set_userfaultfd_bytes(optarg); break; #endif case OPT_UTIME_FSYNC: opt_flags |= OPT_FLAGS_UTIME_FSYNC; break; case OPT_VERBOSE: opt_flags |= PR_ALL; break; #if defined(STRESS_VFORK) 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: opt_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(STRESS_VM_RW) case OPT_VM_RW_BYTES: stress_set_vm_rw_bytes(optarg); break; #endif #if defined(STRESS_VM_SPLICE) case OPT_VM_SPLICE_BYTES: stress_set_vm_splice_bytes(optarg); break; #endif case OPT_WCS_METHOD: if (stress_set_wcs_method(optarg) < 0) exit(EXIT_FAILURE); break; case OPT_YAML: yamlfile = optarg; break; case OPT_ZOMBIE_MAX: stress_set_zombie_max(optarg); break; default: printf("Unknown option (%d)\n",c); exit(EXIT_FAILURE); } } if (stress_exclude(opt_exclude) < 0) exit(EXIT_FAILURE); if ((opt_flags & (OPT_FLAGS_SEQUENTIAL | OPT_FLAGS_ALL)) == (OPT_FLAGS_SEQUENTIAL | OPT_FLAGS_ALL)) { fprintf(stderr, "cannot invoke --sequential and --all options together\n"); exit(EXIT_FAILURE); } if (opt_class && !(opt_flags & (OPT_FLAGS_SEQUENTIAL | OPT_FLAGS_ALL))) { fprintf(stderr, "class option is only used with --sequential or --all options\n"); exit(EXIT_FAILURE); } if (logfile) pr_openlog(logfile); if (opt_flags & OPT_SYSLOG) openlog("stress-ng", 0, LOG_USER); pr_dbg(stderr, "%" PRId32 " processors online, %" PRId32 " processors configured\n", stress_get_processors_online(), stress_get_processors_configured()); if ((opt_flags & OPT_FLAGS_MINMAX_MASK) == OPT_FLAGS_MINMAX_MASK) { fprintf(stderr, "maximize and minimize cannot be used together\n"); exit(EXIT_FAILURE); } #if defined(STRESS_RDRAND) id = stressor_id_find(STRESS_RDRAND); if ((procs[id].num_procs || (opt_flags & OPT_FLAGS_SEQUENTIAL)) && (stress_rdrand_supported() < 0)) { procs[id].num_procs = 0; procs[id].exclude = true; } #endif #if defined(STRESS_TSC) id = stressor_id_find(STRESS_TSC); if ((procs[id].num_procs || (opt_flags & OPT_FLAGS_SEQUENTIAL)) && (stress_tsc_supported() < 0)) { procs[id].num_procs = 0; procs[id].exclude = true; } #endif #if defined(STRESS_APPARMOR) id = stressor_id_find(STRESS_APPARMOR); if ((procs[id].num_procs || (opt_flags & OPT_FLAGS_SEQUENTIAL)) && (stress_apparmor_supported() < 0)) { procs[id].num_procs = 0; procs[id].exclude = true; } #endif /* * Disable pathological stressors if user has not explicitly * request them to be used. Let's play safe. */ if (!(opt_flags & OPT_FLAGS_PATHOLOGICAL)) { for (i = 0; i < STRESS_MAX; i++) { if (stressors[i].class & CLASS_PATHOLOGICAL) { if (procs[i].num_procs > 0) { pr_inf(stderr, "disabled '%s' (enable it " "with --pathological option)\n", munge_underscore((char *)stressors[i].name)); } procs[i].num_procs = 0; procs[i].exclude = true; } } } if (opt_flags & OPT_FLAGS_RANDOM) { int32_t n = opt_random; if (opt_flags & OPT_FLAGS_SET) { fprintf(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 = mwc32() % ((opt_random >> 5) + 2); int32_t i = mwc32() % STRESS_MAX; if (!procs[i].exclude) { if (rnd > n) rnd = n; procs[i].num_procs += rnd; n -= rnd; } } } #if defined(STRESS_PERF_STATS) if (opt_flags & OPT_FLAGS_PERF_STATS) perf_init(); #endif stress_process_dumpable(false); stress_cwd_readwriteable(); set_oom_adjustment("main", false); set_sched(opt_sched, opt_sched_priority); set_iopriority(opt_ionice_class, opt_ionice_level); #if defined(MLOCKED_SECTION) { extern void *__start_mlocked; extern void *__stop_mlocked; stress_mlock_region(&__start_mlocked, &__stop_mlocked); } #endif for (i = 0; signals[i] != -1; i++) { if (stress_sighandler("stress-ng", signals[i], handle_sigint, NULL) < 0) exit(EXIT_FAILURE); } for (i = 0; i < STRESS_MAX; i++) total_procs += procs[i].num_procs; if (opt_flags & OPT_FLAGS_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 (opt_flags & OPT_FLAGS_ALL) { if (total_procs) { pr_err(stderr, "the all option cannot be specified with other stressors enabled\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); } for (i = 0; i < STRESS_MAX; i++) { if (!procs[i].exclude) procs[i].num_procs = opt_class ? (stressors[i].class & opt_class ? opt_all : 0) : opt_all; total_procs += procs[i].num_procs; 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); } } } } else { if (!total_procs) { pr_err(stderr, "No stress workers\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); } } } } #if defined(STRESS_PTHREAD) { id = stressor_id_find(STRESS_PTHREAD); struct rlimit limit; if (procs[id].num_procs && (getrlimit(RLIMIT_NPROC, &limit) == 0)) { uint64_t max = (uint64_t)limit.rlim_cur / procs[id].num_procs; stress_adjust_pthread_max(max); } } #endif #if defined(STRESS_SLEEP) { id = stressor_id_find(STRESS_SLEEP); struct rlimit limit; if (procs[id].num_procs && (getrlimit(RLIMIT_NPROC, &limit) == 0)) { uint64_t max = (uint64_t)limit.rlim_cur / procs[id].num_procs; stress_adjust_sleep_max(max); } } #endif if (show_hogs(opt_class) < 0) { free_procs(); exit(EXIT_FAILURE); } 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); #if defined(STRESS_PERF_STATS) pthread_spin_init(&shared->perf.lock, 0); #endif /* * Allocate shared cache memory */ shared->mem_cache_level = mem_cache_level; shared->mem_cache_ways = mem_cache_ways; if (stress_cache_alloc("cache allocate") < 0) { (void)munmap(shared, len); free_procs(); exit(EXIT_FAILURE); } #if defined(STRESS_THERMAL_ZONES) if (opt_flags & OPT_FLAGS_THERMAL_ZONES) tz_init(&shared->tz_info); #endif #if defined(STRESS_SEMAPHORE_POSIX) id = stressor_id_find(STRESS_SEMAPHORE_POSIX); if (procs[id].num_procs || (opt_flags & OPT_FLAGS_SEQUENTIAL)) stress_semaphore_posix_init(); #endif #if defined(STRESS_SEMAPHORE_SYSV) id = stressor_id_find(STRESS_SEMAPHORE_SYSV); if (procs[id].num_procs || (opt_flags & OPT_FLAGS_SEQUENTIAL)) stress_semaphore_sysv_init(); #endif if (opt_flags & OPT_FLAGS_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[j].num_procs = 0; if (!procs[i].exclude) { 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, opt_backoff, opt_ionice_class, opt_ionice_level, shared->stats, &duration, &success, &resource_success); } } } else { /* * Run all stressors in parallel */ stress_run(total_procs, max_procs, opt_backoff, opt_ionice_class, opt_ionice_level, shared->stats, &duration, &success, &resource_success); } pr_inf(stdout, "%s run completed in %.2fs%s\n", success ? "successful" : "unsuccessful", duration, duration_to_str(duration)); if (yamlfile) { yaml = fopen(yamlfile, "w"); if (!yaml) pr_err(stdout, "Cannot output YAML data to %s\n", yamlfile); pr_yaml(yaml, "---\n"); pr_yaml_runinfo(yaml); } if (opt_flags & OPT_FLAGS_METRICS) metrics_dump(yaml, max_procs, ticks_per_sec); #if defined(STRESS_PERF_STATS) if (opt_flags & OPT_FLAGS_PERF_STATS) perf_stat_dump(yaml, stressors, procs, max_procs, duration); #endif #if defined(STRESS_THERMAL_ZONES) if (opt_flags & OPT_FLAGS_THERMAL_ZONES) { tz_dump(yaml, shared, stressors, procs, max_procs); tz_free(&shared->tz_info); } #endif if (opt_flags & OPT_FLAGS_TIMES) times_dump(yaml, ticks_per_sec, duration); free_procs(); #if defined(STRESS_SEMAPHORE_POSIX) stress_semaphore_posix_destroy(); #endif #if defined(STRESS_SEMAPHORE_SYSV) stress_semaphore_sysv_destroy(); #endif (void)munmap(shared, len); if (opt_flags & OPT_SYSLOG) closelog(); if (yaml) { pr_yaml(yaml, "...\n"); fclose(yaml); } if (!success) exit(EXIT_NOT_SUCCESS); if (!resource_success) exit(EXIT_NO_RESOURCE); exit(EXIT_SUCCESS); } stress-ng-0.05.23/stress-rdrand.c0000664000175000017500000001001312702231255015203 0ustar kingking/* * Copyright (C) 2013-2016 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" #include #include #include #include #include #include #if defined(STRESS_RDRAND) static bool rdrand_supported = false; #include /* * stress_rdrand_supported() * check if rdrand is supported */ int stress_rdrand_supported(void) { uint32_t eax, ebx, ecx, edx; /* 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_inf(stderr, "rdrand stressor will be skipped, " "not a recognised Intel CPU.\n"); return -1; } /* ..and supports rdrand? */ __cpuid(1, eax, ebx, ecx, edx); if (!(ecx & 0x40000000)) { pr_inf(stderr, "rdrand stressor will be skipped, CPU " "does not support the rdrand instruction.\n"); return -1; } rdrand_supported = true; return 0; } /* * 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 RDRAND64x32() \ { \ 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) { if (rdrand_supported) { double time_start, duration, billion_bits; time_start = time_now(); do { RDRAND64x32(); (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); duration = time_now() - time_start; billion_bits = ((double)*counter * 64.0 * 32.0) / 1000000000.0; pr_dbg(stderr, "%s: %.3f billion random bits read " "(instance %" PRIu32")\n", name, billion_bits, instance); if (duration > 0.0) { pr_dbg(stderr, "%s: %.3f billion random bits per " "second (instance %" PRIu32")\n", name, (double)billion_bits / duration, instance); } } return EXIT_SUCCESS; } #else /* * stress_rdrand_supported() * check if rdrand is supported */ int stress_rdrand_supported(void) { pr_inf(stderr, "rdrand stressor will be skipped, CPU does not " "support the rdrand instruction.\n"); return -1; } /* * 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; (void)name; return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-lease.c0000664000175000017500000001165312702231255015035 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_LEASE) #include #include #include #include #include #include #include #include #include #include #include #if defined(_POSIX_PRIORITY_SCHEDULING) #include #endif static uint64_t lease_sigio; static uint64_t opt_lease_breakers = DEFAULT_LEASE_BREAKERS; static bool set_lease_breakers = false; void stress_set_lease_breakers(const char *optarg) { set_lease_breakers = true; 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 MLOCKED stress_lease_handler(int dummy) { (void)dummy; lease_sigio++; } /* * stress_lease_spawn() * spawn a process */ static pid_t stress_lease_spawn( const char *filename, const char *name, const uint64_t max_ops, uint64_t *counter) { pid_t pid; if (!set_lease_breakers) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_lease_breakers = MAX_LEASE_BREAKERS; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_lease_breakers = MIN_LEASE_BREAKERS; } again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; return -1; } if (pid == 0) { setpgid(0, pgrp); stress_parent_died_alarm(); 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 (child): errno=%d: (%s)\n", name, errno, strerror(errno)); } continue; } (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); exit(EXIT_SUCCESS); } setpgid(pid, pgrp); 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]; int ret, fd, status; pid_t l_pids[MAX_LEASE_BREAKERS]; pid_t pid = getpid(); uint64_t i; memset(l_pids, 0, sizeof(l_pids)); if (stress_sighandler(name, SIGIO, stress_lease_handler, NULL) < 0) return EXIT_FAILURE; ret = stress_temp_dir_mk(name, pid, instance); if (ret < 0) return exit_status(-ret); (void)stress_temp_filename(filename, PATH_MAX, name, pid, instance, mwc32()); fd = creat(filename, S_IRUSR | S_IWUSR); if (fd < 0) { ret = exit_status(errno); pr_err(stderr, "%s: creat failed: errno=%d: (%s)\n", name, errno, strerror(errno)); (void)stress_temp_dir_rm(name, pid, instance); return ret; } (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) { ret = exit_status(errno); pr_err(stderr, "%s: open failed (parent): 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: fcntl 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)); ret = EXIT_SUCCESS; reap: for (i = 0; i < opt_lease_breakers; i++) { if (l_pids[i]) { (void)kill(l_pids[i], SIGKILL); (void)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 ret; } #endif stress-ng-0.05.23/stress-mmapfork.c0000664000175000017500000000553612702231255015563 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_MMAPFORK) #include #include #include #include #include #include #include #include #define MAX_PIDS (32) /* * stress_mmapfork() * stress mappings + fork VM subystem */ int stress_mmapfork( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pids[MAX_PIDS]; struct sysinfo info; void *ptr; int32_t instances; (void)instance; if ((instances = stressor_instances(STRESS_MMAPFORK)) < 1) instances = stress_get_processors_configured(); do { size_t i, n, len; memset(pids, 0, sizeof(pids)); for (n = 0; n < MAX_PIDS; n++) { retry: if (!opt_do_run) goto reap; pids[n] = fork(); if (pids[n] < 0) { /* Out of resources for fork, re-do, ugh */ if (errno == EAGAIN) { usleep(10000); goto retry; } break; } if (pids[n] == 0) { /* Child */ setpgid(0, pgrp); stress_parent_died_alarm(); if (sysinfo(&info) < 0) { pr_fail_err(name, "sysinfo"); _exit(0); } len = ((size_t)info.freeram / (instances * MAX_PIDS)) / 2; ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_POPULATE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (ptr != MAP_FAILED) { madvise(ptr, len, MADV_WILLNEED); memset(ptr, 0, len); madvise(ptr, len, MADV_DONTNEED); munmap(ptr, len); } _exit(0); } setpgid(pids[n], pgrp); } reap: for (i = 0; i < n; i++) { int status; if (waitpid(pids[i], &status, 0) < 0) { if (errno != EINTR) pr_err(stderr, "%s: waitpid errno=%d (%s)\n", name, errno, strerror(errno)); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); return EXIT_SUCCESS; } #endif stress-ng-0.05.23/stress-af-alg.c0000664000175000017500000001214312702231255015066 0ustar kingking/* * Copyright (C) 2013-2016 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(STRESS_AF_ALG) #include #include #include #include #include #include #include #include #define MAX_AF_ALG_RETRIES (25) #define SHA1_DIGEST_SIZE (20) #define SHA224_DIGEST_SIZE (28) #define SHA256_DIGEST_SIZE (32) #define SHA384_DIGEST_SIZE (48) #define SHA512_DIGEST_SIZE (64) #define MD4_DIGEST_SIZE (16) #define MD5_DIGEST_SIZE (16) #define RMD128_DIGEST_SIZE (16) #define RMD160_DIGEST_SIZE (20) #define RMD256_DIGEST_SIZE (32) #define RMD320_DIGEST_SIZE (40) #define WP256_DIGEST_SIZE (32) #define WP384_DIGEST_SIZE (48) #define WP512_DIGEST_SIZE (64) #define TGR128_DIGEST_SIZE (16) #define TGR160_DIGEST_SIZE (20) #define TGR192_DIGEST_SIZE (24) /* See https://lwn.net/Articles/410833/ */ typedef struct { const char *type; const char *name; const ssize_t digest_size; bool bind_fail; } alg_info_t; static alg_info_t algo_info[] = { { "hash", "sha1", SHA1_DIGEST_SIZE, false }, { "hash", "sha224", SHA224_DIGEST_SIZE, false }, { "hash", "sha256", SHA256_DIGEST_SIZE, false }, { "hash", "sha384", SHA384_DIGEST_SIZE, false }, { "hash", "sha512", SHA512_DIGEST_SIZE, false }, { "hash", "md4", MD4_DIGEST_SIZE, false }, { "hash", "md5", MD5_DIGEST_SIZE, false }, { "hash", "rmd128", RMD128_DIGEST_SIZE, false }, { "hash", "rmd160", RMD160_DIGEST_SIZE, false }, { "hash", "rmd256", RMD256_DIGEST_SIZE, false }, { "hash", "rmd320", RMD320_DIGEST_SIZE, false }, { "hash", "wp256", WP256_DIGEST_SIZE, false }, { "hash", "wp384", WP384_DIGEST_SIZE, false }, { "hash", "wp512", WP512_DIGEST_SIZE, false }, { "hash", "tgr128", TGR128_DIGEST_SIZE, false }, { "hash", "tgr160", TGR160_DIGEST_SIZE, false }, { "hash", "tgr192", TGR192_DIGEST_SIZE, false }, { NULL, NULL, 0, false }, }; /* * stress_af_alg() * stress socket AF_ALG domain */ int stress_af_alg( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { int sockfd = -1, rc = EXIT_FAILURE; int retries = MAX_AF_ALG_RETRIES; (void)instance; (void)name; for (;;) { sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0); if (sockfd >= 0) break; retries--; if ((!opt_do_run) || (retries < 0) || (errno != EAFNOSUPPORT)) { pr_fail_err(name, "socket"); return rc; } /* * We may need to retry on EAFNOSUPPORT * as udev may have to load in some * crypto modules which can be racy or * take some time */ usleep(200000); } do { int i; bool bind_ok = false; for (i = 0; algo_info[i].type; i++) { int fd; ssize_t j; const ssize_t digest_size = algo_info[i].digest_size; char input[1024], digest[digest_size]; struct sockaddr_alg sa; if (algo_info[i].bind_fail) continue; memset(&sa, 0, sizeof(sa)); sa.salg_family = AF_ALG; memcpy(sa.salg_type, algo_info[i].type, sizeof(sa.salg_type)); memcpy(sa.salg_name, algo_info[i].name, sizeof(sa.salg_name)); if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { /* Perhaps the hash does not exist with this kernel */ if (errno == ENOENT) { algo_info[i].bind_fail = true; continue; } pr_fail_err(name, "bind"); goto tidy; } bind_ok = true; fd = accept(sockfd, NULL, 0); if (fd < 0) { pr_fail_err(name, "accept"); (void)close(fd); goto tidy; } stress_strnrnd(input, sizeof(input)); for (j = 32; j < (ssize_t)sizeof(input); j++) { if (send(fd, input, j, 0) != j) { pr_fail_err(name, "send"); (void)close(fd); goto tidy; } if (recv(fd, digest, digest_size, MSG_WAITALL) != digest_size) { pr_fail_err(name, "recv"); (void)close(fd); goto tidy; } (*counter)++; if (max_ops && (*counter >= max_ops)) { (void)close(fd); goto done; } } (void)close(fd); } if (!bind_ok) { errno = ENOENT; pr_fail_err(name, "bind to all hash types"); break; } } while (opt_do_run && (!max_ops || *counter < max_ops)); done: rc = EXIT_SUCCESS; tidy: (void)close(sockfd); return rc; } #endif stress-ng-0.05.23/stress-socket-fd.c0000664000175000017500000001652412702231255015625 0ustar kingking/* * Copyright (C) 2013-2016 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 "stress-ng.h" #define MSG_ID 'M' #define MAX_FDS (65536) static int opt_socket_fd_port = DEFAULT_SOCKET_FD_PORT; /* * stress_set_socket_fd_port() * set port to use */ void stress_set_socket_fd_port(const char *optarg) { stress_set_net_port("sockfd-port", optarg, MIN_SOCKET_FD_PORT, MAX_SOCKET_FD_PORT - STRESS_PROCS_MAX, &opt_socket_fd_port); } /* * stress_socket_fd_send() * send a fd (fd_send) over a socket fd */ static inline int stress_socket_fd_send(const int fd, const int fd_send) { struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; int *ptr; char ctrl[CMSG_SPACE(sizeof(int))]; static char msg_data[1] = { MSG_ID }; iov.iov_base = msg_data; iov.iov_len = 1; memset(&msg, 0, sizeof(struct msghdr)); msg.msg_iov = &iov; msg.msg_iovlen = 1; memset(ctrl, 0, sizeof(ctrl)); msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); ptr = (int *)CMSG_DATA(cmsg); *ptr = fd_send; return sendmsg(fd, &msg, 0); } /* * stress_socket_fd_recv() * recv an fd over a socket, return fd or -1 if fail */ static inline int stress_socket_fd_recv(const int fd) { struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; char msg_data[1]; char ctrl[CMSG_SPACE(sizeof(int))]; iov.iov_base = msg_data; iov.iov_len = 1; memset(&msg, 0, sizeof(struct msghdr)); msg.msg_iov = &iov; msg.msg_iovlen = 1; memset(ctrl, 0, sizeof(ctrl)); msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); if (recvmsg(fd, &msg, 0) <= 0) return -errno; if (msg_data[0] != MSG_ID) return -1; if ((msg.msg_flags & MSG_CTRUNC) == MSG_CTRUNC) return -1; cmsg = CMSG_FIRSTHDR(&msg); if (cmsg && (cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS) && ((size_t)cmsg->cmsg_len >= (size_t)CMSG_LEN(sizeof(int)))) { int *const ptr = (int *)CMSG_DATA(cmsg); return *ptr; } return -1; } /* * stress_socket_client() * client reader */ static void stress_socket_client( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid, const size_t max_fd) { struct sockaddr *addr; setpgid(0, pgrp); stress_parent_died_alarm(); do { int fd, retries = 0, fds[max_fd]; size_t i; socklen_t addr_len = 0; retry: if (!opt_do_run) { (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { pr_fail_dbg(name, "socket"); /* failed, kick parent to finish */ (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } stress_set_sockaddr(name, instance, ppid, AF_UNIX, opt_socket_fd_port, &addr, &addr_len); if (connect(fd, addr, addr_len) < 0) { (void)close(fd); usleep(10000); retries++; if (retries > 100) { /* Give up.. */ pr_fail_dbg(name, "connect"); (void)kill(getppid(), SIGALRM); exit(EXIT_FAILURE); } goto retry; } for (i = 0; i < max_fd; i++) fds[i] = stress_socket_fd_recv(fd); for (i = 0; i < max_fd; i++) { if (fds[i] >= 0) (void)close(fds[i]); } (void)shutdown(fd, SHUT_RDWR); (void)close(fd); } while (opt_do_run && (!max_ops || *counter < max_ops)); struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); /* Inform parent we're all done */ (void)kill(getppid(), SIGALRM); } /* * handle_socket_sigalrm() * catch SIGALRM */ static void MLOCKED handle_socket_sigalrm(int dummy) { (void)dummy; opt_do_run = false; } /* * stress_socket_server() * server writer */ static int stress_socket_server( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t pid, const pid_t ppid, const size_t max_fd) { int fd, status; int so_reuseaddr = 1; struct sockaddr_un *addr_un; socklen_t addr_len = 0; struct sockaddr *addr = NULL; uint64_t msgs = 0; int rc = EXIT_SUCCESS; setpgid(pid, pgrp); if (stress_sighandler(name, SIGALRM, handle_socket_sigalrm, NULL) < 0) { rc = EXIT_FAILURE; goto die; } if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { rc = exit_status(errno); pr_fail_dbg(name, "socket"); goto die; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, AF_UNIX, opt_socket_fd_port, &addr, &addr_len); if (bind(fd, addr, addr_len) < 0) { rc = exit_status(errno); pr_fail_dbg(name, "bind"); goto die_close; } if (listen(fd, 10) < 0) { pr_fail_dbg(name, "listen"); rc = EXIT_FAILURE; goto die_close; } do { int sfd = accept(fd, (struct sockaddr *)NULL, NULL); if (sfd >= 0) { size_t i; for (i = 0; i < max_fd; i++) { int newfd = open("/dev/null", O_RDWR); if (stress_socket_fd_send(sfd, newfd) < 0) break; if (newfd >= 0) (void)close(newfd); } (void)close(sfd); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: (void)close(fd); die: if (addr) { addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } if (pid) { (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } pr_dbg(stderr, "%s: %" PRIu64 " messages sent\n", name, msgs); return rc; } /* * stress_socket_fd * stress socket fd passing */ int stress_socket_fd( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid, ppid = getppid(); const size_t max_fd = stress_get_file_limit(); pr_dbg(stderr, "%s: process [%d] using socket port %d\n", name, getpid(), opt_socket_fd_port + instance); again: pid = fork(); if (pid < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_fail_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { stress_socket_client(counter, instance, max_ops, name, ppid, max_fd); exit(EXIT_SUCCESS); } else { return stress_socket_server(counter, instance, max_ops, name, pid, ppid, max_fd); } }