--- make-3.82.90/job.h	Mon Jul 12 21:20:41 2010
+++ make-3.82.90-mod/job.h	Mon Apr 11 14:24:29 2011
@@ -64,6 +64,8 @@
     unsigned int good_stdin:1;	/* Nonzero if this child has a good stdin.  */
     unsigned int deleted:1;	/* Nonzero if targets have been deleted.  */
     unsigned int dontcare:1;    /* Saved dontcare flag.  */
+    FILE *tempout;		/* Optional place to save stdout */
+    FILE *temperr;		/* Optional place to save stderr */
   };
 
 extern struct child *children;
--- make-3.82.90/job.c	Sat Nov  6 17:56:24 2010
+++ make-3.82.90-mod/job.c	Tue Apr 12 13:30:05 2011
@@ -243,6 +243,10 @@
 /* Number of jobserver tokens this instance is currently using.  */
 
 unsigned int jobserver_tokens = 0;
+
+/* File descriptor to use as a sync semaphore in -j mode. */
+
+int syncfd = -2;
 
 #ifdef WINDOWS32
 /*
@@ -514,6 +518,52 @@
   */
 }
 
+/* Synchronize the output of jobs in -j mode to keep the results of
+   each job together. This is done by holding the results in temp files,
+   one each for stdout and stderr, and only releasing them to "real"
+   stdout and stderr when an exclusive lock can be obtained. */
+
+static void
+sync_output(struct child *c)
+{
+  ssize_t nread;
+  char buffer[8192];
+  struct flock fl;
+
+  if (lseek(fileno(c->tempout), 0, SEEK_SET) == -1)
+    perror("lseek");
+  if (lseek(fileno(c->temperr), 0, SEEK_SET) == -1)
+    perror("lseek");
+
+  memset(&fl, 0, sizeof(fl));
+  fl.l_type = F_WRLCK;
+  fl.l_whence = SEEK_SET;
+  fl.l_pid = getpid();
+  fl.l_start = fl.l_len = 0;
+  if (fcntl(syncfd, F_SETLKW, &fl) == -1)
+    perror("fcntl");
+  else
+    {
+      /*
+       * We've entered the "critical section" during which a lock is held.
+       * We want to keep it as short as possible.
+       */
+      while ((nread = fread(buffer, 1, sizeof(buffer), c->tempout)) > 0)
+	write(fileno(stdout), buffer, nread);
+
+      while ((nread = fread(buffer, 1, sizeof(buffer), c->temperr)) > 0)
+	write(fileno(stderr), buffer, nread);
+
+      /* Exit the critical section */
+      fl.l_type = F_UNLCK;
+      if (fcntl(syncfd, F_SETLKW, &fl) == -1)
+	perror("fcntl");
+    }
+
+  fclose(c->tempout);
+  fclose(c->temperr);
+}
+
 extern int shell_function_pid, shell_function_completed;
 
 /* Reap all dead children, storing the returned status and the new command
@@ -790,6 +840,10 @@
         c->sh_batch_file = NULL;
       }
 
+      /* Synchronize parallel output if requested */
+      if (syncfd >= 0 && c->tempout)
+	sync_output(c);
+
       /* If this child had the good stdin, say it is now free.  */
       if (c->good_stdin)
         good_stdin_used = 0;
@@ -1053,6 +1107,7 @@
 #else
   char **argv;
 #endif
+  char *syncfile;
 
   /* If we have a completely empty commandset, stop now.  */
   if (!child->command_ptr)
@@ -1356,6 +1411,26 @@
 
 #else  /* !__EMX__ */
 
+      if ((syncfile = variable_expand_for_file("$(MAKESYNCFILE)", child->file))
+	  && *syncfile)
+	{
+	  /*
+	   * Note that we never write to the syncfile but must _open_
+	   * it for write in order for fcntl() to acquire the lock.
+	   */
+	  if (syncfd == -2 && (syncfd = open(syncfile, O_WRONLY|O_APPEND)) == -1)
+	    perror(syncfile);
+	  else if (syncfd >= 0)
+	    if (!(child->tempout = tmpfile()) || !(child->temperr = tmpfile()))
+	      {
+		perror("tmpfile()");
+		goto error;
+	      }
+	}
+      else
+	syncfd = -2;
+
       child->pid = vfork ();
       environ = parent_environ;	/* Restore value child may have clobbered.  */
       if (child->pid == 0)
@@ -1379,6 +1454,22 @@
             setrlimit (RLIMIT_STACK, &stack_limit);
 #endif
 
+	  /* Arrange to collect output into tempfiles */
+	  if (syncfd >= 0)
+	    {
+	      int outfd = fileno(stdout);
+	      int errfd = fileno(stderr);
+
+	      if ((close(outfd) == -1)
+		|| (dup2(fileno(child->tempout), outfd) == -1)
+		|| (close(errfd) == -1)
+		|| (dup2(fileno(child->temperr), errfd) == -1))
+	      {
+		perror("dup2()");
+		goto error;
+	      }
+	    }
+
 	  child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
                              argv, child->environment);
 	}
