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