benchmark runs, needs debugging memory allocation

parent 031c6307
......@@ -91,6 +91,13 @@ impl Instruction {
| DeleteFutex(_)
| LockFutex(_,_)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
......@@ -206,6 +213,13 @@ impl Instruction {
| DeleteFutex(_)
| LockFutex(_,_)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| NotifyThread(_)
| ThreadSetPriority(_, _)
| ThreadClearCPU(_, _)
......@@ -334,6 +348,13 @@ impl Instruction {
| DeleteFutex(_)
| LockFutex(_, _)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| NotifyThread(_)
| ThreadSetPriority(_, _)
| ThreadGetPriority(_)
......@@ -458,6 +479,13 @@ impl Instruction {
| DeleteFutex(_)
| LockFutex(_,_)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| NotifyThread(_)
| ThreadSetPriority(_,_) // FIXME - Not sure about these
| ThreadGetPriority(_)
......@@ -574,6 +602,13 @@ impl Instruction {
| DeleteFutex(_)
| LockFutex(_,_)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| NotifyThread(_) |
ThreadSetPriority(_,_) |
NewFrameCursor(_) |
......@@ -816,6 +851,28 @@ impl Instruction {
format!("UNLOCKFUTEX {}, {}", ops[futexref], ops[count])
}
&Instruction_::CondVarNew => {
format!("CONDVAR_NEW")
}
&Instruction_::CondVarDelete(addr) => {
format!("CONDVAR_DELETE {}", ops[addr])
}
&Instruction_::CondVarAcqLock(addr) => {
format!("CONDVAR_ACQ_LOCK {}", ops[addr])
}
&Instruction_::CondVarRelLock(addr) => {
format!("CONDVAR_REL_LOCK {}", ops[addr])
}
&Instruction_::CondVarWait(addr) => {
format!("CONDVAR_WAIT {}", ops[addr])
}
&Instruction_::CondVarSignal(addr) => {
format!("CONDVAR_SIGNAL {}", ops[addr])
}
&Instruction_::CondVarBroadcast(addr) => {
format!("CONDVAR_BROADCAST {}", ops[addr])
}
&Instruction_::NewRTThread {
attr,
stack,
......@@ -1447,6 +1504,14 @@ pub enum Instruction_ {
LockFutex(OpIndex, OpIndex),
UnlockFutex(OpIndex, OpIndex),
CondVarNew,
CondVarDelete(OpIndex),
CondVarAcqLock(OpIndex),
CondVarRelLock(OpIndex),
CondVarWait(OpIndex),
CondVarSignal(OpIndex),
CondVarBroadcast(OpIndex),
// #[cfg(feature = "realtime")]
/// notify a thread to start running
/// args: threadref for the target thread
......
......@@ -24,6 +24,7 @@ use std::fmt;
use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::RwLock;
use std::intrinsics::write_bytes;
// some common types that the compiler may use internally
//#[cfg(not(feature = "realtime"))]
......@@ -72,6 +73,8 @@ lazy_static! {
P(MuType::new(new_internal_id(), MuType_::threadref()));
pub static ref FUTEXREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::futexref()));
pub static ref CONDVARREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::condvarref()));
}
#[cfg(not(feature = "realtime"))]
......@@ -93,6 +96,7 @@ lazy_static! {
STACKREF_TYPE.clone(),
THREADREF_TYPE.clone(),
FUTEXREF_TYPE.clone(),
CONDVARREF_TYPE.clone(),
UPTR_U8_TYPE.clone(),
UPTR_U64_TYPE.clone()
];
......@@ -124,6 +128,7 @@ lazy_static! {
IREF_VOID_TYPE.clone(),
STACKREF_TYPE.clone(),
THREADREF_TYPE.clone(),
CONDVARREF_TYPE.clone(),
UPTR_U8_TYPE.clone(),
UPTR_U64_TYPE.clone(),
ATTRREF_TYPE.clone(),
......@@ -284,7 +289,8 @@ impl MuType {
MuType_::FuncRef(_)
| MuType_::StackRef
| MuType_::ThreadRef
| MuType_::FutexRef => true,
| MuType_::FutexRef
| MuType_::CondVarRef => true,
#[cfg(feature = "realtime")]
MuType_::RegionRef => true,
......@@ -336,6 +342,7 @@ impl MuType {
| MuType_::StackRef
| MuType_::Tagref64
| MuType_::FutexRef
| MuType_::CondVarRef
| MuType_::UPtr(_) => true,
#[cfg(feature = "realtime")]
MuType_::AttrRef
......@@ -567,7 +574,7 @@ impl MuType {
match self.v {
Int(len) => Some(len),
Ref(_) | IRef(_) | WeakRef(_) | UPtr(_) | ThreadRef | StackRef
| FutexRef | Tagref64 | FuncRef(_) | UFuncPtr(_) => Some(64),
| FutexRef | CondVarRef | Tagref64 | FuncRef(_) | UFuncPtr(_) => Some(64),
#[cfg(feature = "realtime")]
RegionRef => Some(64),
......@@ -698,6 +705,7 @@ pub enum MuType_ {
/// ufuncptr<@sig>
UFuncPtr(P<MuFuncSig>),
FutexRef,
CondVarRef,
/// RTMu-specific
/// Real-Time Threads' attributes
......@@ -722,12 +730,12 @@ impl MuType_ {
#[cfg(not(feature = "realtime"))]
rodal_enum!(MuType_{(Int: size), Float, Double, (Ref: ty), (IRef: ty), (WeakRef: ty), (UPtr: ty),
(Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, StackRef, FutexRef, Tagref64,
(Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, StackRef, FutexRef, CondVarRef, Tagref64,
(Vector: ty, size), (FuncRef: ty), (UFuncPtr: ty)});
#[cfg(feature = "realtime")]
rodal_enum!(MuType_{(Int: size), Float, Double, (Ref: ty), (IRef: ty), (WeakRef: ty), (UPtr: ty),
(Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, RegionRef, TimerRef, FutexRef, TimeVal, AttrRef, StackRef, Tagref64,
(Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, RegionRef, TimerRef, FutexRef, CondVarRef, TimeVal, AttrRef, StackRef, Tagref64,
(Vector: ty, size), (FuncRef: ty), (UFuncPtr: ty)});
impl fmt::Display for MuType {
......@@ -752,6 +760,7 @@ impl fmt::Display for MuType_ {
&MuType_::Void => write!(f, "void"),
&MuType_::ThreadRef => write!(f, "threadref"),
&MuType_::FutexRef => write!(f, "futexref"),
&MuType_::CondVarRef => write!(f, "condvarref"),
#[cfg(feature = "realtime")]
&MuType_::AttrRef => write!(f, "attrref"),
......@@ -937,6 +946,9 @@ impl MuType_ {
pub fn futexref() -> MuType_ {
MuType_::FutexRef
}
pub fn condvarref() -> MuType_ {
MuType_::CondVarRef
}
#[cfg(feature = "realtime")]
pub fn attrref() -> MuType_ {
......
......@@ -2787,6 +2787,27 @@ impl<'a> InstructionSelection {
}
}
}
// FIXME. to finish it faster, I'm using rust atomic ops, may need fix
Instruction_::CmpXchg {
is_weak,
success_order,
fail_order,
mem_loc,
expected_value,
desired_value,
..
} => {
let res = self.get_result_value(node);
let resty = &res.ty.v;
match resty {
MuType_::Int(64) => {
;
}
_ => {
unimplemented!("Atomic compare and exchange for type: {}", resty);
}
}
}
#[cfg(feature = "realtime")]
Instruction_::NewRTThread {
......@@ -2966,6 +2987,129 @@ impl<'a> InstructionSelection {
);
}
Instruction_::CondVarNew => {
trace!("instsel on CondVarNew");
let res = self.get_result_value(node);
self.emit_runtime_entry(
&entrypoints::CONDVAR_NEW,
vec![],
Some(vec![res]),
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarDelete(condref) => {
trace!("instsel on CondVarDelete");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_DELETE,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarAcqLock(condref) => {
trace!("instsel on CondVarAcqLock");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_ACQ_LOCK,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarRelLock(condref) => {
trace!("instsel on CondVarRelLock");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_REL_LOCK,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarWait(condref) => {
trace!("instsel on CondVarWait");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_WAIT,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarSignal(condref) => {
trace!("instsel on CondVarSignal");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_SIGNAL,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CondVarBroadcast(condref) => {
trace!("instsel on CondVarBroadcast");
let ref ops = inst.ops;
let ref condref = ops[condref];
let tmp_condref =
self.emit_ireg(condref, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::CONDVAR_BROADCAST,
vec![tmp_condref],
None,
Some(node),
f_content,
f_context,
vm
);
}
#[cfg(feature = "realtime")]
Instruction_::ThreadGetPriority(thread) => {
trace!("instsel on ThreadGetPriority");
......
......@@ -717,6 +717,13 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
| NewThread { .. }
| NewRTThread { .. }
| NewFutex(_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| DeleteFutex(_)
| LockFutex(_, _)
| UnlockFutex(_,_)
......
......@@ -270,7 +270,7 @@ impl BackendType {
TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1)
}
MuType_::FutexRef => TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1),
MuType_::CondVarRef | MuType_::FutexRef => TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1),
// RTMu-specific
#[cfg(feature = "realtime")]
MuType_::RegionRef | MuType_::TimerRef => {
......@@ -398,6 +398,7 @@ impl BackendType {
| MuType_::FuncRef(_)
| MuType_::ThreadRef
| MuType_::FutexRef
| MuType_::CondVarRef
| MuType_::StackRef => {
debug_assert!(pointer_aligned);
res.push(WordType::NonRef);
......@@ -536,6 +537,7 @@ impl BackendType {
| MuType_::FuncRef(_)
| MuType_::ThreadRef
| MuType_::FutexRef
| MuType_::CondVarRef
| MuType_::StackRef => BackendType {
ty: ty.clone(),
size: 8,
......@@ -646,7 +648,7 @@ impl BackendType {
// struct
MuType_::Struct(ref name) => {
trace!("BackendType::resolve::struct({})", name);
trace!("STRUCT_TAG_MAP: {:#?}", STRUCT_TAG_MAP);
// trace!("STRUCT_TAG_MAP: {:#?}", STRUCT_TAG_MAP);
let read_lock = STRUCT_TAG_MAP.read().unwrap();
trace!("1");
let struc = read_lock.get(name).unwrap();
......@@ -984,6 +986,7 @@ impl RegGroup {
| MuType_::Tagref64
| MuType_::FuncRef(_)
| MuType_::FutexRef
| MuType_::CondVarRef
| MuType_::UFuncPtr(_) => RegGroup::GPR,
#[cfg(feature = "realtime")]
......
......@@ -95,6 +95,13 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| DeleteFutex(_)
| LockFutex(_, _)
| UnlockFutex(_,_)
| CondVarNew
| CondVarDelete(_)
| CondVarAcqLock(_)
| CondVarRelLock(_)
| CondVarWait(_)
| CondVarSignal(_)
| CondVarBroadcast(_)
| NotifyThread(_)
| ThreadSetPriority(_, _)
| ThreadGetPriority(_)
......
......@@ -27,7 +27,7 @@ pub mod immix;
pub const IMMIX_SPACE_RATIO: f64 = 1.0 - LO_SPACE_RATIO;
pub const LO_SPACE_RATIO: f64 = 0.2;
pub const DEFAULT_HEAP_SIZE: usize = 500 << 20;
pub const DEFAULT_HEAP_SIZE: usize = 15000 << 20;
// preallocating 16 GB for space
pub const LOG_BYTES_PREALLOC_SPACE: usize = 34;
......
......@@ -156,6 +156,7 @@ fn link_executable_internal(
let mut cc = Command::new(get_c_compiler());
cc.arg("-latomic");
// external libs
for path in libpath.iter() {
cc.arg(format!("-L{}", path));
......
......@@ -329,6 +329,41 @@ lazy_static! {
vec![ADDRESS_TYPE.clone()], // (attrref)
vec![] // returns nothing
);
pub static ref CONDVAR_NEW: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_new",
vec![], // ()
vec![ADDRESS_TYPE.clone()] // returns convar address
);
pub static ref CONDVAR_DELETE: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_delete",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
pub static ref CONDVAR_ACQ_LOCK: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_acq_lock",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
pub static ref CONDVAR_REL_LOCK: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_rel_lock",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
pub static ref CONDVAR_WAIT: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_wait",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
pub static ref CONDVAR_SIGNAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_signal",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
pub static ref CONDVAR_BROADCAST: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_condvar_broadcast",
vec![ADDRESS_TYPE.clone()], // (cv's address)
vec![] // returns nothing
);
}
// impl/decl: gc/lib.rs
......
use super::*;
#[cfg(target_os = "linux")]
use super::condvar_rtmu_linux::*;
type CondVar = SysCondVar;
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_new() -> Address {
let res = Address::from_mut_ptr(CondVar::new());
trace!("muentry_condvar_new returning {}", res);
res
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_delete(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_delete of condvar:\n{}", cd);
cd.delete();
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_acq_lock(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_acq_lock of condvar:\n{}", cd);
cd.acq_lock();
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_rel_lock(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_rel_lock of condvar:\n{}", cd);
cd.rel_lock();
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_wait(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_wait of condvar:\n{}", cd);
cd.wait();
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_signal(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_signal of condvar:\n{}", cd);
cd.signal();
}
#[no_mangle]
pub unsafe extern "C" fn muentry_condvar_broadcast(cv_addr: Address) {
let cd: &mut CondVar = cv_addr.to_ref_mut();
trace!("muentry_condvar_broadcast of condvar:\n{}", cd);
cd.broadcast();
}
use std::fmt;
use libc;
use utils::Address;
pub(crate) struct SysCondVar {
pub mtx: *mut libc::pthread_mutex_t,
pub cv: *mut libc::pthread_cond_t,
pub mtx_locked: bool,
}
impl SysCondVar {
pub(crate) fn new() -> *mut SysCondVar {
let m: libc::pthread_mutex_t = unsafe { std::mem::zeroed() };
let c: libc::pthread_cond_t = unsafe { std::mem::zeroed() };
let res = Box::new(
SysCondVar {
mtx: Box::into_raw(Box::new(m)),
cv: Box::into_raw(Box::new(c)),
mtx_locked: false,
}
);
let err = unsafe {
libc::pthread_mutex_init(res.mtx, std::ptr::null())
};
assert_eq!(err, 0);
let err = unsafe {
libc::pthread_cond_init(res.cv, std::ptr::null())
};
assert_eq!(err, 0);
return Box::into_raw(res);
}
pub(crate) fn delete(&self) {
let boxed = unsafe { Box::from_raw(self.mtx) };
let boxed = unsafe { Box::from_raw(self.cv) };
let boxed = unsafe { Box::from_raw(self as *const SysCondVar as *mut SysCondVar) };
}
pub(crate) fn acq_lock(&mut self) {
let err = unsafe {
libc::pthread_mutex_lock(self.mtx)
};
self.mtx_locked = true;
assert_eq!(err, 0);
}
pub(crate) fn rel_lock(&mut self) {
let err = unsafe {
libc::pthread_mutex_unlock(self.mtx)
};
self.mtx_locked = false;
assert_eq!(err, 0);
}
pub(crate) fn wait(&self) {
// assert_eq!(self.mtx_locked, true);
let err = unsafe {
libc::pthread_cond_wait(self.cv, self.mtx)
};
assert_eq!(err, 0);
}
pub(crate) fn signal(&self) {
let err = unsafe {
libc::pthread_cond_signal(self.cv)
};
assert_eq!(err, 0);
}
pub(crate) fn broadcast(&self) {
let err = unsafe {
libc::pthread_cond_broadcast(self.cv)
};
assert_eq!(err, 0);
}
}
impl fmt::Display for SysCondVar {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "\nCondVar address: {} {{", Address::from_ref(&self)).unwrap();
writeln!(f, "\n\tMutex address: {}", Address::from_mut_ptr(self.mtx)).unwrap();
writeln!(f, "\n\tpthread cv address: {}", Address::from_mut_ptr(self.cv)).unwrap();
writeln!(f, "\n\tLocked?: {}", self.mtx_locked).unwrap();
writeln!(f, "}}\n")
}
}
......@@ -16,6 +16,7 @@
use std::sync::atomic::{AtomicU32, Ordering};
use super::*;
use runtime::thread::{SysResult, MU_SUCCESS};
// use super::futex_rtmu::*;
pub(super) type OsTidT = libc::pid_t;
......@@ -42,51 +43,51 @@ impl sys_rtmu_futex {
}
pub fn lock(&mut self, timeout_ns: u64) {
let my_tid = os_gettid();
match self.mem.compare_exchange(
0 as u32,
my_tid as u32,
Ordering::SeqCst,
Ordering::SeqCst
) {
Ok(_) => {
trace!("FUTEX.lock fastpath success");
}
Err(id) => {
trace!(
"FUTEX.lock fastpath failed: #{:#?} already locked it",
id
);
sys_futex_lock_slowpath(
&mut self.mem as *const AtomicU32 as *const u32 as *mut u32,
timeout_ns
);
}
}
let res = sys_futex_lock_slowpath(
&mut self.mem as *const AtomicU32 as *const u32 as *mut u32,
timeout_ns,
);
// let mut res: SysResult = -1;
//
// while res == -1 {
// if self.mem.fetch_add(1, Ordering::SeqCst) == 0 {
// trace!("FUTEX.lock({}) fastpath success",
// Address::from_mut_ptr(self as *const sys_rtmu_futex as *mut sys_rtmu_futex));
// break;
// } else {
// let fval = self.mem.load(Ordering::SeqCst);
// trace!(
// "FUTEX.lock({}) fastpath failed (res={}), \ncurrent fval: #{}\nerror#{}",
// Address::from_mut_ptr(self as *const sys_rtmu_futex as *mut sys_rtmu_futex),
// res, fval, unsafe { (*libc::__errno_location()) }
// );
// res = sys_futex_lock_slowpath(
// &mut self.mem as *const AtomicU32 as *const u32 as *mut u32,
// timeout_ns,
// );
// }
// }