Release the jwack token when doing a synchronous lock wait.

Although we were deadlock-free before, under some circumstances we'd end up
holding a perfectly good token while in sync wait; that would reduce our
parallelism for no good reason.  So give back our tokens before waiting for
anybody else.
This commit is contained in:
Avery Pennarun 2010-12-10 23:04:46 -08:00
commit c4be0050f7
2 changed files with 19 additions and 1 deletions

View file

@ -273,10 +273,18 @@ def main(targets, shouldbuildfunc):
fid,t = locked.pop(0) fid,t = locked.pop(0)
lock = state.Lock(fid) lock = state.Lock(fid)
lock.trylock() lock.trylock()
if not lock.owned: while not lock.owned:
if vars.DEBUG_LOCKS: if vars.DEBUG_LOCKS:
warn('%s (WAITING)\n' % _nice(t)) warn('%s (WAITING)\n' % _nice(t))
# this sequence looks a little silly, but the idea is to
# give up our personal token while we wait for the lock to
# be released; but we should never run get_token() while
# holding a lock, or we could cause deadlocks.
jwack.release_mine()
lock.waitlock() lock.waitlock()
lock.unlock()
jwack.get_token(t)
lock.trylock()
assert(lock.owned) assert(lock.owned)
if vars.DEBUG_LOCKS: if vars.DEBUG_LOCKS:
log('%s (...unlocked!)\n' % _nice(t)) log('%s (...unlocked!)\n' % _nice(t))

View file

@ -24,6 +24,13 @@ def _release(n):
_mytokens = 1 _mytokens = 1
def release_mine():
global _mytokens
assert(_mytokens >= 1)
os.write(_fds[1], 't')
_mytokens -= 1
def _timeout(sig, frame): def _timeout(sig, frame):
pass pass
@ -161,9 +168,12 @@ def running():
def wait_all(): def wait_all():
_debug("wait_all\n") _debug("wait_all\n")
while running(): while running():
while _mytokens >= 1:
release_mine()
_debug("wait_all: wait()\n") _debug("wait_all: wait()\n")
wait(want_token=0) wait(want_token=0)
_debug("wait_all: empty list\n") _debug("wait_all: empty list\n")
get_token('self') # get my token back
if _toplevel: if _toplevel:
bb = '' bb = ''
while 1: while 1: