along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "attribs.h"
#include "builtins.h"
#include "lto-common.h"
+#include "opts-jobserver.h"
-
-/* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */
+/* Number of parallel tasks to run. */
static int lto_parallelism;
+/* Number of active WPA streaming processes. */
+static int nruns = 0;
+
+/* GNU make's jobserver info. */
+static jobserver_info *jinfo = NULL;
+
/* Return true when NODE has a clone that is analyzed (i.e. we need
to load its body even if the node itself is not needed). */
"streaming subprocess was killed by signal");
}
while (!WIFEXITED (status) && !WIFSIGNALED (status));
+
+ --nruns;
+
+ /* Return token to the jobserver if active. */
+ if (jinfo != NULL && jinfo->is_active)
+ jinfo->return_token ();
}
#endif
bool ARG_UNUSED (last))
{
#ifdef HAVE_WORKING_FORK
- static int nruns;
-
if (lto_parallelism <= 1)
{
stream_out_partitions_1 (temp_filename, blen, min, max);
return;
}
- /* Do not run more than LTO_PARALLELISM streamings
- FIXME: we ignore limits on jobserver. */
if (lto_parallelism > 0 && nruns >= lto_parallelism)
- {
- wait_for_child ();
- nruns --;
- }
+ wait_for_child ();
+
/* If this is not the last parallel partition, execute new
streaming process. */
if (!last)
{
+ if (jinfo != NULL && jinfo->is_active)
+ while (true)
+ {
+ if (jinfo->get_token ())
+ break;
+ if (nruns > 0)
+ wait_for_child ();
+ else
+ {
+ /* There are no free tokens, lets do the job outselves. */
+ stream_out_partitions_1 (temp_filename, blen, min, max);
+ asm_nodes_output = true;
+ return;
+ }
+ }
+
pid_t cpid = fork ();
if (!cpid)
/* Last partition; stream it and wait for all children to die. */
else
{
- int i;
stream_out_partitions_1 (temp_filename, blen, min, max);
- for (i = 0; i < nruns; i++)
+ while (nruns > 0)
wait_for_child ();
+
+ if (jinfo != NULL && jinfo->is_active)
+ jinfo->disconnect ();
}
asm_nodes_output = true;
#else
lto_parallelism = 1;
- /* TODO: jobserver communication is not supported, yet. */
if (!strcmp (flag_wpa, "jobserver"))
- lto_parallelism = param_max_lto_streaming_parallelism;
+ {
+ jinfo = new jobserver_info ();
+ if (jinfo->is_active)
+ jinfo->connect ();
+
+ lto_parallelism = param_max_lto_streaming_parallelism;
+ }
else
{
lto_parallelism = atoi (flag_wpa);
if (!error_msg.empty ())
error_msg = "jobserver is not available: " + error_msg;
}
+
+void
+jobserver_info::connect ()
+{
+ if (!pipe_path.empty ())
+ pipefd = open (pipe_path.c_str (), O_RDWR);
+}
+
+void
+jobserver_info::disconnect ()
+{
+ if (!pipe_path.empty ())
+ {
+ gcc_assert (close (pipefd) == 0);
+ pipefd = -1;
+ }
+}
+
+bool
+jobserver_info::get_token ()
+{
+ int fd = pipe_path.empty () ? rfd : pipefd;
+ char c;
+ unsigned n = read (fd, &c, 1);
+ if (n != 1)
+ {
+ gcc_assert (errno == EAGAIN);
+ return false;
+ }
+ else
+ return true;
+}
+
+void
+jobserver_info::return_token ()
+{
+ int fd = pipe_path.empty () ? wfd : pipefd;
+ char c = 'G';
+ gcc_assert (write (fd, &c, 1) == 1);
+}
/* Default constructor. */
jobserver_info ();
+ /* Connect to the server. */
+ void connect ();
+
+ /* Disconnect from the server. */
+ void disconnect ();
+
+ /* Get token from the server. */
+ bool get_token ();
+
+ /* Return token to the server. */
+ void return_token ();
+
/* Error message if there is a problem. */
string error_msg = "";
/* Skipped MAKEFLAGS where --jobserver-auth is skipped. */
int wfd = -1;
/* Named pipe path. */
string pipe_path = "";
+ /* Pipe file descriptor. */
+ int pipefd = -1;
/* Return true if jobserver is active. */
bool is_active = false;
};