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 f3670528 authored by qinsoon's avatar qinsoon

[wip] keep on thread impl

parent 6d46f0fb
......@@ -18,4 +18,5 @@ simple_logger = "0.4.0"
nalgebra = "0.8.2"
linked-hash-map = "0.0.10"
hprof = "0.1.3"
memmap = "0.4.0"
\ No newline at end of file
memmap = "0.4.0"
memsec = "0.1.9"
\ No newline at end of file
......@@ -11,11 +11,11 @@ use std::default;
use std::sync::RwLock;
use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use utils::Address;
pub type WPID = usize;
pub type MuID = usize;
pub type MuName = &'static str;
pub type Address = usize; // TODO: replace this with Address(usize)
pub type OpIndex = usize;
......@@ -633,8 +633,8 @@ impl fmt::Display for MemoryLocation {
#[derive(Debug)] // Display, PartialEq
pub struct MuEntityHeader {
id: MuID,
name: RwLock<Option<MuName>>
pub id: MuID,
pub name: RwLock<Option<MuName>>
}
impl MuEntityHeader {
......
#[macro_use]
pub mod inst;
pub mod ir;
pub mod inst;
pub mod types;
pub mod ir;
pub mod ir_semantics;
pub mod ptr;
pub mod op;
pub mod op;
\ No newline at end of file
......@@ -42,6 +42,9 @@ struct ASMCode {
block_liveout: HashMap<MuName, Vec<MuID>>
}
unsafe impl Send for ASMCode {}
unsafe impl Sync for ASMCode {}
impl MachineCode for ASMCode {
fn number_of_insts(&self) -> usize {
self.code.len()
......@@ -1087,10 +1090,10 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
use std::path;
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&fv.func_id).unwrap().borrow();
let func = funcs.get(&fv.func_id).unwrap().read().unwrap();
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(&fv.id()).unwrap().borrow();
let cf = compiled_funcs.get(&fv.id()).unwrap().read().unwrap();
let code = cf.mc.emit();
......
......@@ -161,7 +161,7 @@ impl <'a> InstructionSelection {
if self.match_funcref_const(func) {
let target_id = self.emit_get_funcref_const(func);
let funcs = vm.funcs().read().unwrap();
let target = funcs.get(&target_id).unwrap().borrow();
let target = funcs.get(&target_id).unwrap().read().unwrap();
if vm.is_running() {
unimplemented!()
......@@ -790,7 +790,7 @@ impl CompilerPass for InstructionSelection {
debug!("{}", self.name());
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_ver.func_id).unwrap().borrow();
let func = funcs.get(&func_ver.func_id).unwrap().read().unwrap();
self.backend.start_code(func.name().unwrap());
// prologue (get arguments from entry block first)
......
......@@ -57,7 +57,7 @@ impl CompilerPass for PeepholeOptimization {
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().borrow_mut();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
for i in 0..cf.mc.number_of_insts() {
self.remove_redundant_move(i, &mut cf);
......
......@@ -25,7 +25,7 @@ impl RegisterAllocation {
// returns true if we spill registers (which requires another instruction selection)
fn coloring(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> bool {
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().borrow_mut();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
cf.mc.trace_mc();
......
......@@ -6,6 +6,7 @@ extern crate immix_rust as gc;
#[macro_use]
pub mod utils;
#[macro_use]
pub mod ast;
pub mod vm;
pub mod compiler;
......
pub mod thread;
\ No newline at end of file
pub extern crate immix_rust as gc;
pub use gc::common::Address;
pub use gc::common::ObjectReference;
pub type Word = usize;
pub mod thread;
pub enum RuntimeValue {
Pointer(Address),
Value(Word)
}
\ No newline at end of file
......@@ -6,7 +6,3 @@ __thread void* mu_tls;
void* init_thread_local(void* local) {
return NULL;
}
void* aligned_mem(uint64_t size, uint64_t align) {
}
extern crate memmap;
#![allow(dead_code)]
use gc::Mutator;
use ast::ir::*;
use ast::ptr::*;
use ast::types::*;
use vm::VM;
use runtime::RuntimeValue;
use runtime::gc;
use utils::ByteSize;
use utils::Address;
use utils::mem::memmap;
use utils::mem::memsec;
use std::sync::Arc;
use std::thread;
use std::thread::JoinHandle;
pub const STACK_SIZE : ByteSize = (4 << 20); // 4mb
#[cfg(target_arch = "x86_64")]
pub const PAGE_SIZE : ByteSize = (4 << 10); // 4kb
impl_mu_entity!(MuThread);
impl_mu_entity!(MuStack);
pub struct MuStack {
hdr: MuEntityHeader,
pub hdr: MuEntityHeader,
func_id: MuID,
size: ByteSize,
state: MuStackState,
size: ByteSize,
// lo addr hi addr
// | overflow guard page | actual stack ..................... | underflow guard page|
// | | | |
......@@ -26,6 +42,11 @@ pub struct MuStack {
upper_bound : Address,
underflow_guard: Address,
// this frame pointers should only be used when stack is not active
sp : Address,
bp : Address,
ip : Address,
exception_obj : Option<Address>,
#[allow(dead_code)]
......@@ -33,7 +54,7 @@ pub struct MuStack {
}
impl MuStack {
pub fn new(id: MuID, func_id: MuID) -> MuStack {
pub fn new(id: MuID, func: &MuFunction) -> MuStack {
let total_size = PAGE_SIZE * 2 + STACK_SIZE;
let anon_mmap = match memmap::Mmap::anonymous(total_size, memmap::Protection::ReadWrite) {
......@@ -41,15 +62,84 @@ impl MuStack {
Err(_) => panic!("failed to mmap for a stack"),
};
let overflow_guard = Address::from_ptr(anon_mmap.ptr());
let mmap_start = Address::from_ptr(anon_mmap.ptr());
debug_assert!(mmap_start.is_aligned_to(PAGE_SIZE));
let overflow_guard = mmap_start;
let lower_bound = mmap_start.plus(PAGE_SIZE);
let upper_bound = lower_bound.plus(STACK_SIZE);
let underflow_guard = upper_bound;
unsafe {
memsec::mprotect(overflow_guard.to_ptr_mut::<u8>(), PAGE_SIZE, memsec::Prot::NoAccess);
memsec::mprotect(underflow_guard.to_ptr_mut::<u8>(), PAGE_SIZE, memsec::Prot::NoAccess);
}
unimplemented!()
debug!("creating stack {} with entry func {:?}", id, func);
debug!("overflow_guard : {}", overflow_guard);
debug!("lower_bound : {}", lower_bound);
debug!("upper_bound : {}", upper_bound);
debug!("underflow_guard: {}", underflow_guard);
MuStack {
hdr: MuEntityHeader::unnamed(id),
func_id: func.id(),
state: MuStackState::Ready(func.sig.arg_tys.clone()),
size: STACK_SIZE,
overflow_guard: overflow_guard,
lower_bound: lower_bound,
upper_bound: upper_bound,
underflow_guard: upper_bound,
sp: upper_bound,
bp: upper_bound,
ip: unsafe {Address::zero()},
exception_obj: None,
mmap: anon_mmap
}
}
}
pub enum MuStackState {
Ready(Vec<P<MuType>>), // ready to resume when values of given types are supplied (can be empty)
Active,
Dead
}
pub struct MuThread {
hdr: MuEntityHeader,
allocator: Box<Mutator>,
pub hdr: MuEntityHeader,
allocator: Box<gc::Mutator>,
stack: Option<Box<MuStack>>,
user_tls: Option<Address>
}
impl MuThread {
pub fn new(id: MuID, allocator: Box<gc::Mutator>, stack: Box<MuStack>, user_tls: Option<Address>) -> MuThread {
MuThread {
hdr: MuEntityHeader::unnamed(id),
allocator: allocator,
stack: Some(stack),
user_tls: user_tls
}
}
user_tls: Address
pub fn launch(id: MuID, stack: Box<MuStack>, user_tls: Option<Address>, vals: Vec<RuntimeValue>, vm: &VM) -> JoinHandle<()> {
match thread::Builder::new().name(format!("Mu Thread #{}", id)).spawn(move || {
let mut muthread = Box::new(MuThread::new(id, gc::new_mutator(), stack, user_tls));
MuThread::thread_entry(muthread, vm);
}) {
Ok(handle) => handle,
Err(_) => panic!("failed to create a thread")
}
}
/// entry function for launching a mu thread
pub fn thread_entry(mu_thread: Box<MuThread>, vm: &VM) -> ! {
}
}
\ No newline at end of file
pub extern crate memmap;
pub extern crate memsec;
\ No newline at end of file
#![allow(dead_code)]
extern crate immix_rust as gc;
pub use gc::common::Address;
pub use gc::common::ObjectReference;
pub type ByteSize = usize;
pub mod mem;
mod linked_hashset;
pub use utils::linked_hashset::LinkedHashSet;
pub use utils::linked_hashset::LinkedHashMap;
pub use runtime::Address;
pub use runtime::ObjectReference;
macro_rules! select_value {
($cond: expr, $res1 : expr, $res2 : expr) => {
if $cond {
......
......@@ -456,7 +456,7 @@ impl MuCtx {
fv
} else {
let guard = ctx.internal.vm.funcs().read().unwrap();
let mut func = guard.get(&fid).unwrap().borrow_mut();
let mut func = guard.get(&fid).unwrap().write().unwrap();
let fv = MuFunctionVersion::new(fv_id, fid, func.sig.clone());
func.new_version(fv_id);
......
extern crate immix_rust as gc;
use std::collections::HashMap;
use ast::ptr::P;
......@@ -9,12 +7,16 @@ use compiler::backend;
use compiler::backend::BackendTypeInfo;
use vm::machine_code::CompiledFunction;
use vm::vm_options::VMOptions;
use runtime::gc;
use runtime::thread::MuStack;
use runtime::RuntimeValue;
use runtime::thread::MuThread;
use utils::Address;
use std::sync::RwLock;
use std::cell::RefCell;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
use std::thread::JoinHandle;
pub struct VM {
next_id: AtomicUsize,
......@@ -31,10 +33,12 @@ pub struct VM {
func_sigs: RwLock<HashMap<MuID, P<MuFuncSig>>>,
// key: (func_id, func_ver_id)
func_vers: RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>>,
funcs: RwLock<HashMap<MuID, RefCell<MuFunction>>>,
func_vers: RwLock<HashMap<(MuID, MuID), RwLock<MuFunctionVersion>>>,
funcs: RwLock<HashMap<MuID, RwLock<MuFunction>>>,
compiled_funcs: RwLock<HashMap<MuID, RwLock<CompiledFunction>>>,
compiled_funcs: RwLock<HashMap<MuID, RefCell<CompiledFunction>>>
threads: RwLock<Vec<JoinHandle<()>>>
}
impl <'a> VM {
......@@ -56,7 +60,9 @@ impl <'a> VM {
func_sigs: RwLock::new(HashMap::new()),
func_vers: RwLock::new(HashMap::new()),
funcs: RwLock::new(HashMap::new()),
compiled_funcs: RwLock::new(HashMap::new())
compiled_funcs: RwLock::new(HashMap::new()),
threads: RwLock::new(vec!())
};
ret.is_running.store(false, Ordering::SeqCst);
......@@ -148,7 +154,7 @@ impl <'a> VM {
pub fn declare_func (&self, func: MuFunction) {
info!("declare function {}", func);
let mut funcs = self.funcs.write().unwrap();
funcs.insert(func.id(), RefCell::new(func));
funcs.insert(func.id(), RwLock::new(func));
}
pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
......@@ -157,17 +163,17 @@ impl <'a> VM {
let func_ver_key = (func_ver.func_id, func_ver.id());
{
let mut func_vers = self.func_vers.write().unwrap();
func_vers.insert(func_ver_key, RefCell::new(func_ver));
func_vers.insert(func_ver_key, RwLock::new(func_ver));
}
// acquire a reference to the func_ver
let func_vers = self.func_vers.read().unwrap();
let func_ver = func_vers.get(&func_ver_key).unwrap().borrow();
let func_ver = func_vers.get(&func_ver_key).unwrap().write().unwrap();
// change current version to this (obsolete old versions)
let funcs = self.funcs.read().unwrap();
debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
let mut func = funcs.get(&func_ver.func_id).unwrap().borrow_mut();
let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
func.new_version(func_ver.id());
......@@ -179,7 +185,7 @@ impl <'a> VM {
debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
debug_assert!(self.func_vers.read().unwrap().contains_key(&(func.func_id, func.func_ver_id)));
self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RefCell::new(func));
self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
}
pub fn get_backend_type_info(&self, tyid: MuID) -> P<BackendTypeInfo> {
......@@ -214,15 +220,15 @@ impl <'a> VM {
&self.globals
}
pub fn funcs(&self) -> &RwLock<HashMap<MuID, RefCell<MuFunction>>> {
pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
&self.funcs
}
pub fn func_vers(&self) -> &RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>> {
pub fn func_vers(&self) -> &RwLock<HashMap<(MuID, MuID), RwLock<MuFunctionVersion>>> {
&self.func_vers
}
pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RefCell<CompiledFunction>>> {
pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
&self.compiled_funcs
}
......@@ -235,6 +241,24 @@ impl <'a> VM {
}
pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
Box::new(MuStack::new(self.next_id(), func_id))
let funcs = self.funcs.read().unwrap();
let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
Box::new(MuStack::new(self.next_id(), func))
}
pub fn new_thread_normal(&self, stack: Box<MuStack>, threadlocal: Address, vals: Vec<RuntimeValue>) {
let user_tls = {
if threadlocal.is_zero() {
None
} else {
Some(threadlocal)
}
};
// set up arguments on stack
unimplemented!();
MuThread::launch(self.next_id(), stack, user_tls, vals, self);
}
}
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