GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

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(
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 := {
val cp: Seq[File] = (dependencyClasspath in Compile).value.files
cp
}
makeClasspathFile := {
val cp = (fullClasspath in Runtime).value.files
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 := {
val jl = jarList.value
val jlStr = jl.mkString(":")
println("Dependency jars: " + jlStr)
IO.write(new java.io.File("cbinding/jars.txt"), jlStr)
IO.write(new java.io.File("cbinding/classpath.txt"), cpStr)
}
*.so
jars.txt
test_client
classpath.txt
classpath.h
CFLAGS += -std=gnu11
ifndef JAVA_HOME
$(error JAVA_HOME is required. Invoke with 'make JAVA_HOME=/path/to/java/home')
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
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)
cbinding.txt: ../build.sbt
cd .. ; sbt makeJarListFile
classpath.txt: ../build.sbt
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:
rm *.so
rm *.so test_client
veryclean:
rm *.so test_client classpath.txt classpath.h
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <jni.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() {
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) {
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) {
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