Skip to content

Commit

Permalink
Add TokenPool to SubprocessSet::DoWork()
Browse files Browse the repository at this point in the history
- add monitor interface to TokenPool
- posix: monitor token rfd_ in DoWork() too
  • Loading branch information
Stefan Becker committed May 27, 2016
1 parent e1ee0f4 commit 9832d65
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ bool RealCommandRunner::StartCommand(Edge* edge) {
bool RealCommandRunner::WaitForCommand(Result* result) {
Subprocess* subproc;
while ((subproc = subprocs_.NextFinished()) == NULL) {
bool interrupted = subprocs_.DoWork();
bool interrupted = subprocs_.DoWork(tokens_);
if (interrupted)
return false;
}
Expand Down
18 changes: 16 additions & 2 deletions src/subprocess-posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#include "subprocess.h"
#include "tokenpool.h"

#include <assert.h>
#include <errno.h>
Expand Down Expand Up @@ -216,7 +217,7 @@ Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
}

#ifdef USE_PPOLL
bool SubprocessSet::DoWork() {
bool SubprocessSet::DoWork(struct TokenPool* tokens) {
vector<pollfd> fds;
nfds_t nfds = 0;

Expand All @@ -230,6 +231,12 @@ bool SubprocessSet::DoWork() {
++nfds;
}

if (tokens) {
pollfd pfd = { tokens->GetMonitorFd(), POLLIN | POLLPRI, 0 };
fds.push_back(pfd);
++nfds;
}

interrupted_ = 0;
int ret = ppoll(&fds.front(), nfds, NULL, &old_mask_);
if (ret == -1) {
Expand Down Expand Up @@ -266,7 +273,7 @@ bool SubprocessSet::DoWork() {
}

#else // !defined(USE_PPOLL)
bool SubprocessSet::DoWork() {
bool SubprocessSet::DoWork(struct TokenPool* tokens) {
fd_set set;
int nfds = 0;
FD_ZERO(&set);
Expand All @@ -281,6 +288,13 @@ bool SubprocessSet::DoWork() {
}
}

if (tokens) {
int fd = tokens->GetMonitorFd();
FD_SET(fd, &set);
if (nfds < fd+1)
nfds = fd+1;
}

interrupted_ = 0;
int ret = pselect(nfds, &set, 0, 0, 0, &old_mask_);
if (ret == -1) {
Expand Down
2 changes: 1 addition & 1 deletion src/subprocess-win32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
return subprocess;
}

bool SubprocessSet::DoWork() {
bool SubprocessSet::DoWork(struct TokenPool* tokens) {
DWORD bytes_read;
Subprocess* subproc;
OVERLAPPED* overlapped;
Expand Down
4 changes: 3 additions & 1 deletion src/subprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ struct Subprocess {
friend struct SubprocessSet;
};

struct TokenPool;

/// SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
/// DoWork() waits for any state change in subprocesses; finished_
/// is a queue of subprocesses as they finish.
Expand All @@ -77,7 +79,7 @@ struct SubprocessSet {
~SubprocessSet();

Subprocess* Add(const string& command, bool use_console = false);
bool DoWork();
bool DoWork(struct TokenPool* tokens);
Subprocess* NextFinished();
void Clear();

Expand Down
5 changes: 5 additions & 0 deletions src/tokenpool-gnu-make.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct GNUmakeTokenPool : public TokenPool {
virtual void Reserve();
virtual void Release();
virtual void Clear();
virtual int GetMonitorFd();

bool Setup();

Expand Down Expand Up @@ -201,6 +202,10 @@ void GNUmakeTokenPool::Clear() {
Return();
}

int GNUmakeTokenPool::GetMonitorFd() {
return(rfd_);

This comment has been minimized.

Copy link
@colincross

colincross May 28, 2016

This won't work, if there are more tokens than jobs to run then rfd_ will always be readable, the poll in DoWork will return immediately, and ninja will spin.

This comment has been minimized.

Copy link
@stefanb2

stefanb2 May 28, 2016

Owner

Addressed by e486f7a

But unfortunately there is a much bigger problem: RealCommandRunner::WaitForCommand() continues to loop even if there is more work ready to start and tokens have become available. I'll try to address that in another change.

}

struct TokenPool *TokenPool::Get(void) {
GNUmakeTokenPool *tokenpool = new GNUmakeTokenPool;
if (tokenpool->Setup())
Expand Down
6 changes: 6 additions & 0 deletions src/tokenpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ struct TokenPool {
virtual void Release() = 0;
virtual void Clear() = 0;

#ifdef _WIN32
// @TODO
#else
virtual int GetMonitorFd() = 0;
#endif

// returns NULL if token pool is not available
static struct TokenPool *Get(void);
};

0 comments on commit 9832d65

Please sign in to comment.