This is experimental clone() (vs. fork()) patch for mpm-itk apache 2.2. Really I see no perfomance benefits, but only little RAM. But using CLONE_VFORK must relax scheduling in theory. Primary - for experiments with LXC. (c) Denis Kaganovich, Licensed under the same terms as the rest of Apache (or Anarchy license). First I remove vfork by default die to segfaults. But then I back to vfork on my servers, keepend defaults. So, to use vfork add "CloneFlags 16384" in mpm_itk config section. --- a/server/mpm/experimental/itk/itk.c 2014-02-28 11:04:38.000000000 +0300 +++ b/server/mpm/experimental/itk/itk.c 2014-02-28 11:37:45.292890651 +0300 @@ -104,6 +104,19 @@ #define HARD_THREAD_LIMIT 1 #endif +#ifdef __linux__ +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,49) && defined(CLONE_FS) +#define ITK_USE_CLONE 1 +static int clone_flags1 = 0, clone_flags2 = 0; +#else +#define ITK_USE_CLONE 0 +#endif +#else +#define ITK_USE_CLONE 0 +#endif + /* config globals */ int ap_threads_per_child=0; /* Worker threads per child */ @@ -713,7 +726,11 @@ static void child_main(int child_num_arg */ { +#if ITK_USE_CLONE + pid_t pid = syscall(SYS_clone, clone_flags1, 0, NULL, NULL), child_pid; +#else pid_t pid = fork(), child_pid; +#endif int status; switch (pid) { case -1: @@ -728,6 +745,12 @@ static void child_main(int child_num_arg } exit(0); default: /* parent; just wait for child to be done */ +#if ITK_USE_CLONE + if (clone_flags1 & CLONE_VFORK) { + /* pid always done, ignore interrupts (die means die) */ + child_pid = waitpid(pid, &status, WNOHANG); + } else +#endif do { child_pid = waitpid(pid, &status, 0); } while (child_pid == -1 && errno == EINTR); @@ -804,6 +827,8 @@ static int make_child(server_rec *s, int if ((pid = os_fork(unixd_config.user_name)) == -1) { #elif defined(TPF) if ((pid = os_fork(s, slot)) == -1) { +#elif ITK_USE_CLONE + if ((pid = syscall(SYS_clone, clone_flags2, 0, NULL, NULL)) == -1) { #else if ((pid = fork()) == -1) { #endif @@ -1426,6 +1451,10 @@ static int itk_pre_config(apr_pool_t *p, #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; #endif +#if ITK_USE_CLONE + clone_flags1 = SIGCHLD; + clone_flags2 = SIGCHLD | CLONE_FS; +#endif apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); @@ -1678,6 +1707,19 @@ static const char *set_nice_value (cmd_p return NULL; } +#if ITK_USE_CLONE +static const char *set_clone_flags(cmd_parms *cmd, void *dummy, const char *flags1, const char *flags2) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) + return err; + + clone_flags1 = (SIGCHLD) ^ atoi(flags1); + clone_flags2 = (SIGCHLD | CLONE_FS) ^ (flags2 ? atoi(flags2) : 0); + return NULL; +} +#endif + static const command_rec itk_cmds[] = { UNIX_DAEMON_COMMANDS, LISTEN_COMMANDS, @@ -1697,6 +1739,10 @@ AP_INIT_TAKE1("MaxClientsVHost", set_max "Maximum number of children alive at the same time for this virtual host."), AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF, "Set nice value for the given vhost, from -20 (highest priority) to 19 (lowest priority)."), +#if ITK_USE_CLONE +AP_INIT_TAKE12("CloneFlags", set_clone_flags, NULL, RSRC_CONF, + "XOR to default (SIGCHLD, SIGCHLD|CLONE_FS) clone flags. See /usr/include/{linux,bits}/sched.h or 'man 2 clone'"), +#endif AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND, { NULL } };