mirror of
https://salsa.debian.org/srivasta/make-dfsg.git
synced 2024-12-25 05:29:47 +00:00
* Fix jobserver algorithm again.
* A couple of nits. * Fix considered pruning for double-colon rules.
This commit is contained in:
parent
b3fa4b3c7e
commit
5dc4b92b60
8 changed files with 120 additions and 69 deletions
|
@ -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
|
||||
|
|
52
ChangeLog
52
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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
76
job.c
76
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. */
|
||||
|
||||
else if (job_fds[0] >= 0)
|
||||
if (children == 0)
|
||||
{
|
||||
char token = '-';
|
||||
/* 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)
|
||||
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"));
|
||||
|
||||
/* 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]);
|
||||
|
||||
/* Something's done. We don't want to block for a whole child,
|
||||
just reap whatever's there. */
|
||||
reap_children (0, 0);
|
||||
if (debug_flag)
|
||||
printf (_("Obtained token for child 0x%08lx (%s).\n"),
|
||||
(unsigned long int) c, c->file->name);
|
||||
break;
|
||||
}
|
||||
|
||||
assert (c->job_token != '-');
|
||||
if (debug_flag)
|
||||
printf (_("Obtained token for child 0x%08lx (%s).\n"),
|
||||
(unsigned long int) c, c->file->name);
|
||||
}
|
||||
if (errno != EINTR && errno != EBADF)
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
|
||||
/* 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]);
|
||||
|
||||
/* 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.
|
||||
|
|
1
job.h
1
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;
|
||||
|
|
23
main.c
23
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)
|
||||
|
|
22
remake.c
22
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue