summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/job.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-10-04 20:30:03 +0000
committerphk <phk@FreeBSD.org>2002-10-04 20:30:03 +0000
commit16827939fabe12f22c5b06ee3fdf29f6c10b1de2 (patch)
tree98ed9d47d1a398a3c149f0b83a5ffbf247e2fe59 /usr.bin/make/job.c
parentd4e647af8cfa186194177cf5f696c35a1f1b8505 (diff)
downloadFreeBSD-src-16827939fabe12f22c5b06ee3fdf29f6c10b1de2.zip
FreeBSD-src-16827939fabe12f22c5b06ee3fdf29f6c10b1de2.tar.gz
Give make(1) the ability to use KQUEUE to wait for worker processes
instead of polling for them. Unfortunately we cannot enable it yet because it panics the kernel somewhere in kqueue. Submitted by: Stefan Farfeleder <e0026813@stud3.tuwien.ac.at>
Diffstat (limited to 'usr.bin/make/job.c')
-rw-r--r--usr.bin/make/job.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 92264b2..7026b88 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -106,6 +106,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/time.h>
+#include <sys/event.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
@@ -237,9 +238,13 @@ STATIC Boolean jobFull; /* Flag to tell when the job table is full. It
* (2) a job can only be run locally, but
* nLocal equals maxLocal */
#ifndef RMT_WILL_WATCH
+#ifdef USE_KQUEUE
+static int kqfd; /* File descriptor obtained by kqueue() */
+#else
static fd_set outputs; /* Set of descriptors of pipes connected to
* the output channels of children */
#endif
+#endif
STATIC GNode *lastNode; /* The node for which output was most recently
* produced. */
@@ -692,7 +697,7 @@ JobClose(job)
if (usePipes) {
#ifdef RMT_WILL_WATCH
Rmt_Ignore(job->inPipe);
-#else
+#elif !defined(USE_KQUEUE)
FD_CLR(job->inPipe, &outputs);
#endif
if (job->outPipe != job->inPipe) {
@@ -1267,10 +1272,22 @@ JobExec(job, argv)
* position in the buffer to the beginning and mark another
* stream to watch in the outputs mask
*/
+#ifdef USE_KQUEUE
+ struct kevent kev[2];
+#endif
job->curPos = 0;
#ifdef RMT_WILL_WATCH
Rmt_Watch(job->inPipe, JobLocalInput, job);
+#elif defined(USE_KQUEUE)
+ EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job);
+ EV_SET(&kev[1], job->pid, EVFILT_PROC, EV_ADD | EV_ONESHOT,
+ NOTE_EXIT, 0, NULL);
+ if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) {
+ /* kevent() will fail if the job is already finished */
+ if (errno != EBADF && errno != ESRCH)
+ Punt("kevent: %s", strerror(errno));
+ }
#else
FD_SET(job->inPipe, &outputs);
#endif /* RMT_WILL_WATCH */
@@ -2229,10 +2246,16 @@ void
Job_CatchOutput()
{
int nfds;
+#ifdef USE_KQUEUE
+#define KEV_SIZE 4
+ struct kevent kev[KEV_SIZE];
+ int i;
+#else
struct timeval timeout;
fd_set readfds;
LstNode ln;
Job *job;
+#endif
#ifdef RMT_WILL_WATCH
int pnJobs; /* Previous nJobs */
#endif
@@ -2262,6 +2285,27 @@ Job_CatchOutput()
}
#else
if (usePipes) {
+#ifdef USE_KQUEUE
+ if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) {
+ Punt("kevent: %s", strerror(errno));
+ } else {
+ for (i = 0; i < nfds; i++) {
+ if (kev[i].flags & EV_ERROR) {
+ warnc(kev[i].data, "kevent");
+ continue;
+ }
+ switch (kev[i].filter) {
+ case EVFILT_READ:
+ JobDoOutput(kev[i].udata, FALSE);
+ break;
+ case EVFILT_PROC:
+ /* Just wake up and let Job_CatchChildren() collect the
+ * terminated job. */
+ break;
+ }
+ }
+ }
+#else
readfds = outputs;
timeout.tv_sec = SEL_SEC;
timeout.tv_usec = SEL_USEC;
@@ -2282,6 +2326,7 @@ Job_CatchOutput()
}
Lst_Close(jobs);
}
+#endif /* !USE_KQUEUE */
}
#endif /* RMT_WILL_WATCH */
}
@@ -2411,6 +2456,12 @@ Job_Init(maxproc, maxlocal)
}
#endif
+#ifdef USE_KQUEUE
+ if ((kqfd = kqueue()) == -1) {
+ Punt("kqueue: %s", strerror(errno));
+ }
+#endif
+
begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);
if (begin != NULL) {
OpenPOWER on IntegriCloud