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