summaryrefslogtreecommitdiff
path: root/posixos.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2016-03-13 01:12:07 -0500
committerPaul Smith <psmith@gnu.org>2016-03-13 01:12:07 -0500
commitfd1dd7c398974b05950735a724838c09eb72ad1e (patch)
tree3ab124b56dfb7eb29597fcbb9b4393ad960143fb /posixos.c
parent14b2d7effb0afd75dfd1ed2534e331784f7d2977 (diff)
downloadmake-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.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/posixos.c b/posixos.c
index 7ff75117..ffd52eb3 100644
--- a/posixos.c
+++ b/posixos.c
@@ -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;
+}