Commit 68adfdb2 authored by Guido Trotter's avatar Guido Trotter
Browse files

Processor: Acquire locks before executing an LU

If we're running in a "new style" LU we may need some locks, as required
by the ExpandNames function, to be able to run. We'll walk up the lock
levels present in the needed_locks dictionary and acquire them, then run
the actual LU. LUs can release some or all the acquired locks, if they
want, before terminating, provided they update their needed_locks
dictionary appropriately, so that we know not to release a level if they
have already done so.

Reviewed-by: iustinp
parent d465bdc8
......@@ -123,6 +123,29 @@ class Processor(object):
return result
def _LockAndExecLU(self, lu, level):
"""Execute a Logical Unit, with the needed locks.
This is a recursive function that starts locking the given level, and
proceeds up, till there are no more locks to acquire. Then it executes the
given LU and its opcodes.
"""
if level in lu.needed_locks:
# This is always safe to do, as we can't acquire more/less locks than
# what was requested.
lu.needed_locks[level] = self.context.glm.acquire(level,
lu.needed_locks[level])
try:
result = self._LockAndExecLU(lu, level + 1)
finally:
if lu.needed_locks[level]:
self.context.glm.release(level)
else:
result = self._ExecLU(lu)
return result
def ExecOpCode(self, op):
"""Execute an opcode.
......@@ -151,7 +174,8 @@ class Processor(object):
self.exclusive_BGL = lu_class.REQ_BGL
lu = lu_class(self, op, self.context, sstore)
lu.ExpandNames()
result = self._ExecLU(lu)
assert lu.needed_locks is not None, "needed_locks not set by LU"
result = self._LockAndExecLU(lu, locking.LEVEL_NODE)
finally:
self.context.glm.release(locking.LEVEL_CLUSTER)
self.exclusive_BGL = False
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment