diff options
author | Paul Smith <psmith@gnu.org> | 2016-03-13 01:12:07 -0500 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2016-03-13 01:12:07 -0500 |
commit | fd1dd7c398974b05950735a724838c09eb72ad1e (patch) | |
tree | 3ab124b56dfb7eb29597fcbb9b4393ad960143fb /posixos.c | |
parent | 14b2d7effb0afd75dfd1ed2534e331784f7d2977 (diff) | |
download | make-git-fd1dd7c398974b05950735a724838c09eb72ad1e.tar.gz |
[SV 44555] Use vfork() instead of fork() where available.
Testing has shown that vfork() is actually significantly
more efficient on systems where it's supported, even for
copy-on-write implementations. If make is big enough,
duplicating the page tables is significant overhead.
* configure.ac: Check for fork/vfork.
* makeint.h: Include vfork.h and set up #define for it.
* os.h, posixos.c (get_bad_stdin): For children who can't use
the normal stdin file descriptor, get a broken one.
* job.c (start_job_command): Avoid so many ifdefs and simplify
the invocation of child_execute_job()
(child_execute_job): move the fork operation here so it can
return early for the parent process. Switch to use vfork().
* function.c (func_shell_base): Use new child_execute_job() and
simplify ifdefs.
* job.h, main.c, remote-cstms.c, vmsjobs.c, w32os.c: Update
declarations and calls.
Diffstat (limited to 'posixos.c')
-rw-r--r-- | posixos.c | 66 |
1 files changed, 50 insertions, 16 deletions
@@ -174,27 +174,31 @@ jobserver_acquire_all () } } -/* This is really only invoked on OS/2. - On POSIX we just call jobserver_clear() in the child process. */ -void jobserver_pre_child () +/* Prepare the jobserver to start a child process. */ +void jobserver_pre_child (int recursive) { - CLOSE_ON_EXEC (job_fds[0]); - CLOSE_ON_EXEC (job_fds[1]); + /* If it's not a recursive make, avoid polutting the jobserver pipes. */ + if (!recursive && job_fds[0] >= 0) + { + CLOSE_ON_EXEC (job_fds[0]); + CLOSE_ON_EXEC (job_fds[1]); + } } -void jobserver_post_child () +void jobserver_post_child (int recursive) { #if defined(F_GETFD) && defined(F_SETFD) - for (int i = 0; i < 2; ++i) - { - int flags; - EINTRLOOP (flags, fcntl (job_fds[i], F_GETFD)); - if (flags >= 0) - { - int r; - EINTRLOOP (r, fcntl (job_fds[i], F_SETFD, flags & ~FD_CLOEXEC)); - } - } + if (!recursive && job_fds[0] >= 0) + for (int i = 0; i < 2; ++i) + { + int flags; + EINTRLOOP (flags, fcntl (job_fds[i], F_GETFD)); + if (flags >= 0) + { + int r; + EINTRLOOP (r, fcntl (job_fds[i], F_SETFD, flags & ~FD_CLOEXEC)); + } + } #endif } @@ -388,3 +392,33 @@ jobserver_acquire (int timeout) #endif #endif /* MAKE_JOBSERVER */ + +/* Create a "bad" file descriptor for stdin when parallel jobs are run. */ +int +get_bad_stdin () +{ + static int bad_stdin = -1; + + /* Set up a bad standard input that reads from a broken pipe. */ + + if (bad_stdin == -1) + { + /* Make a file descriptor that is the read end of a broken pipe. + This will be used for some children's standard inputs. */ + int pd[2]; + if (pipe (pd) == 0) + { + /* Close the write side. */ + (void) close (pd[1]); + /* Save the read side. */ + bad_stdin = pd[0]; + + /* Set the descriptor to close on exec, so it does not litter any + child's descriptor table. When it is dup2'd onto descriptor 0, + that descriptor will not close on exec. */ + CLOSE_ON_EXEC (bad_stdin); + } + } + + return bad_stdin; +} |