Commit 53057e9d authored by Kunshan Wang's avatar Kunshan Wang

C-initiater.

C programs can start Mu.
parent 8739b1c2
...@@ -39,18 +39,14 @@ lazy val root = (project in file(".")).settings( ...@@ -39,18 +39,14 @@ lazy val root = (project in file(".")).settings(
antlr4GenVisitor in Antlr4 := false antlr4GenVisitor in Antlr4 := false
) )
lazy val jarList = taskKey[Seq[File]]("list dependency jars") lazy val makeClasspathFile = taskKey[Unit]("write the run-time classpath to target/jars.txt as colon-separated list")
jarList := { makeClasspathFile := {
val cp: Seq[File] = (dependencyClasspath in Compile).value.files val cp = (fullClasspath in Runtime).value.files
cp
} println("fullClasspath: \n" + cp.mkString("\n"))
lazy val makeJarListFile = taskKey[Unit]("write a list of dependency jar paths separated by colons (:) to target/jars.txt") val cpStr = cp.mkString(":")
makeJarListFile := { IO.write(new java.io.File("cbinding/classpath.txt"), cpStr)
val jl = jarList.value
val jlStr = jl.mkString(":")
println("Dependency jars: " + jlStr)
IO.write(new java.io.File("cbinding/jars.txt"), jlStr)
} }
*.so *.so
jars.txt test_client
classpath.txt
classpath.h
CFLAGS += -std=gnu11 CFLAGS += -std=gnu11
ifndef JAVA_HOME ifndef JAVA_HOME
$(error JAVA_HOME is required. Invoke with 'make JAVA_HOME=/path/to/java/home') $(error JAVA_HOME is required. Invoke with 'make JAVA_HOME=/path/to/java/home')
endif endif
CFLAGS += -I $(JAVA_HOME)/include
ifndef OS
uname := $(shell uname)
ifeq ($(uname),Darwin)
OS = OSX
else
ifeq ($(uname),Linux)
OS = LINUX
else
$(error Unrecognized operating system $(uname). I currently only worked on OSX and Linux.)
endif
endif
endif
ifeq ($(OS),OSX)
CFLAGS += -I $(JAVA_HOME)/include/darwin
endif
ifeq ($(OS),LINUX)
CFLAGS += -I $(JAVA_HOME)/include/linux
endif
LDFLAGS += -L $(JAVA_HOME)/jre/lib/server -l jvm -rpath $(JAVA_HOME)/jre/lib/server
.PHONY: all .PHONY: all
all: libmurefimpl2start.so all: libs tests
libmurefimpl2start.so: refimpl2-start.c cbinding.txt .PHONY: libs
libs: libmurefimpl2start.so
libmurefimpl2start.so: refimpl2-start.c classpath.h
$(CC) -fPIC -shared $(CFLAGS) -o $@ $< $(LDFLAGS) $(CC) -fPIC -shared $(CFLAGS) -o $@ $< $(LDFLAGS)
cbinding.txt: ../build.sbt classpath.txt: ../build.sbt
cd .. ; sbt makeJarListFile cd .. ; sbt makeClasspathFile
classpath.h: classpath.txt
xxd -i classpath.txt > classpath.h
.PHONY: clean .PHONY: tests
tests: test_client
test_client: test_client.c libmurefimpl2start.so
$(CC) $(CFLAGS) -I . -o $@ $< -L . -l murefimpl2start
.PHONY: clean veryclean
clean: clean:
rm *.so rm *.so test_client
veryclean:
rm *.so test_client classpath.txt classpath.h
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "refimpl2-start.h" #include "refimpl2-start.h"
#include "classpath.h"
static JavaVM *jvm;
static JNIEnv *env;
static jclass cinitiater_cls;
static jmethodID new_mid;
static jmethodID new_ex_mid;
static jmethodID close_mid;
static char *cinitiater_class = "uvm/refimpl/nat/CInitiater";
static char *new_method = "mu_refimpl2_new";
static char *new_ex_method = "mu_refimpl2_new_ex";
static char *close_method = "mu_refimpl2_close";
static int refimpl2_start_debug;
static void init_jvm() {
char *debug_env = getenv("REFIMPL2_START_DEBUG");
if (debug_env != NULL) {
refimpl2_start_debug = 1;
}
JavaVMInitArgs vm_args;
JavaVMOption options[1];
char *cpoptionstr = (char*)calloc(classpath_txt_len + 100, 1);
strcat(cpoptionstr, "-Djava.class.path=");
strncat(cpoptionstr, (const char*)classpath_txt, classpath_txt_len);
options[0].optionString = cpoptionstr;
if (refimpl2_start_debug) {
printf("Classpath option: '%s'\n", cpoptionstr);
}
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_FALSE;
int rv = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (rv != JNI_OK) {
printf("ERROR: Failed to create JVM: %d\n", rv);
exit(1);
}
free(cpoptionstr);
jclass cinitiater_cls = (*env)->FindClass(env, cinitiater_class);
if (cinitiater_cls == NULL) {
printf("ERROR: class %s cannot be found.\n", cinitiater_class);
exit(1);
}
new_mid = (*env)->GetStaticMethodID(env, cinitiater_cls, new_method, "()J");
if (new_mid == NULL) {
printf("ERROR: method %s cannot be found.\n", new_method);
exit(1);
}
new_ex_mid = (*env)->GetStaticMethodID(env, cinitiater_cls, new_ex_method, "(JJJ)J");
if (new_ex_mid == NULL) {
printf("ERROR: method %s cannot be found.\n", new_ex_method);
exit(1);
}
close_mid = (*env)->GetStaticMethodID(env, cinitiater_cls, close_method, "(J)V");
if (close_mid == NULL) {
printf("ERROR: method %s cannot be found.\n", close_method);
exit(1);
}
}
MuVM *mu_refimpl2_new() { MuVM *mu_refimpl2_new() {
return NULL; if (jvm == NULL) {
init_jvm();
}
uintptr_t rv = (*env)->CallStaticLongMethod(env, cinitiater_cls, new_mid);
return (MuVM*)rv;
} }
MuVM *mu_refimpl2_new_ex(int64_t heap_size, int64_t global_size, int64_t stack_size) { MuVM *mu_refimpl2_new_ex(int64_t heap_size, int64_t global_size, int64_t stack_size) {
return NULL; if (jvm == NULL) {
init_jvm();
}
uintptr_t rv = (*env)->CallStaticLongMethod(env, cinitiater_cls, new_ex_mid,
heap_size, global_size, stack_size);
return (MuVM*)rv;
} }
void mu_refimpl2_close(MuVM *mvm) { void mu_refimpl2_close(MuVM *mvm) {
if (jvm == NULL) {
init_jvm();
}
(*env)->CallStaticVoidMethod(env, cinitiater_cls, close_mid, mvm);
} }
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // write
#include <refimpl2-start.h>
#include <muapi.h>
char *hw_string = "Hello world!\n";
int main() {
MuVM *mvm = mu_refimpl2_new_ex(1048576, 1048576, 32768);
MuCtx *ctx = mvm->new_context(mvm);
char *bundle1 =
".typedef @cint = int<32>\n"
".typedef @void = void\n"
".typedef @cvoidptr = uptr<@void>\n"
".typedef @csize_t = int<64>\n"
".funcsig @write.sig = (@cint @cvoidptr @csize_t) -> (@csize_t)\n"
".typedef @write.fp = ufuncptr<@write.sig>\n"
".const @the_fd <@cint> = 1\n"
;
char bundle2[256];
sprintf(bundle2,
".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));
char *bundle3 =
".funcsig @v_v = ()->()\n"
".funcdef @hw VERSION %1 <@v_v> {\n"
" %entry():\n"
" %rv = CCALL #DEFAULT <@write.fp @write.sig> @the_write (@the_fd @the_string @the_length)\n"
" COMMINST @uvm.thread_exit\n"
"}\n"
;
printf("Loading bundles...\n");
printf("Bundle1:\n%s\n", bundle1);
ctx->load_bundle(ctx, bundle1, strlen(bundle1));
printf("Bundle2:\n%s\n", bundle2);
ctx->load_bundle(ctx, bundle2, strlen(bundle2));
printf("Bundle3:\n%s\n", bundle3);
ctx->load_bundle(ctx, bundle3, strlen(bundle3));
printf("Bundles loaded. Execute...\n");
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);
mvm->execute(mvm);
mu_refimpl2_close(mvm);
return 0;
}
package uvm.refimpl.nat;
import uvm.refimpl.MicroVM;
import uvm.refimpl.MicroVM$;
/** Static functions for the convenient of C programs that start Mu via JNI. */
public class CInitiater {
/** Called by the native program, this function creates a Mu instance. */
static long mu_refimpl2_new() {
MicroVM mvm = new MicroVM(MicroVM$.MODULE$.DEFAULT_HEAP_SIZE(), MicroVM$.MODULE$.DEFAULT_GLOBAL_SIZE(),
MicroVM$.MODULE$.DEFAULT_STACK_SIZE());
long fak = NativeClientSupport$.MODULE$.exposeMicroVM(mvm);
return fak;
}
/**
* Called by the native program, this function creates a Mu instance with
* extra arguments.
*/
static long mu_refimpl2_new_ex(long heap_size, long global_size, long stack_size) {
MicroVM mvm = new MicroVM(heap_size, global_size, stack_size);
long fak = NativeClientSupport$.MODULE$.exposeMicroVM(mvm);
return fak;
}
/**
* Called by the native program, this function closes and deallocates a Mu
* instance.
*/
static void mu_refimpl2_close(long mvmFak) {
NativeClientSupport$.MODULE$.unexposeMicroVM(mvmFak);
// does not really deallocate it.
}
}
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