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 f86b7d03 authored by Kunshan Wang's avatar Kunshan Wang

C binding for threadlocal

parent 6d022bce
......@@ -242,9 +242,16 @@ struct MuCtx {
// Thread and stack creation and stack destruction
MuStackRefValue (*new_stack )(MuCtx *ctx, MuFuncRefValue func);
MuThreadRefValue (*new_thread)(MuCtx *ctx, MuStackRefValue stack,
MuHowToResume htr, MuValue *vals, int nvals, MuRefValue exc);
MuRefValue threadlocal,
MuHowToResume htr, MuValue *vals, int nvals,
MuRefValue exc);
void (*kill_stack)(MuCtx *ctx, MuStackRefValue stack);
// Thread-local object reference
void (*set_threadlocal)(MuCtx *ctx, MuThreadRefValue thread,
MuRefValue threadlocal);
MuRefValue (*get_threadlocal)(MuCtx *ctx, MuThreadRefValue thread);
// Frame cursor operations
MuFCRefValue (*new_cursor )(MuCtx *ctx, MuStackRefValue stack);
void (*next_frame )(MuCtx *ctx, MuFCRefValue cursor);
......
......@@ -8,6 +8,7 @@
#include <muapi.h>
char *hw_string = "Hello world!\n";
char *hw2_string = "Goodbye world!\n";
int main() {
MuVM *mvm = mu_refimpl2_new_ex(1048576, 1048576, 32768);
......@@ -29,7 +30,9 @@ int main() {
".const @the_write <@write.fp> = 0x%lx\n"
".const @the_string <@cvoidptr> = 0x%lx\n"
".const @the_length <@csize_t> = 0x%lx\n"
, (uintptr_t)write, (uintptr_t)hw_string, (unsigned long)strlen(hw_string));
".const @the_length2 <@csize_t> = 0x%lx\n"
, (uintptr_t)write, (uintptr_t)hw_string,
(unsigned long)strlen(hw_string), (unsigned long)strlen(hw2_string));
char *bundle3 =
".funcsig @v_v = ()->()\n"
......@@ -53,11 +56,45 @@ int main() {
MuFuncRefValue func = ctx->handle_from_func(ctx, ctx->id_of(ctx, "@hw"));
MuStackRefValue stack = ctx->new_stack(ctx, func);
MuThreadRefValue thread = ctx->new_thread(ctx, stack, MU_REBIND_PASS_VALUES,
NULL, 0, NULL);
MuThreadRefValue thread = ctx->new_thread(ctx, stack, NULL,
MU_REBIND_PASS_VALUES, NULL, 0, NULL);
mvm->execute(mvm);
char *bundle4 =
".typedef @cchar = int<8>\n"
".typedef @charhybrid = hybrid<@cchar>\n"
".typedef @refvoid = ref<@void>\n"
".funcdef @hw2 VERSION %1 <@v_v> {\n"
" %entry():\n"
" %tl = COMMINST @uvm.get_threadlocal\n"
" %p = COMMINST @uvm.native.pin <@refvoid> (%tl)\n"
" %rv = CCALL #DEFAULT <@write.fp @write.sig> @the_write (@the_fd %p @the_length2)\n"
" COMMINST @uvm.native.unpin <@refvoid> (%tl)\n"
" COMMINST @uvm.thread_exit\n"
"}\n"
;
printf("Loading additional bundle...\n");
ctx->load_bundle(ctx, bundle4, strlen(bundle4));
printf("Bundle loaded. Create a thread-local string object...\n");
MuIntValue hlen = ctx->handle_from_sint32(ctx, 256, 32);
MuRefValue hobj = ctx->new_hybrid(ctx, ctx->id_of(ctx, "@charhybrid"), hlen);
MuUPtrValue hpobj = ctx->pin(ctx, hobj);
char *mustrbuf = (char*)ctx->handle_to_ptr(ctx, hpobj);
strcpy(mustrbuf, hw2_string);
ctx->unpin(ctx, hobj);
printf("Object populated. Create thread with threadlocal and execute...\n");
MuFuncRefValue func2 = ctx->handle_from_func(ctx, ctx->id_of(ctx, "@hw2"));
MuStackRefValue stack2 = ctx->new_stack(ctx, func2);
MuThreadRefValue thread2 = ctx->new_thread(ctx, stack2, hobj,
MU_REBIND_PASS_VALUES, NULL, 0, NULL);
mvm->execute(mvm);
mu_refimpl2_close(mvm);
return 0;
......
......@@ -298,8 +298,13 @@ object NativeMuCtx {
exposeMuValue(ctx, rv)
}
def kill_stack(ctx: MuCtx, stack: MuStackRefValue): Unit = ctx.killStack(stack)
def set_threadlocal(ctx: MuCtx, threadLocal:MuRefValue): Unit = ???
def get_threadlocal(ctx: MuCtx): MuValueFak = ???
def set_threadlocal(ctx: MuCtx, thread: MuThreadRefValue, threadLocal:MuRefValue): Unit = {
ctx.setThreadlocal(thread, threadLocal)
}
def get_threadlocal(ctx: MuCtx, thread: MuThreadRefValue): MuValueFak = {
val rv = ctx.getThreadlocal(thread)
exposeMuValue(ctx, rv)
}
// Frame cursor operations
def new_cursor(ctx: MuCtx, stack: MuStackRefValue): MuValueFak = exposeMuValue(ctx, ctx.newCursor(stack))
......@@ -438,6 +443,7 @@ object ClientAccessibleClassExposer {
val TMicroVM = ru.typeTag[MicroVM].tpe
val TMuCtx = ru.typeTag[MuCtx].tpe
val TMuValue = ru.typeTag[MuValue].tpe
val TOptMuValue = ru.typeTag[Option[MuValue]].tpe
// com.kenai.jffi.Closure.Buffer param getters and return value setters.
// These are partially-applied functions, and will be called in closures (callback from C).
......@@ -458,6 +464,18 @@ object ClientAccessibleClassExposer {
muValue
}
def paramOptMuValue(index: Int, funcName: String, tpe: ru.Type)(buffer: Buffer): Any = {
val muOptValue = getOptMuValue(buffer, index)
muOptValue foreach { muValue => // only check if it is Some(value)
val t = mirror.classSymbol(muValue.getClass).toType
val tpeArg = tpe.typeArgs(0)
require(t <:< tpeArg, "Argument %d of %s expect %s, found %s".format(index, funcName, tpe, t))
}
muOptValue
}
def retVoid(buffer: Buffer, v: Any): Unit = {}
def retByte(buffer: Buffer, v: Any): Unit = buffer.setByteReturn(v.asInstanceOf[Byte])
......@@ -479,6 +497,15 @@ object ClientAccessibleClassExposer {
NativeClientSupport.getMuValueNotNull(addr)
}
private def getOptMuValue(buffer: Buffer, index: Int): Option[MuValue] = {
val addr = buffer.getAddress(index)
if (addr == 0L) {
None
} else {
Some(NativeClientSupport.getMuValueNotNull(addr))
}
}
private def exposeStr(str: String): Word = {
val ptr = NativeClientSupport.stringPool.getOrElseUpdate(str, {
val bytes = str.getBytes(StandardCharsets.US_ASCII)
......@@ -508,6 +535,7 @@ object ClientAccessibleClassExposer {
case t if t =:= TMicroVM => JType.POINTER
case t if t =:= TMuCtx => JType.POINTER
case t if t <:< TMuValue => JType.POINTER
case t if t <:< TOptMuValue => JType.POINTER
}
val MU_NATIVE_ERRNO = 6481626 // muErrno is set to this number if an exception is thrown
......@@ -567,6 +595,7 @@ class ClientAccessibleClassExposer[T: ru.TypeTag: ClassTag](obj: T) {
case t if t =:= TMicroVM => paramMicroVM(i) _
case t if t =:= TMuCtx => paramMuCtx(i) _
case t if t <:< TMuValue => paramMuValue(i, meth.name.toString, t) _
case t if t <:< TOptMuValue => paramOptMuValue(i, meth.name.toString, t) _
}
val returnSetter = returnType match {
......
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