"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "stress-vforkmany.c" between
stress-ng-0.12.09.tar.xz and stress-ng-0.12.10.tar.xz

About: 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-vforkmany.c  (stress-ng-0.12.09.tar.xz):stress-vforkmany.c  (stress-ng-0.12.10.tar.xz)
skipping to change at line 35 skipping to change at line 35
#include "stress-ng.h" #include "stress-ng.h"
#define WASTE_SIZE (64 * MB) #define WASTE_SIZE (64 * MB)
static const stress_help_t help[] = { static const stress_help_t help[] = {
{ NULL, "vforkmany N", "start N workers spawning many vfork children" }, { NULL, "vforkmany N", "start N workers spawning many vfork children" },
{ NULL, "vforkmany-ops N", "stop after spawning N vfork children" }, { NULL, "vforkmany-ops N", "stop after spawning N vfork children" },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
STRESS_PRAGMA_PUSH
STRESS_PRAGMA_WARN_OFF
static inline pid_t stress_shim_vfork(void)
{
#if defined(__NR_vfork)
return (pid_t)syscall(__NR_vfork);
#else
return vfork();
#endif
}
STRESS_PRAGMA_POP
/* /*
* vforkmany_wait() * vforkmany_wait()
* wait and then kill * wait and then kill
*/ */
static void vforkmany_wait(const pid_t pid) static void vforkmany_wait(const pid_t pid)
{ {
for (;;) { for (;;) {
int ret, status; int ret, status;
errno = 0; errno = 0;
skipping to change at line 77 skipping to change at line 65
* stress by vfork'ing as many processes as possible. * stress by vfork'ing as many processes as possible.
* vfork has interesting semantics, the parent blocks * vfork has interesting semantics, the parent blocks
* until the child has exited, plus child processes * until the child has exited, plus child processes
* share the same address space. So we need to be * share the same address space. So we need to be
* careful not to overwrite shared variables across * careful not to overwrite shared variables across
* all the processes. * all the processes.
*/ */
static int stress_vforkmany(const stress_args_t *args) static int stress_vforkmany(const stress_args_t *args)
{ {
static pid_t chpid; static pid_t chpid;
static volatile int instance = 0;
static uint8_t *stack_sig; static uint8_t *stack_sig;
static volatile bool *terminate; static volatile bool *terminate;
static bool *terminate_mmap; static bool *terminate_mmap;
/* We should use an alternative signal stack */ /* We should use an alternative signal stack */
stack_sig = (uint8_t *)mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE , stack_sig = (uint8_t *)mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (stack_sig == MAP_FAILED) { if (stack_sig == MAP_FAILED) {
pr_inf("%s: skipping stressor, cannot allocate signal stack," pr_inf("%s: skipping stressor, cannot allocate signal stack,"
" errno=%d (%s)\n", " errno=%d (%s)\n",
skipping to change at line 150 skipping to change at line 137
break; break;
if (!keep_stressing_flag()) if (!keep_stressing_flag())
_exit(0); _exit(0);
waste_size >>= 1; waste_size >>= 1;
} while (waste_size > 4096); } while (waste_size > 4096);
if (waste != MAP_FAILED) if (waste != MAP_FAILED)
(void)stress_mincore_touch_pages_interruptible(waste, WAS TE_SIZE); (void)stress_mincore_touch_pages_interruptible(waste, WAS TE_SIZE);
if (!keep_stressing_flag())
_exit(0);
do { do {
/* /*
* Force pid to be a register, if it's * Force pid to be a register, if it's
* stashed on the stack or as a global * stashed on the stack or as a global
* then waitpid will pick up the one * then waitpid will pick up the one
* shared by all the vfork children * shared by all the vfork children
* which is problematic on the wait * which is problematic on the wait
* This is a dirty hack. * This is a dirty hack.
*/ */
register pid_t pid; register pid_t pid;
register bool first = (instance == 0); static volatile pid_t start_pid = -1;
vfork_again: vfork_again:
/* /*
* SIGALRM is not inherited over vfork so * SIGALRM is not inherited over vfork so
* instead poll the run time and break out * instead poll the run time and break out
* of the loop if we've run out of run time * of the loop if we've run out of run time
*/ */
if (*terminate) { if (*terminate) {
keep_stressing_set_flag(false); keep_stressing_set_flag(false);
break; break;
} }
inc_counter(args); if (start_pid == -1) {
instance++;
if (first) {
pid = fork(); pid = fork();
if (pid >= 0)
start_pid = getpid();
} else { } else {
pid = stress_shim_vfork(); pid = vfork();
inc_counter(args);
} }
if (pid < 0) { if (pid < 0) {
/* failed, only exit of not the top parent */ /* failed, only exit of not the first parent */
if (!first) shim_sched_yield();
_exit(0); _exit(0);
goto vfork_again;
} else if (pid == 0) { } else if (pid == 0) {
if (waste != MAP_FAILED) if (waste != MAP_FAILED)
(void)stress_mincore_touch_pages_interrup tible(waste, WASTE_SIZE); (void)stress_mincore_touch_pages_interrup tible(waste, WASTE_SIZE);
/* child, parent is blocked, spawn new child */ /* child, parent is blocked, spawn new child */
if (!args->max_ops || (get_counter(args) < args-> max_ops)) if (!args->max_ops || (get_counter(args) < args-> max_ops))
goto vfork_again; goto vfork_again;
_exit(0); _exit(0);
} else {
/* parent, wait for child, and exit if not first
parent */
if (pid >= 1)
(void)vforkmany_wait(pid);
shim_sched_yield();
if (getpid() != start_pid)
_exit(0);
} }
/* parent, wait for child, and exit if not top parent */
(void)vforkmany_wait(pid);
if (!first)
_exit(0);
} while (keep_stressing(args)); } while (keep_stressing(args));
if (waste != MAP_FAILED) if (waste != MAP_FAILED)
(void)munmap((void *)waste, WASTE_SIZE); (void)munmap((void *)waste, WASTE_SIZE);
_exit(0); _exit(0);
} else { } else {
/* /*
* Parent sleeps until timeout/SIGALRM and then * Parent sleeps until timeout/SIGALRM and then
* flags terminate state that the vfork children * flags terminate state that the vfork children
* see and will then exit. We wait for the first * see and will then exit. We wait for the first
* one spawned to unblock and exit * one spawned to unblock and exit
*/ */
(void)setpgid(chpid, g_pgrp); (void)setpgid(chpid, g_pgrp);
g_opt_flags &= ~OPT_FLAGS_OOMABLE; g_opt_flags &= ~OPT_FLAGS_OOMABLE;
 End of changes. 12 change blocks. 
26 lines changed or deleted 21 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)