summaryrefslogtreecommitdiffstats
path: root/usr.bin/make
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make')
-rw-r--r--usr.bin/make/Makefile3
-rw-r--r--usr.bin/make/job.c53
-rw-r--r--usr.bin/make/job.h2
3 files changed, 57 insertions, 1 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
index 88027b21..af802d0 100644
--- a/usr.bin/make/Makefile
+++ b/usr.bin/make/Makefile
@@ -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
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) {
diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h
index f5d406b..6220e09 100644
--- a/usr.bin/make/job.h
+++ b/usr.bin/make/job.h
@@ -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 */
/*-
OpenPOWER on IntegriCloud