Commit d85c082d authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Better init idea?

parent d09fdd8b
......@@ -42,7 +42,7 @@ rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "rust-2018", vers
libc="*"
field-offset = "*"
libloading = "*"
lazy_static = "*"
lazy_static = "1.4.0"
log = "*"
stderrlog = "*"
num = "*"
......
......@@ -29,7 +29,7 @@ log = "*"
[dependencies]
mu_utils = {path = "../utils"}
lazy_static = "0.2.11"
lazy_static = "1.4.0"
log = "*"
simple_logger = "*"
regex = "0.2.2"
......
......@@ -746,27 +746,28 @@ impl fmt::Display for MuType_ {
}
}
#[no_mangle]
pub static STRUCT_TAG_MAP_LOC: Option<
AtomicPtr<RwLock<HashMap<StructTag, StructType_>>>
> = None;
#[no_mangle]
pub static HYBRID_TAG_MAP_LOC: Option<
AtomicPtr<RwLock<HashMap<HybridTag, HybridType_>>>
> = None;
pub type StructTagMap = Option<AtomicPtr<RwLock<HashMap<StructTag, StructType_>>>>;
pub static mut STRUCT_TAG_MAP_LOC: StructTagMap = None;
pub type HybridTagMap = Option<AtomicPtr<RwLock<HashMap<HybridTag, HybridType_>>>>;
pub static mut HYBRID_TAG_MAP_LOC: HybridTagMap = None;
lazy_static! {
/// storing a map from MuName to StructType_
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<StructTag, StructType_>> =
match &STRUCT_TAG_MAP_LOC {
&Some(ref ptr) => unsafe{ptr::read(ptr.load(Ordering::Relaxed))},
&None => RwLock::new(HashMap::new())
unsafe {
match &STRUCT_TAG_MAP_LOC {
&Some(ref ptr) => ptr::read(ptr.load(Ordering::Relaxed)),
&None => RwLock::new(HashMap::new())
}
};
/// storing a map from MuName to HybridType_
pub static ref HYBRID_TAG_MAP : RwLock<HashMap<HybridTag, HybridType_>> =
match &HYBRID_TAG_MAP_LOC {
&Some(ref ptr) => unsafe{ptr::read(ptr.load(Ordering::Relaxed))},
&None => RwLock::new(HashMap::new())
unsafe {
match &HYBRID_TAG_MAP_LOC {
&Some(ref ptr) => ptr::read(ptr.load(Ordering::Relaxed)),
&None => RwLock::new(HashMap::new())
}
};
}
......
......@@ -32,10 +32,10 @@ cc = "*"
[dependencies]
mu_utils = {path = "../utils"}
time = "*"
lazy_static = "0.2.11"
lazy_static = "1.4.0"
log = "*"
stderrlog = "*"
aligned_alloc = "*"
crossbeam = "0.3.0"
field-offset = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "rust-2018", version = "^0.4.0" }
\ No newline at end of file
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "rust-2018", version = "^0.4.0" }
......@@ -56,18 +56,13 @@ impl SpaceDescriptor {
}
pub trait Space {
#[inline(always)]
fn start(&self) -> Address;
#[inline(always)]
fn end(&self) -> Address;
#[inline(always)]
fn is_valid_object(&self, addr: Address) -> bool;
fn destroy(&mut self);
fn prepare_for_gc(&mut self);
fn sweep(&mut self);
#[inline(always)]
fn mark_object_traced(&mut self, obj: ObjectReference);
#[inline(always)]
fn is_object_traced(&self, obj: ObjectReference) -> bool;
#[inline(always)]
fn addr_in_space(&self, addr: Address) -> bool {
......@@ -203,7 +198,6 @@ pub trait Allocator {
fn prepare_for_gc(&mut self);
fn set_mutator(&mut self, mutator: *mut Mutator);
fn destroy(&mut self);
#[inline(always)]
fn alloc(&mut self, size: ByteSize, align: ByteSize) -> Address;
}
......
......@@ -230,6 +230,7 @@ pub fn link_dylib_with_extra_srcs(
vm: &VM
) -> PathBuf {
let files = {
use std::fs;
let mut ret = vec![];
for func in funcs {
......@@ -239,7 +240,21 @@ pub fn link_dylib_with_extra_srcs(
for src in srcs {
ret.push(PathBuf::from(src));
}
ret.push(get_path_under_zebu("src/runtime/init.c"));
// copy library resumtion code
let source = get_path_under_zebu(runtime::LIBRARY_RESUME);
let dest = {
let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
ret.push("resume.c");
ret
};
trace!("copying from {:?} to {:?}", source, dest);
match fs::copy(source.as_path(), dest.as_path()) {
Ok(_) => {}
Err(e) => panic!("failed to copy: {}", e)
}
ret.push(dest);
ret.push(get_path_for_mu_context(vm));
ret
......
......@@ -20,20 +20,15 @@
#include <assert.h>
extern void* vm;
extern void* RODAL_END;
extern void mu_main(void*, void*, int, char**);
extern void mu_main(void*, void*, void*, void*, int, char**);
extern uint32_t mu_retval;
extern void* STRUCT_TAG_MAP;
extern void* HYBRID_TAG_MAP;
extern void* STRUCT_TAG_MAP_LOC;
extern void* HYBRID_TAG_MAP_LOC;
int main(int argc, char** argv) {
STRUCT_TAG_MAP_LOC = &STRUCT_TAG_MAP;
HYBRID_TAG_MAP_LOC = &HYBRID_TAG_MAP;
mu_main(&RODAL_END, &vm, argc, argv);
mu_main(&STRUCT_TAG_MAP, &HYBRID_TAG_MAP, &RODAL_END, &vm, argc, argv);
return (int)mu_retval;
}
......@@ -20,7 +20,7 @@
#include <assert.h>
extern void* vm;
extern void* RODAL_END;
extern void mu_main(void*, void*, int, char**);
extern void mu_main(void*, void*, void*, void*, int, char**);
extern uint32_t mu_retval;
......@@ -30,10 +30,7 @@ extern void* STRUCT_TAG_MAP_LOC;
extern void* HYBRID_TAG_MAP_LOC;
int main(int argc, char** argv) {
STRUCT_TAG_MAP_LOC = &STRUCT_TAG_MAP;
HYBRID_TAG_MAP_LOC = &HYBRID_TAG_MAP;
mu_main(&RODAL_END, &vm, argc, argv);
mu_main(&STRUCT_TAG_MAP, &HYBRID_TAG_MAP, &RODAL_END, &vm, argc, argv);
assert(mu_retval == 0);
return (int)mu_retval;
}
......@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(dead_code)]
use super::*;
use std::alloc::{alloc, dealloc, Layout};
......
......@@ -14,7 +14,10 @@
use crate::compiler::backend::RegGroup;
use crate::vm::VM;
use crate::vm::api::{to_CMuVM};
use crate::vm::api::api_c::CMuVM;
use ast::ir::*;
use ast::types::*;
use utils;
use utils::Address;
use utils::Word;
......@@ -262,6 +265,12 @@ impl ValueLocation {
}
}
/// a C wrapper as resume_mu function for shared library boot images"
/// The C wrapper does:
/// 1. loads the persisted VM
/// 2. returns a MuVM* to the VM (for use with the C API)
pub const LIBRARY_RESUME: &'static str = "src/runtime/resume.c";
/// a C wrapper as main function for executable boot images"
/// The C wrapper does:
/// 1. loads the persisted VM
......@@ -286,24 +295,28 @@ pub static mut LAST_TIME: c_ulong = 0;
// RTMU mu_main needs changes
/// the main function for executable boot image, this function will be called
/// from C For RTMu, we start the primordial thread with the default system attr
/// The client can modify this afterwards
/// a function to resume a mu VM dumped as a shared library boot image, this function will be called
/// from C, and returns a MuVM* that works with the C API
#[no_mangle]
pub extern "C" fn mu_init(
pub extern "C" fn mu_resume(
stm: StructTagMap, htm: HybridTagMap,
edata: *const (),
dumped_vm: *mut Arc<VM>,
) {
let vm = init_runtime(edata, dumped_vm);
// convert the current thread into a mu one
unsafe { thread::MuThread::current_thread_as_mu_thread(Address::zero(), vm); }
) -> *mut CMuVM {
// resume the VM and wrap it into a C API object
to_CMuVM(resume_runtime(stm, htm, edata, dumped_vm))
}
fn init_runtime(
fn resume_runtime(
stm: StructTagMap, htm: HybridTagMap,
edata: *const (),
dumped_vm: *mut Arc<VM>,
) -> Arc<VM> {
unsafe {
STRUCT_TAG_MAP_LOC = stm;
HYBRID_TAG_MAP_LOC = htm;
}
VM::start_logging_env();
debug!("mu_main() started...");
......@@ -323,14 +336,19 @@ fn init_runtime(
// );
}
/// the main function for executable boot image, this function will be called
/// from C For RTMu, we start the primordial thread with the default system attr
/// The client can modify this afterwards
#[no_mangle]
pub extern "C" fn mu_main(
stm: StructTagMap, htm: HybridTagMap,
edata: *const (),
dumped_vm: *mut Arc<VM>,
argc: c_int,
argv: *const *const c_char
) {
let vm = init_runtime(edata, dumped_vm);
let vm = resume_runtime(stm, htm, edata, dumped_vm);
// find the primordial function as an entry
let primordial = vm.primordial().read().unwrap();
if primordial.is_none() {
......
......@@ -18,22 +18,16 @@
#include <string.h>
#include <time.h>
#include <assert.h>
extern void* vm;
extern void* RODAL_END;
extern void mu_init(void*, void*);
extern uint32_t mu_retval;
extern void* mu_resume(void*, void*, void*, void*);
extern void* STRUCT_TAG_MAP;
extern void* HYBRID_TAG_MAP;
extern void* STRUCT_TAG_MAP_LOC;
extern void* HYBRID_TAG_MAP_LOC;
void init() {
STRUCT_TAG_MAP_LOC = &STRUCT_TAG_MAP;
HYBRID_TAG_MAP_LOC = &HYBRID_TAG_MAP;
mu_init(&RODAL_END, &vm);
void* resume_mu() { // Returns a MuVM* (see muapi.h)
return mu_resume(&STRUCT_TAG_MAP, &HYBRID_TAG_MAP, &RODAL_END, &vm);
}
......@@ -372,7 +372,7 @@ lazy_static! {
offset_of!(MuThread=>exception_obj).get_byte_offset();
}
use std::os::raw::{c_char, c_int, c_void};
use std::os::raw::{c_char, c_int};
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_os = "macos", target_os = "linux"))]
......@@ -658,9 +658,16 @@ impl MuThread {
// build exception table as we may execute mu function
vm.build_callsite_table();
if !muentry_get_thread_local().is_zero() {
warn!("current thread has a thread local (has a muthread to it)");
return false;
let cur = muentry_get_thread_local();
if !cur.is_zero() {
if Arc::ptr_eq(&vm, &cur.to_ref::<MuThread>().vm) {
warn!("current thread has a thread local (has a muthread to it)");
return false;
} else {
warn!("current thread is attached to a different mu VM, changing this now");
Box::from_raw(cur.to_ptr_mut::<MuThread>()); // destroy old thread structure as we will be making a new one
// TODO: destroy associated stack as well?
}
}
// fake a stack for current thread
......
......@@ -54,7 +54,7 @@ use std::sync::Arc;
// than *mut MuVM or other concrete pointers. But it doesn't matter, because the
// header is only ever read in these three functions.
#[inline(always)]
fn from_MuVM_ptr(ptr: *mut CMuVM) -> *mut MuVM {
pub fn from_MuVM_ptr(ptr: *mut CMuVM) -> *mut MuVM {
debug_assert!(!ptr.is_null());
unsafe { (*ptr).header as *mut MuVM }
}
......
......@@ -36,11 +36,11 @@ pub struct MuVM {
**/
impl MuVM {
/**
** Create a new micro VM instance from scratch.
** Create a micro VM object for the given VM
**/
pub fn new(opts: &str) -> MuVM {
pub fn new(vm: Arc<VM>)->MuVM {
MuVM {
vm: Arc::new(VM::new_with_opts(opts)),
vm: vm,
// Cache C strings. The C client expects `char*` from `name_of`. We
// assume the client won't call `name_of` very often, so
// that we don't need to initialise this hashmap on
......@@ -138,6 +138,16 @@ impl MuVM {
}
}
#[allow(non_snake_case)]
pub fn to_CMuVM(vm: Arc<VM>) -> *mut CMuVM {
make_new_MuVM(Box::into_raw(Box::new(MuVM::new(vm))) as *mut c_void)
}
#[allow(non_snake_case)]
pub unsafe fn from_CMuVM(vm: *mut CMuVM) -> Arc<VM> {
(*from_MuVM_ptr(vm)).vm.clone()
}
/**
** Create a micro VM instance, and expose it as a C-visible `*mut CMuVM`
** pointer.
......@@ -177,14 +187,9 @@ pub extern "C" fn mu_fastimpl_new_with_opts(opts: *const c_char) -> *mut CMuVM {
}
};
let mvm = Box::new(MuVM::new(str_opts));
let mvm_ptr = Box::into_raw(mvm);
debug!("The MuVM instance address: {:?}", mvm_ptr);
let c_mvm = make_new_MuVM(mvm_ptr as *mut c_void);
debug!("The C-visible CMuVM struct address: {:?}", c_mvm);
let c_mvm = to_CMuVM(Arc::new(VM::new_with_opts(str_opts)));
debug!("The MuVM instance address: {:?}", from_MuVM_ptr(c_mvm));
debug!("The C-visible CMuVM struct address: {:?}", c_mvm as *mut c_void);
c_mvm
}
......
......@@ -47,6 +47,12 @@ pub use self::api_impl::mu_fastimpl_new_with_opts;
/// returns a version string for current Zebu build
pub use self::api_impl::mu_get_version;
/// converts a CMuVM into a Arc<VM>
pub use self::api_impl::from_CMuVM;
/// Converts an Arc<VM> into a CMuvm
pub use self::api_impl::to_CMuVM;
mod deps {
pub use crate::vm::handle::APIHandle;
pub use ast::ir::CName;
......
#include "test_lib.h"
#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include "muapi.h"
#include "mu-fastimpl.h"
#define G(id, ...) global_ ## id
#define L(id, ...) local_ ## id
int main() {
MuVM* mvm = mu_fastimpl_new_with_opts("init_mu --aot-emit-dir=emit");
MuCtx* ctx = mvm->new_context(mvm);
MuIRBuilder* irbuilder;
MuID G(0, i64);
MuID G(1, test_mu_new);
MuID G(2);
{
irbuilder = ctx->new_ir_builder(ctx);
G(0, i64) = irbuilder->gen_sym(irbuilder, "@i64");
irbuilder->new_type_int(irbuilder, G(0, i64), 64);
G(1, test_mu_new) = irbuilder->gen_sym(irbuilder, "@test_mu_new");
G(2) = irbuilder->gen_sym(irbuilder, NULL);
irbuilder->new_funcsig(irbuilder, G(2), (MuTypeNode[]){G(0, i64)}, 1, (MuTypeNode[]){G(0, i64)}, 1);
irbuilder->new_func(irbuilder, G(1, test_mu_new), G(2));
MuID L(0) = irbuilder->gen_sym(irbuilder, NULL);
MuID L(1, test_mu_new.__3.entry) = irbuilder->gen_sym(irbuilder, "@test_mu_new.__3.entry");
MuID L(2, test_mu_new.__3.entry.arg) = irbuilder->gen_sym(irbuilder, "@test_mu_new.__3.entry.arg");
MuID L(3) = irbuilder->gen_sym(irbuilder, NULL);
MuID L(4, test_mu_new.__3.entry.obj) = irbuilder->gen_sym(irbuilder, "@test_mu_new.__3.entry.obj");
irbuilder->new_new(irbuilder, L(3), L(4, test_mu_new.__3.entry.obj), G(0, i64), MU_NO_ID);
MuID L(5) = irbuilder->gen_sym(irbuilder, NULL);
MuID L(6, test_mu_new.__3.entry.iobj) = irbuilder->gen_sym(irbuilder, "@test_mu_new.__3.entry.iobj");
irbuilder->new_getiref(irbuilder, L(5), L(6, test_mu_new.__3.entry.iobj), G(0, i64), L(4, test_mu_new.__3.entry.obj));
MuID L(7) = irbuilder->gen_sym(irbuilder, NULL);
irbuilder->new_store(irbuilder, L(7), 0, MU_ORD_NOT_ATOMIC, G(0, i64), L(6, test_mu_new.__3.entry.iobj), L(2, test_mu_new.__3.entry.arg), MU_NO_ID);
MuID L(8) = irbuilder->gen_sym(irbuilder, NULL);
MuID L(9, test_mu_new.__3.entry.res) = irbuilder->gen_sym(irbuilder, "@test_mu_new.__3.entry.res");
irbuilder->new_load(irbuilder, L(8), L(9, test_mu_new.__3.entry.res), 0, MU_ORD_NOT_ATOMIC, G(0, i64), L(6, test_mu_new.__3.entry.iobj), MU_NO_ID);
MuID L(10) = irbuilder->gen_sym(irbuilder, NULL);
irbuilder->new_ret(irbuilder, L(10), (MuVarNode[]){L(9, test_mu_new.__3.entry.res)}, 1);
irbuilder->new_bb(irbuilder, L(1, test_mu_new.__3.entry), (MuID[]){L(2, test_mu_new.__3.entry.arg)}, (MuTypeNode[]){G(0, i64)}, 1, MU_NO_ID, (MuInstNode[]){L(3), L(5), L(7), L(8), L(10)}, 5);
irbuilder->new_func_ver(irbuilder, L(0), G(1, test_mu_new), (MuBBNode[]){L(1, test_mu_new.__3.entry)}, 1);
irbuilder->load(irbuilder);
}
ctx->make_boot_image(ctx,
(MuID[]){G(0, i64), G(1, test_mu_new)}, 2,
NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0,
"test_mu_new.so");
load_lib(); run_current(mvm);
}
#include "test_lib.h"
int main() {
load_lib();
run_resume();
}
../../src/vm/api/mu-fastimpl.h
\ No newline at end of file
../../src/vm/api/muapi.h
\ No newline at end of file
#!/bin/bash
{
echo -e '#include "test_lib.h"'
$MUC -c test_mu_new.uir emit/test_mu_new.so | head -n -1;
echo -e '\n\tload_lib(); run_current(mvm);\n}'
} > main_build.c
gcc -L$MU_ZEBU/target/$ZEBU_BUILD/deps -lmu -ldl main_build.c test_lib.c -o main_build
gcc -L$MU_ZEBU/target/$ZEBU_BUILD/deps -lmu -ldl main_load.c test_lib.c -o main_load
echo "Testing in same process"
./main_build
echo "testing in diferent process"
./main_load
#include <stddef.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include "muapi.h"
#undef NDEBUG
#include <assert.h>
static void* lib = NULL;
void load_lib() {
void *lib = dlopen("./emit/test_mu_new.so", RTLD_GLOBAL);
if (lib == NULL) {
puts(dlerror());
}
assert(lib != NULL);
}
void run_current(MuVM* vm) {
vm->current_thread_as_mu_thread(vm, NULL);
uint64_t (*test_mu_new)(uint64_t) = dlsym(lib, "test_mu_new");
assert(test_mu_new != NULL);
assert(test_mu_new(3) == 3);
}
void run_resume() {
MuVM* (*resume_mu)() = dlsym(lib, "resume_mu");
assert(resume_mu != NULL);
run_current(resume_mu());
}
#include "muapi.h"
extern void load_lib();
extern void run_resume();
extern void run_current(MuVM* vm);
.typedef i64 = int<64>
.funcdef test_mu_new<(i64)->(i64)>
{
entry(<i64> arg):
obj = NEW <i64>
iobj = GETIREF <i64> obj
STORE <i64> iobj arg
res = LOAD <i64> iobj
RET res
}
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