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>
This commit is contained in:
parent
fa778f80c2
commit
5fd43411f3
@ -20,6 +20,9 @@ CFLAGS+=-DMAKE_VERSION=\"5200209170\"
|
||||
CFLAGS+=-D__FBSDID=__RCSID
|
||||
.endif
|
||||
|
||||
# XXX: kernel currently broken
|
||||
# CFLAGS+=-DUSE_KQUEUE
|
||||
|
||||
main.o: ${MAKEFILE}
|
||||
|
||||
# Set the shell which make(1) uses. Bourne is the default, but a decent
|
||||
|
@ -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) {
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
#define TMPPAT "/tmp/makeXXXXXXXXXX"
|
||||
|
||||
#ifndef USE_KQUEUE
|
||||
/*
|
||||
* The SEL_ constants determine the maximum amount of time spent in select
|
||||
* before coming out to see if a child has finished. SEL_SEC is the number of
|
||||
@ -57,6 +58,7 @@
|
||||
*/
|
||||
#define SEL_SEC 0
|
||||
#define SEL_USEC 100000
|
||||
#endif /* !USE_KQUEUE */
|
||||
|
||||
|
||||
/*-
|
||||
|
Loading…
Reference in New Issue
Block a user