summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>1999-08-23 22:15:17 +0000
committerPaul Smith <psmith@gnu.org>1999-08-23 22:15:17 +0000
commit5dc4b92b606351290d979371da4a500ce8f6a57e (patch)
treeb8d06830fdf21258b23c4759a4ae0ca53b1f5bea
parentb3fa4b3c7e77cb4a1767b16b1cfbef2ab19a78cf (diff)
downloadgunmake-5dc4b92b606351290d979371da4a500ce8f6a57e.tar.gz
* Fix jobserver algorithm again.
* A couple of nits. * Fix considered pruning for double-colon rules.
-rw-r--r--.cvsignore2
-rw-r--r--ChangeLog52
-rw-r--r--README.template11
-rw-r--r--configure.in2
-rw-r--r--job.c72
-rw-r--r--job.h1
-rw-r--r--main.c23
-rw-r--r--remake.c22
8 files changed, 118 insertions, 67 deletions
diff --git a/.cvsignore b/.cvsignore
index 446fbca..fb15a2b 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -22,3 +22,5 @@ sun4 i386 i386-netbsd hp300-netbsd hp300 rs6000 sun3 news800 amiga
hp700 hp834 mips sol2 i486-linux
customs
+
+install-sh mkinstalldirs
diff --git a/ChangeLog b/ChangeLog
index c6e22bb..92e54e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+1999-08-23 Paul D. Smith <psmith@gnu.org>
+
+ * remake.c (update_file): Move the considered check into the
+ double-colon rule loop, so we consider double-colon rules
+ individually (otherwise after the first is pruned, the rest might
+ not get run).
+
+ * README.template: Minor changes.
+
+ Remove the debugging features of the jobserver, so it no longer
+ writes distinct tokens to the pipe. Thus, we don't need to store
+ the token we get. A side effect of this is to remove a potential
+ "unavailable token" situation: make-1 invokes make-2 with its
+ special token and make-3 with a normal token; make-2 completes.
+ Now we're waiting for make-3 but using 2 tokens; our special token
+ is idle. In the new version we don't have special tokens per se,
+ we merely decide if we already have a child or not. If we don't,
+ we don't need a token. If we do, we have to get one to run the
+ next child. Similar for putting tokens back: if we're cleaning up
+ the last child, we don't put a token back. Otherwise, we do.
+
+ * main.c: Add a new, internal flag --jobserver-fds instead of
+ overloading the meaning of -j. Remove job_slots_str and add the
+ stringlist jobserver_fds.
+ (struct command_switch): We don't need the int_string type.
+ (switches[]): Add a new option for --jobserver-fds and remove
+ conditions around -j. Make the description for the former 0 so it
+ doesn't print during "make --help".
+ (main): Rework jobserver parsing. If we got --jobserver-fds
+ make sure it's valid. We only get one and job_slots must be 0.
+ If we're the toplevel make (-jN without --jobserver-fds) create
+ the pipe and write generic tokens.
+ Create the stringlist struct for the submakes.
+ Clean up the stringlist where necessary.
+ (init_switches): Remove int_string handling.
+ (print_usage): Don't print internal flags (description ptr is 0).
+ (decode_switches): Remove int_string handling.
+ (define_makeflags): Remove int_string handling.
+
+ * job.c: Remove my_job_token flag and all references to the
+ child->job_token field.
+ (free_job_token): Remove this and merge it into free_child().
+ (reap_children): Rework the "reaped a child" logic slightly.
+ Don't call defunct free_job_token anymore. Always call
+ free_child, even if we're dying.
+ (free_child): If we're not freeing the only child, put a token
+ back in the pipe. Then, if we're dying, don't bother to free.
+ (new_job): If we are using the jobserver, loop checking to see if
+ a) there are no children or b) we get a token from the pipe.
+
+ * job.h (struct child): Remove the job_token field.
+
1999-08-20 Paul D. Smith <psmith@gnu.org>
* variable.c (try_variable_definition): Allocate for variable
diff --git a/README.template b/README.template
index c9a199d..a8ea5a8 100644
--- a/README.template
+++ b/README.template
@@ -1,6 +1,7 @@
This directory contains the %VERSION% release of GNU Make.
-All bugs reported for previous releases have been fixed.
-Some bugs surely remain.
+
+See the file NEWS for the user-visible changes from previous releases.
+In addition, there have been bugs fixed.
For general building and installation instructions, see the file INSTALL.
@@ -24,6 +25,8 @@ site. There is information there about ordering hardcopy documentation.
http://www.gnu.org/doc/doc.html
http://www.gnu.org/manual/manual.html
+You can also find the latest versions of GNU Make from there.
+
Please send GNU make bug reports to bug-make@gnu.org. Please see the
section of the manual entitles `Problems and Bugs' for information on
submitting bug reports.
@@ -61,9 +64,5 @@ debug this code, you can do `make check-loadavg' to see if it works
properly on your system. (You must run `configure' beforehand, but you
need not build Make itself to run this test.)
-See the file NEWS for what has changed since previous releases.
-
-GNU Make is fully documented in make.texinfo. See the section entitled
-`Problems and Bugs' for information on submitting bug reports.
GNU Make is free software. See the file COPYING for copying conditions.
diff --git a/configure.in b/configure.in
index c320a2a..9cc0b05 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ AC_REVISION([$Id$])
AC_PREREQ(2.13)dnl dnl Minimum Autoconf version required.
AC_INIT(vpath.c)dnl dnl A distinctive file to look for in srcdir.
-AM_INIT_AUTOMAKE(make, 3.77.93)
+AM_INIT_AUTOMAKE(make, 3.77.94)
AM_CONFIG_HEADER(config.h)
dnl Regular configure stuff
diff --git a/job.c b/job.c
index 34d1ddd..01a99ae 100644
--- a/job.c
+++ b/job.c
@@ -310,8 +310,6 @@ extern int shell_function_pid, shell_function_completed;
complete child, waiting for it to die if necessary. If ERR is nonzero,
print an error message first. */
-static int rc_block, rc_reap_all, rc_got_block, rc_start_rfd, rc_end_rfd;
-
void
reap_children (block, err)
int block, err;
@@ -326,11 +324,6 @@ reap_children (block, err)
# define REAP_MORE dead_children
#endif
- rc_block = block;
- rc_reap_all = 0;
- rc_got_block = 0;
- rc_start_rfd = job_rfd;
-
/* As long as:
We have at least one child outstanding OR a shell function in progress,
@@ -451,7 +444,6 @@ reap_children (block, err)
{
/* No local children are dead. */
reap_more = 0;
- rc_reap_all = 1;
if (!block || !any_remote)
break;
@@ -677,10 +669,8 @@ reap_children (block, err)
/* Only block for one child. */
block = 0;
- rc_block = block;
}
- rc_end_rfd = job_rfd;
return;
}
@@ -691,11 +681,12 @@ free_child (child)
register struct child *child;
{
/* If this child is the only one it was our "free" job, so don't put a
- token back for it. */
+ token back for it. This child has already been removed from the list,
+ so if there any left this wasn't the last one. */
- if (job_fds[1] >= 0 && (child != children || child->next != 0))
+ if (job_fds[1] >= 0 && children)
{
- char *token = '+';
+ char token = '+';
/* Write a job token back to the pipe. */
@@ -874,7 +865,7 @@ start_job_command (child)
? "%s" : (char *) 0, p);
/* Optimize an empty command. People use this for timestamp rules,
- and forking a useless shell all the time leads to inefficiency. */
+ so avoid forking a useless shell. */
#if !defined(VMS) && !defined(_AMIGA)
if (
@@ -1361,6 +1352,7 @@ new_job (file)
/* Wait for a job slot to be freed up. If we allow an infinite number
don't bother; also job_slots will == 0 if we're using the jobserver. */
+
if (job_slots != 0)
while (job_slots_used == job_slots)
reap_children (1, 0);
@@ -1369,41 +1361,49 @@ new_job (file)
/* If we are controlling multiple jobs make sure we have a token before
starting the child. */
+ /* This can be inefficient. There's a decent chance that this job won't
+ actually have to run any subprocesses: the command script may be empty
+ or otherwise optimized away. It would be nice if we could defer
+ obtaining a token until just before we need it, in start_job_command.
+ To do that we'd need to keep track of whether we'd already obtained a
+ token (since start_job_command is called for each line of the job, not
+ just once). Also more thought needs to go into the entire algorithm;
+ this is where the old parallel job code waits, so... */
+
else if (job_fds[0] >= 0)
- if (children == 0)
- {
- char token = '-';
+ while (1)
+ {
+ char token;
- while (token == '-')
/* If we don't already have a job started, use our "free" token. */
- if (children == 0)
- token = '+';
+ if (!children)
+ break;
/* Read a token. As long as there's no token available we'll block.
If we get a SIGCHLD we'll return with EINTR. If one happened
before we got here we'll return immediately with EBADF because
the signal handler closes the dup'd file descriptor. */
- else if (read (job_rfd, &c->job_token, 1) < 1)
+ if (read (job_rfd, &token, 1) == 1)
{
- if (errno != EINTR && errno != EBADF)
- pfatal_with_name (_("read jobs pipe"));
+ if (debug_flag)
+ printf (_("Obtained token for child 0x%08lx (%s).\n"),
+ (unsigned long int) c, c->file->name);
+ break;
+ }
- /* Re-dup the read side of the pipe, so the signal handler can
- notify us if we miss a child. */
- if (job_rfd < 0)
- job_rfd = dup (job_fds[0]);
+ if (errno != EINTR && errno != EBADF)
+ pfatal_with_name (_("read jobs pipe"));
- /* Something's done. We don't want to block for a whole child,
- just reap whatever's there. */
- reap_children (0, 0);
- }
+ /* Re-dup the read side of the pipe, so the signal handler can
+ notify us if we miss a child. */
+ if (job_rfd < 0)
+ job_rfd = dup (job_fds[0]);
- assert (c->job_token != '-');
- if (debug_flag)
- printf (_("Obtained token for child 0x%08lx (%s).\n"),
- (unsigned long int) c, c->file->name);
- }
+ /* Something's done. We don't want to block for a whole child,
+ just reap whatever's there. */
+ reap_children (0, 0);
+ }
#endif
/* The job is now primed. Start it running.
diff --git a/job.h b/job.h
index 4c5e7e5..00e9599 100644
--- a/job.h
+++ b/job.h
@@ -46,7 +46,6 @@ struct child
unsigned int good_stdin:1; /* Nonzero if this child has a good stdin. */
unsigned int deleted:1; /* Nonzero if targets have been deleted. */
- char job_token; /* The token read from the job pipe. */
};
extern struct child *children;
diff --git a/main.c b/main.c
index dcab8b5..de82b59 100644
--- a/main.c
+++ b/main.c
@@ -1301,11 +1301,15 @@ int main (int argc, char ** argv)
{
char *cp;
- if (jobserver_fds->max > 1)
- fatal (NILF, _("internal error: multiple --jobserver-fds options."));
+ if (jobserver_fds->idx > 1)
+ fatal (NILF, _("internal error: multiple --jobserver-fds options"));
- if (job_slots > 0)
- fatal (NILF, _("internal error: --jobserver-fds unexpected."));
+ /* The combination of a pipe + !job_slots means we're using the
+ jobserver. If !job_slots and we don't have a pipe, we can start
+ infinite jobs. */
+
+ if (job_slots != 0)
+ fatal (NILF, _("internal error: --jobserver-fds unexpected"));
/* Now parse the fds string and make sure it has the proper format. */
@@ -1313,13 +1317,7 @@ int main (int argc, char ** argv)
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
fatal (NILF,
- _("internal error: invalid --jobserver-fds string `%s'."), cp);
-
- /* Set job_slots to 0. The combination of a pipe + !job_slots means
- we're using the jobserver. If !job_slots and we don't have a pipe, we
- can start infinite jobs. */
-
- job_slots = 0;
+ _("internal error: invalid --jobserver-fds string `%s'"), cp);
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
@@ -1353,7 +1351,8 @@ int main (int argc, char ** argv)
/* Every make assumes that it always has one job it can run. For the
submakes it's the token they were given by their parent. For the
- top make, we just subtract one from the number the user wants. */
+ top make, we just subtract one from the number the user wants. We
+ want job_slots to be 0 to indicate we're using the jobserver. */
while (--job_slots)
while (write (job_fds[1], &c, 1) != 1)
diff --git a/remake.c b/remake.c
index 74c4a9a..d96d4ed 100644
--- a/remake.c
+++ b/remake.c
@@ -316,19 +316,19 @@ update_file (file, depth)
register int status = 0;
register struct file *f;
- /* Prune the dependency graph: if we've already been here on _this_ pass
- through the dependency graph, we don't have to go any further. We won't
- reap_children until we start the next pass, so no state change is
- possible below here until then. */
- if (file->considered == considered)
- {
- DEBUGPR (_("Pruning file `%s'.\n"));
- return 0;
- }
- file->considered = considered;
-
for (f = file->double_colon ? file->double_colon : file; f != 0; f = f->prev)
{
+ /* Prune the dependency graph: if we've already been here on _this_
+ pass through the dependency graph, we don't have to go any further.
+ We won't reap_children until we start the next pass, so no state
+ change is possible below here until then. */
+ if (f->considered == considered)
+ {
+ DEBUGPR (_("Pruning file `%s'.\n"));
+ continue;
+ }
+ f->considered = considered;
+
status |= update_file_1 (f, depth);
check_renamed (f);