less redundant code

parent edc0795b
Pipeline #3710 passed with stages
in 58 minutes and 9 seconds
......@@ -1989,160 +1989,6 @@ impl<'a> InstructionSelection {
}
}
/// This instruction is the same as NewThread, with one change:
/// - the `NEW_THREAD_NORMAL` entrypoint function for realtime threads (RTMu),
/// gets an additional `attr: RTAttr` argument
Instruction_::NewThreadRT {
attr,
stack,
thread_local,
is_exception,
ref args,
} => {
trace!("instsel on NEWTHREADRT");
let ref ops = inst.ops;
let res = self.get_result_value(node);
let attr = self.emit_ireg(&ops[attr], f_content, f_context, vm);
let stack = self.emit_ireg(&ops[stack], f_content, f_context, vm);
let tl = match thread_local {
Some(tl) => self.emit_ireg(&ops[tl], f_content, f_context, vm),
None => self.make_nullref(vm),
};
if is_exception {
let exc = self.emit_ireg(&ops[args[0]], f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::NEW_THREAD_EXCEPTIONAL,
vec![attr, stack, tl, exc],
Some(vec![res]),
Some(node),
f_content,
f_context,
vm,
);
} else {
let new_sp = self.make_temporary(f_context, ADDRESS_TYPE.clone(), vm);
self.emit_load_base_offset(
&new_sp,
&stack,
*thread::MUSTACK_SP_OFFSET as i32,
vm,
);
// prepare arguments on the new stack in the generated code
// check thread::MuStack::setup_args() for how we do it in the runtime
//
// 1. the stack arguments will be put to a reserved location during
// MuStack::new(), it is from (new_sp - 2*POINTER_SIZE) to
// (new_sp - 2*POINTER_SIZE - stack_arg_size)
// 2. the register arguments will be pushed to current SP, the start
// function will consume them.
{
use compiler::backend::x86_64::callconv::swapstack;
use compiler::backend::x86_64::callconv::CallConvResult;
use compiler::backend::x86_64::{ARGUMENT_FPRS, ARGUMENT_GPRS};
let arg_values =
self.process_arguments(&args, ops, f_content, f_context, vm);
// compute call convention
let arg_tys = arg_values.iter().map(|x| x.ty.clone()).collect();
let callconv = swapstack::compute_arguments(&arg_tys);
let mut gpr_args = vec![];
let mut fpr_args = vec![];
let mut stack_args = vec![];
for i in 0..callconv.len() {
let ref arg = arg_values[i];
let ref cc = callconv[i];
match cc {
&CallConvResult::GPR(_) => gpr_args.push(arg.clone()),
&CallConvResult::GPREX(_, _) => {
let (arg_l, arg_h) =
self.split_int128(arg, f_context, vm);
gpr_args.push(arg_l);
gpr_args.push(arg_h);
}
&CallConvResult::FPR(_) => fpr_args.push(arg.clone()),
&CallConvResult::STACK => stack_args.push(arg.clone()),
}
}
// for arguments that are not used, we push a 0
let zero = self.make_int64_const(0, vm);
let mut word_pushed = 0;
for i in 0..ARGUMENT_FPRS.len() {
let val = {
if i < fpr_args.len() {
&fpr_args[i]
} else {
&zero
}
};
word_pushed += 1;
self.emit_store_base_offset(
&new_sp,
-(word_pushed * WORD_SIZE as i32),
val,
vm,
);
}
for i in 0..ARGUMENT_GPRS.len() {
let val = {
if i < gpr_args.len() {
&gpr_args[i]
} else {
&zero
}
};
word_pushed += 1;
self.emit_store_base_offset(
&new_sp,
-(word_pushed * WORD_SIZE as i32),
val,
vm,
);
}
if !stack_args.is_empty() {
// need to put stack arguments to the preserved space
self.emit_store_stack_values(
&stack_args,
Some((&new_sp, 2 * WORD_SIZE as i32)),
MU_CALL_CONVENTION,
vm,
);
}
// adjust sp - we have pushed all argument registers
// (some could be 0 though)
self.backend
.emit_sub_r_imm(&new_sp, word_pushed * WORD_SIZE as i32);
// store the sp back to MuStack
self.emit_store_base_offset(
&stack,
*thread::MUSTACK_SP_OFFSET as i32,
&new_sp,
vm,
);
// call runtime entry
self.emit_runtime_entry(
&entrypoints::NEW_THREAD_NORMAL,
vec![attr, stack, tl],
Some(vec![res.clone()]),
Some(node),
f_content,
f_context,
vm,
);
}
}
}
Instruction_::CurrentStack => {
trace!("instsel on CURRENT_STACK");
......
......@@ -44,7 +44,7 @@ impl RuntimeEntrypoint {
}
// decl: thread/mod.rs
#[cfg(not(feature = "realtime"))]
//#[cfg(not(feature = "realtime"))]
lazy_static! {
// impl: runtime_ARCH_OS.c
pub static ref GET_THREAD_LOCAL : RuntimeEntrypoint = RuntimeEntrypoint::new(
......@@ -86,41 +86,7 @@ lazy_static! {
// decl: thread/mod.rs
#[cfg(feature = "realtime")]
lazy_static! {
// impl: runtime_ARCH_OS.c
pub static ref GET_THREAD_LOCAL : RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_get_thread_local",
vec![],
vec![ADDRESS_TYPE.clone()]);
pub static ref SET_RETVAL : RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_set_retval",
vec![UINT32_TYPE.clone()],
vec![]);
pub static ref THREAD_EXIT : RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_thread_exit",
vec![ADDRESS_TYPE.clone()],
vec![]);
// impl: thread/mod.rs
pub static ref NEW_STACK: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_stack",
vec![ADDRESS_TYPE.clone(), ADDRESS_TYPE.clone()],
vec![STACKREF_TYPE.clone()]);
pub static ref KILL_STACK: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_kill_stack",
vec![STACKREF_TYPE.clone()],
vec![]);
pub static ref SAFECALL_KILL_STACK: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_safecall_kill_stack",
vec![STACKREF_TYPE.clone()],
vec![]);
pub static ref NEW_THREAD_NORMAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_thread_normal",
vec![REF_VOID_TYPE.clone(), STACKREF_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
pub static ref NEW_THREAD_EXCEPTIONAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_thread_exceptional",
vec![REF_VOID_TYPE.clone(), STACKREF_TYPE.clone(), REF_VOID_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
;
}
// impl/decl: gc/lib.rs
......
......@@ -31,6 +31,7 @@ use libc::c_void;
#[cfg(feature = "realtime")]
use runtime::thread::thread_rtmu::RTAttr;
use runtime::thread::MuThread;
/// a list of all entrypoints used by compiler to generate calls into runtime
/// (where generated code entries the runtime)
......@@ -300,7 +301,9 @@ pub extern "C" fn mu_main(
.as_ref()
.map(|name| resolve_symbol(Arc::new(name.clone())))
.unwrap_or(unsafe { Address::zero() });
thread::MuThread::new_thread_normal(stack, threadlocal, args, vm.clone());
let muthread = thread::MuThread::new_thread_normal(stack, threadlocal, args, vm.clone());
MuThread::notify_to_run(muthread);
loop {
let thread = vm.pop_join_handle();
......
......@@ -30,7 +30,7 @@ use std;
use std::fmt;
use std::option;
use std::ptr;
use std::sync::Arc;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
use std::thread::JoinHandle;
......@@ -337,6 +337,8 @@ pub struct MuThread {
pub rt_attr: Arc<RTAttr>,
#[cfg(feature = "realtime")]
pub sys_thread_id: MuThreadID,
#[cfg(feature = "realtime")]
pub runnable: Arc<(Mutex<bool>, Condvar)>,
}
unsafe impl Sync for MuThread {}
......@@ -407,6 +409,33 @@ pub fn check_result() -> c_int {
}
impl MuThread {
/// a `MuThread` member function which
/// causes the calling thread to wait on its own `runnable` condition variable.
/// (used to synchronise creating a thread, setting its attributes and running it)
pub fn wait_for_run(muthread: *const MuThread) {
#[cfg(feature = "realtime")]
{
let &(ref lock, ref cvar) = unsafe { &*(*muthread).runnable };
let mut ready = lock.lock().unwrap();
while !*ready {
ready = cvar.wait(ready).unwrap();
}
}
}
/// a `MuThread` member function which
/// signals the calling thread of a change in its own `runnable` condition variable.
/// (this function is used in conjunction with the `wait_for_run` function)
pub fn notify_to_run(muthread: *const MuThread) {
#[cfg(feature = "realtime")]
{
let &(ref lock, ref cvar) = unsafe { &*(*muthread).runnable };
let mut ready = lock.lock().unwrap();
*ready = true;
cvar.notify_one();
}
}
/// is current thread a Mu thread?
#[inline(always)]
pub fn has_current() -> bool {
......@@ -472,6 +501,8 @@ impl MuThread {
rt_attr: Arc::new(RTAttr::new()),
#[cfg(feature = "realtime")]
sys_thread_id: 0 as MuThreadID,
#[cfg(feature = "realtime")]
runnable: Arc::new((Mutex::new(false), Condvar::new())),
};
}
......@@ -481,12 +512,13 @@ impl MuThread {
threadlocal: Address,
vals: Vec<ValueLocation>,
vm: Arc<VM>,
) {
) -> *mut MuThread {
// set up arguments on stack
stack.setup_args(vals);
let (join_handle, _) =
let (join_handle, muthread) =
MuThread::mu_thread_launch(vm.next_id(), stack, threadlocal, None, vm.clone());
vm.push_join_handle(join_handle);
muthread
}
/// creates and launches a mu thread, returns a JoinHandle and address to its MuThread structure
......@@ -500,13 +532,8 @@ impl MuThread {
let new_sp = stack.sp;
// FIXME - not all threads need a mutator
let mut thread: Box<MuThread> = Box::new(MuThread::new(
id,
mm::new_mutator(),
stack,
user_tls,
vm,
));
let mut thread: Box<MuThread> =
Box::new(MuThread::new(id, mm::new_mutator(), stack, user_tls, vm));
{
// set mutator for each allocator
let mutator_ptr = &mut thread.allocator as *mut mm::Mutator;
......@@ -525,22 +552,12 @@ impl MuThread {
let muth_ptr = Box::into_raw(muthread);
#[cfg(feature = "realtime")]
unsafe {
unsafe {
(*muth_ptr).sys_thread_id = MuThread::muthread_self();
};
let muthread = unsafe { Box::from_raw(muth_ptr) };
// apply the initial rt attributes to the sys thread
// let res = sys_thread_apply_rtattr(muthread.sys_thread_id, attr.clone());
// FIXME check for failure
// assert_eq!(
// res, MU_SUCCESS,
// "Failed to apply new thread attributes with error #{}",
// res
// );
// trace!("Apply new thread attrs result #{}", res);
let muthread = Box::into_raw(muthread);
// set thread local
unsafe { set_thread_local(muthread) };
......@@ -550,6 +567,8 @@ impl MuThread {
debug!("new sp: 0x{:x}", new_sp);
debug!("sp_store: 0x{:x}", sp_threadlocal_loc);
MuThread::wait_for_run(muthread);
unsafe {
match exception {
Some(e) => muthread_start_exceptional(e, new_sp, sp_threadlocal_loc),
......@@ -618,6 +637,8 @@ impl MuThread {
rt_attr: Arc::new(RTAttr::new()),
#[cfg(feature = "realtime")]
sys_thread_id: MuThread::muthread_self(),
#[cfg(feature = "realtime")]
runnable: Arc::new((Mutex::new(false), Condvar::new())),
});
{
let mutator_ptr = &mut fake_mu_thread.allocator as *mut mm::Mutator;
......@@ -639,7 +660,7 @@ impl fmt::Display for MuThread {
"MuThread @{:?}: {}\n",
self as *const MuThread, self.hdr
)
.unwrap();
.unwrap();
write!(f, "- header @{:?}\n", &self.hdr as *const MuEntityHeader).unwrap();
// specific to RTMu thread attributes
#[cfg(feature = "realtime")]
......@@ -648,47 +669,47 @@ impl fmt::Display for MuThread {
"- priority @{:?}\n",
&self.rt_attr.priority as *const MuPriority
)
.unwrap();
.unwrap();
#[cfg(feature = "realtime")]
write!(
f,
"- affinity @{:?}\n",
&self.rt_attr.affinity as *const MuAffinityMask
)
.unwrap();
.unwrap();
#[cfg(feature = "realtime")]
write!(
f,
"- affinity size @{:?}\n",
&self.rt_attr.affinity_size as *const MuAffinitySize
)
.unwrap();
.unwrap();
write!(
f,
"- allocator @{:?}\n",
&self.allocator as *const mm::Mutator
)
.unwrap();
.unwrap();
write!(f, "- stack @{:?}\n", &self.stack as *const *mut MuStack).unwrap();
write!(
f,
"- native sp @{:?}: {}\n",
&self.native_sp_loc as *const Address, self.native_sp_loc
)
.unwrap();
.unwrap();
write!(
f,
"- user_tls @{:?}: {}\n",
&self.user_tls as *const Address, self.user_tls
)
.unwrap();
.unwrap();
write!(
f,
"- exc obj @{:?}: {}\n",
&self.exception_obj as *const Address, self.exception_obj
)
.unwrap();
.unwrap();
Ok(())
}
......@@ -725,3 +746,40 @@ pub unsafe extern "C" fn muentry_kill_stack(stack: *mut MuStack) {
// This new box will be destroyed upon returning
Box::from_raw(stack);
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_exceptional(
stack: *mut MuStack,
thread_local: Address,
exception: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
Some(exception),
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_normal(
stack: *mut MuStack,
thread_local: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
None,
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
......@@ -15,41 +15,3 @@
/// MU (non-real-time) specific threading stuff goes to this module
/// Currently it's empty
use super::*;
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_exceptional(
stack: *mut MuStack,
thread_local: Address,
exception: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
Some(exception),
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_normal(
stack: *mut MuStack,
thread_local: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
None,
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
......@@ -100,42 +100,55 @@ impl MuThread {
}
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_exceptional(
attr: *mut RTAttr,
stack: *mut MuStack,
thread_local: Address,
exception: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
Some(exception),
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_normal(
attr: *mut RTAttr,
stack: *mut MuStack,
thread_local: Address,
) -> *mut MuThread {
let vm = MuThread::current_mut().vm.clone();
let (join_handle, muthread) = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
None,
vm.clone(),
);
vm.push_join_handle(join_handle);
muthread
}
\ No newline at end of file
//// Creates a new thread
//#[no_mangle]
//pub unsafe extern "C" fn muentry_new_thread_exceptional(
// attr: *mut RTAttr,
// stack: *mut MuStack,
// thread_local: Address,
// exception: Address,
//) -> *mut MuThread {
// let vm = MuThread::current_mut().vm.clone();
// let (join_handle, muthread) = MuThread::mu_thread_launch(
// vm.next_id(),
// Box::from_raw(stack),
// thread_local,
// Some(exception),
// vm.clone(),
// );
//
// // Apply the client requested thread attributes
// MuThread::muthread_apply_rtattr(unsafe { (*muthread).sys_thread_id } , Arc::from_raw(attr));
//
// // Now the new thread is ready to run, so we notify its condition variable
// MuThread::notify_to_run(muthread);
//
// vm.push_join_handle(join_handle);
// muthread
//}
//
//// Creates a new thread
//#[no_mangle]
//pub unsafe extern "C" fn muentry_new_thread_normal(
// attr: *mut RTAttr,
// stack: *mut MuStack,
// thread_local: Address,
//) -> *mut MuThread {
// let vm = MuThread::current_mut().vm.clone();
// let (join_handle, muthread) = MuThread::mu_thread_launch(
// vm.next_id(),
// Box::from_raw(stack),
// thread_local,
// None,
// vm.clone(),
// );
//
// // Apply the client requested thread attributes
// MuThread::muthread_apply_rtattr(unsafe { (*muthread).sys_thread_id }, Arc::from_raw(attr));
//
// // Now the new thread is ready to run, so we notify its condition variable
// MuThread::notify_to_run(muthread);
//
// vm.push_join_handle(join_handle);
// muthread
//}
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