GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit ccf57143 authored by Kunshan Wang's avatar Kunshan Wang

Python binding for threadlocal

parent f86b7d03
......@@ -86,7 +86,7 @@ with mu.new_context() as ctx:
_start = ctx.handle_from_func(id_of("@_start"))
st = ctx.new_stack(_start)
th = ctx.new_thread(st, PassValues(args, rvbox))
th = ctx.new_thread(st, None, PassValues(args, rvbox))
mu.execute()
......
......@@ -66,7 +66,7 @@ example::
arg1 = ctx.handle_from_int(10, 64)
arg2 = ctx.handle_from_double(3.14)
stack = ctx.new_stack(func)
thread = ctx.new_thread(stack, PassValues(arg1, arg2))
thread = ctx.new_thread(stack, None, PassValues(arg1, arg2))
mu.execute() # The thread will actually run now.
......@@ -103,7 +103,7 @@ be pasesed into methods like in C. For example::
func = ctx.handle_from_func(id_of("@factorial"))
arg = ctx.handle_from_int(10, 64)
stack = ctx.new_stack(func)
thread = ctx.new_thread(stack, PassValues(arg))
thread = ctx.new_thread(stack, None, PassValues(arg))
Type checks are performed on each and every method call. Handles (instances of
MuValue) must match the expected argument types. For example, if a method
......@@ -780,21 +780,29 @@ class MuCtx(_StructOfMethodsWrapper):
defaults to MU_SEQ_CST."""
return self.fence_(ord)
def new_thread(self, stack, how_to_resume):
def new_thread(self, stack, threadlocal, how_to_resume):
"""Wrapper of the underlying ``new_thread``.
This method now takes only a stack and a ``HowToResume`` value which can
be either ``PassValues`` or ``ThrowExc``.
This method now takes only a stack, a threadlocal and a ``HowToResume``
value which can be either ``PassValues`` or ``ThrowExc``.
Arguments:
stack: a MuStackRefValue, the initial stack the new thread should
bind to.
threadlocal: a MuRefValue or None, the initial thread-local objref
of the created thread.
how_to_resume: a HowToResume value. See the docstring of
MuTrapHandler.
Returns:
a MuThreadRefValue, referring to the newly created thread.
"""
if threadlocal == None:
threadlocal = 0
else:
_assert_instance(threadlocal, MuRefValue)
_assert_instance(how_to_resume, HowToResume)
if isinstance(how_to_resume, PassValues):
htr = CMU_REBIND_PASS_VALUES
......@@ -812,7 +820,7 @@ class MuCtx(_StructOfMethodsWrapper):
cnvals = 0
cexc = exc.c_mu_value
return self.new_thread_(stack, htr, cvals, cnvals, cexc)
return self.new_thread_(stack, threadlocal, htr, cvals, cnvals, cexc)
def dump_keepalives(self, cursor, nvals):
"""Wrapper of the underlying ``dump_keepalives``.
......@@ -1014,9 +1022,11 @@ _initialize_methods(MuCtx, [
("fence_" , None , [CMuMemOrd]),
("new_stack" , MuStackRefValue , [MuFuncRefValue]),
("new_thread_" , MuThreadRefValue , [MuStackRefValue, CMuHowToResume,
ctypes.POINTER(CMuValue), ctypes.c_int, CMuRefValue]),
("new_thread_" , MuThreadRefValue , [MuStackRefValue, CMuRefValue,
CMuHowToResume, ctypes.POINTER(CMuValue), ctypes.c_int, CMuRefValue]),
("kill_stack" , None , [MuStackRefValue]),
("set_threadlocal" , None , [MuThreadRefValue, MuRefValue]),
("get_threadlocal" , MuRefValue , [MuThreadRefValue]),
("new_cursor" , MuFCRefValue , [MuStackRefValue]),
("next_frame" , None , [MuFCRefValue]),
......
......@@ -75,6 +75,18 @@ with mu.new_context() as ctx:
.typedef @void = void
.typedef @refvoid = ref<@void>
.const @NULLREF <@refvoid> = NULL
.funcsig @trap_threadlocal.sig = (@refvoid @refvoid) -> ()
.funcdef @trap_threadlocal VERSION %v1 <@trap_threadlocal.sig> {
%entry(<@refvoid> %r1 <@refvoid> %r2):
%r3 = COMMINST @uvm.get_threadlocal
[%trap1] TRAP <> KEEPALIVE (%r1 %r2 %r3)
%r4 = COMMINST @uvm.get_threadlocal
[%trap2] TRAP <> KEEPALIVE (%r1 %r2 %r4)
COMMINST @uvm.thread_exit
}
""")
class TestRefImpl2CBinding(unittest.TestCase):
......@@ -244,7 +256,7 @@ class TestRefImpl2CBinding(unittest.TestCase):
main = ctx.handle_from_func(id_of("@main"))
st = ctx.new_stack(main)
th = ctx.new_thread(st, PassValues(forty_two))
th = ctx.new_thread(st, None, PassValues(forty_two))
mu.execute()
......@@ -272,7 +284,7 @@ class TestRefImpl2CBinding(unittest.TestCase):
func = ctx.handle_from_func(id_of("@trap_exit_test"))
st = ctx.new_stack(func)
th = ctx.new_thread(st, PassValues(forty_two))
th = ctx.new_thread(st, None, PassValues(forty_two))
mu.execute()
......@@ -308,7 +320,7 @@ class TestRefImpl2CBinding(unittest.TestCase):
func = ctx.handle_from_func(id_of("@trap_exit_test"))
st = ctx.new_stack(func)
th = ctx.new_thread(st, PassValues(forty_two))
th = ctx.new_thread(st, None, PassValues(forty_two))
mu.execute()
......@@ -365,7 +377,7 @@ class TestRefImpl2CBinding(unittest.TestCase):
func = ctx.handle_from_func(id_of("@trap_rebind_test"))
st = ctx.new_stack(func)
th = ctx.new_thread(st, PassValues())
th = ctx.new_thread(st, None, PassValues())
mu.execute()
......@@ -378,8 +390,71 @@ class TestRefImpl2CBinding(unittest.TestCase):
func = ctx.handle_from_func(id_of("@trap_rebind_test"))
st = ctx.new_stack(func)
th = ctx.new_thread(st, PassValues())
th = ctx.new_thread(st, None, PassValues())
mu.execute()
self.assertEqual(test_result2, [True])
def test_trap_threadlocal(self):
ctx = self.ctx
id_of = ctx.id_of
name_of = ctx.name_of
box = []
class MyHandler(MuTrapHandler):
def handle_trap(self, ctx, thread, stack, wpid):
print("Hey! This is Python!")
cursor = ctx.new_cursor(stack)
iid = ctx.cur_inst(cursor)
if name_of(iid) == "@trap_threadlocal.v1.entry.trap1":
r1, r2, r3 = ctx.dump_keepalives(cursor, 3)
r1 = r1.cast(MuRefValue)
r2 = r2.cast(MuRefValue)
r3 = r3.cast(MuRefValue)
ctx.close_cursor(cursor)
rl = ctx.get_threadlocal(thread)
eql = ctx.ref_eq(rl, r3)
box.append(eql)
eq1 = ctx.ref_eq(r1, r3)
box.append(eq1)
ctx.set_threadlocal(thread, r2)
elif name_of(iid) == "@trap_threadlocal.v1.entry.trap2":
r1, r2, r4 = ctx.dump_keepalives(cursor, 3)
r1 = r1.cast(MuRefValue)
r2 = r2.cast(MuRefValue)
r4 = r4.cast(MuRefValue)
ctx.close_cursor(cursor)
rl = ctx.get_threadlocal(thread)
eql = ctx.ref_eq(rl, r4)
box.append(eql)
eq2 = ctx.ref_eq(r2, r4)
box.append(eq2)
return Rebind(stack, PassValues())
mh1 = MyHandler()
mu.set_trap_handler(mh1)
ref1 = ctx.new_fixed(id_of("@i64"))
ref2 = ctx.new_fixed(id_of("@i64"))
func = ctx.handle_from_func(id_of("@trap_threadlocal"))
st = ctx.new_stack(func)
th = ctx.new_thread(st, ref1, PassValues(ref1, ref2))
mu.execute()
self.assertEqual(box, [True, True, True, True])
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