less redundant code, plus update ci.yml

parent 30c3dff9
Pipeline #3708 failed with stages
in 58 minutes and 42 seconds
......@@ -17,8 +17,9 @@ before_script:
build:
stage: build
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo clean
- time rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test -j6 --release --no-run --color=always
- rustc --version
- cargo clean
- time cargo test -j6 --release --no-run --color=always
artifacts:
paths:
- target/release/deps/libmu.so
......@@ -28,22 +29,22 @@ build:
test:cargo:api:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_api --release 2> /dev/null
- cargo test test_api --release 2> /dev/null
test:cargo:ir:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_ir --release 2> /dev/null
- cargo test test_ir --release 2> /dev/null
test:cargo:compiler:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_compiler --release 2> /dev/null
- cargo test test_compiler --release 2> /dev/null
test:cargo:runtime:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_runtime --release 2> /dev/null
- cargo test test_runtime --release 2> /dev/null
.build_muc: &build_muc |
if [ -d "tests/test_muc/mu-tool-compiler" ]; then rm -Rf tests/test_muc/mu-tool-compiler; fi
......
......@@ -243,8 +243,9 @@ 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
#[no_mangle]
#[cfg(not(feature = "realtime"))]
pub extern "C" fn mu_main(
edata: *const (),
dumped_vm: *mut Arc<VM>,
......@@ -313,81 +314,6 @@ pub extern "C" fn mu_main(
}
}
/// the main function for RTMu executable boot image, this function will be called from C
/// We lunch the primordial thread with the system's default thread attr
/// The client is responsible for using the MuThreadID to modify them.
#[no_mangle]
#[cfg(feature = "realtime")]
pub extern "C" fn mu_main(
edata: *const (),
dumped_vm: *mut Arc<VM>,
argc: c_int,
argv: *const *const c_char,
) {
VM::start_logging_env();
debug!("mu_main() started...");
// load and resume the VM
unsafe {
rodal::load_asm_bounds(
rodal::Address::from_ptr(dumped_vm),
rodal::Address::from_ptr(edata),
)
};
let vm = VM::resume_vm(dumped_vm);
// find the primordial function as an entry
let primordial = vm.primordial().read().unwrap();
if primordial.is_none() {
panic!("no primordial thread/stack/function. Client should provide an entry point");
} else {
let primordial = primordial.as_ref().unwrap();
// create mu stack
let stack = vm.new_stack(primordial.func_id);
// if the primordial named some const arguments, we use the const args
// otherwise we push 'argc' and 'argv' to new stack
let args: Vec<ValueLocation> = if primordial.has_const_args {
primordial
.args
.iter()
.map(|arg| ValueLocation::from_constant(arg.clone()))
.collect()
} else {
let mut args = vec![];
// 1st arg: argc
args.push(ValueLocation::from_constant(Constant::Int(argc as u64)));
// 2nd arg: argv
args.push(ValueLocation::from_constant(Constant::Int(argv as u64)));
args
};
let threadlocal = vm
.primordial_threadlocal
.read()
.unwrap()
.as_ref()
.map(|name| resolve_symbol(Arc::new(name.clone())))
.unwrap_or(unsafe { Address::zero() });
let attr: RTAttr = RTAttr::new();
thread::MuThread::new_thread_normal(Arc::new(attr), stack, threadlocal, args, vm.clone());
loop {
let thread = vm.pop_join_handle();
if thread.is_none() {
break;
}
thread.unwrap().join().unwrap();
}
trace!("All threads have exited, quiting...");
}
}
/// runtime function to print a hex value (for PRINTHEX instruction for debugging use)
#[no_mangle]
pub extern "C" fn muentry_print_hex(x: u64) {
......
......@@ -452,6 +452,246 @@ impl MuThread {
Box::from_raw(mu_thread);
}
}
fn new(
id: MuID,
allocator: mm::Mutator,
stack: Box<MuStack>,
user_tls: Address,
vm: Arc<VM>,
) -> MuThread {
return MuThread {
hdr: MuEntityHeader::unnamed(id),
allocator,
stack: Box::into_raw(stack),
native_sp_loc: unsafe { Address::zero() },
user_tls,
vm,
exception_obj: unsafe { Address::zero() },
#[cfg(feature = "realtime")]
rt_attr: Arc::new(RTAttr::new()),
#[cfg(feature = "realtime")]
sys_thread_id: 0 as MuThreadID,
};
}
/// creates a new Mu thread with normal execution
pub fn new_thread_normal(
mut stack: Box<MuStack>,
threadlocal: Address,
vals: Vec<ValueLocation>,
vm: Arc<VM>,
) {
// set up arguments on stack
stack.setup_args(vals);
let (join_handle, _) =
MuThread::mu_thread_launch(vm.next_id(), stack, threadlocal, None, vm.clone());
vm.push_join_handle(join_handle);
}
/// creates and launches a mu thread, returns a JoinHandle and address to its MuThread structure
fn mu_thread_launch(
id: MuID,
stack: Box<MuStack>,
user_tls: Address,
exception: Option<Address>,
vm: Arc<VM>,
) -> (JoinHandle<()>, *mut 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,
));
{
// set mutator for each allocator
let mutator_ptr = &mut thread.allocator as *mut mm::Mutator;
thread.allocator.update_mutator_ptr(mutator_ptr);
}
// we need to return the pointer, but we cannot send it to other thread
let muthread_ptr = Box::into_raw(thread);
let muthread = unsafe { Box::from_raw(muthread_ptr) };
(
match thread::Builder::new()
.name(format!("Mu Thread #{}", id))
.spawn(move || {
// Save the sys thread ID before starting
let muth_ptr = Box::into_raw(muthread);
#[cfg(feature = "realtime")]
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) };
let addr = unsafe { muentry_get_thread_local() };
let sp_threadlocal_loc = addr + *NATIVE_SP_LOC_OFFSET;
debug!("new sp: 0x{:x}", new_sp);
debug!("sp_store: 0x{:x}", sp_threadlocal_loc);
unsafe {
match exception {
Some(e) => muthread_start_exceptional(e, new_sp, sp_threadlocal_loc),
None => muthread_start_normal(new_sp, sp_threadlocal_loc),
}
// Thread finished, delete it's data
Box::from_raw(muthread);
}
}) {
Ok(handle) => handle,
Err(_) => panic!("failed to create a thread"),
},
muthread_ptr,
)
}
/// disguises current thread as a Mu thread (setup MuThread metadata, thread local for it),
/// returns true if we have created a MuThread on this call, false means we had MuThread
/// for current thread before.
pub unsafe fn current_thread_as_mu_thread(threadlocal: Address, vm: Arc<VM>) -> bool {
use std::usize;
// 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;
}
// fake a stack for current thread
let fake_mu_stack_for_cur = Box::new(MuStack {
hdr: MuEntityHeader::unnamed(vm.next_id()),
// active state
state: MuStackState::Active,
// we do not know anything about current stack
// treat it as max size
size: usize::MAX,
overflow_guard: Address::zero(),
lower_bound: Address::zero(),
upper_bound: Address::max(),
underflow_guard: Address::max(),
// these will only be used when stack is not active (we still save to these fields)
// their values do not matter now
sp: Address::zero(),
bp: Address::zero(),
ip: Address::zero(),
// we are not responsible for keeping the memory alive
mmap: None,
});
// fake a thread for current thread
let mut fake_mu_thread = Box::new(MuThread {
hdr: MuEntityHeader::unnamed(vm.next_id()),
// we need a valid allocator and stack
allocator: mm::new_mutator(),
stack: Box::into_raw(fake_mu_stack_for_cur),
// we do not need native_sp_loc (we do not expect the thread to call THREADEXIT)
native_sp_loc: Address::zero(),
// valid thread local from user
user_tls: threadlocal,
vm,
exception_obj: Address::zero(),
#[cfg(feature = "realtime")]
rt_attr: Arc::new(RTAttr::new()),
#[cfg(feature = "realtime")]
sys_thread_id: MuThread::muthread_self(),
});
{
let mutator_ptr = &mut fake_mu_thread.allocator as *mut mm::Mutator;
fake_mu_thread.allocator.update_mutator_ptr(mutator_ptr);
}
// set thread local
let ptr_fake_mu_thread: *mut MuThread = Box::into_raw(fake_mu_thread);
set_thread_local(ptr_fake_mu_thread);
true
}
}
impl fmt::Display for MuThread {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"MuThread @{:?}: {}\n",
self as *const MuThread, self.hdr
)
.unwrap();
write!(f, "- header @{:?}\n", &self.hdr as *const MuEntityHeader).unwrap();
// specific to RTMu thread attributes
#[cfg(feature = "realtime")]
write!(
f,
"- priority @{:?}\n",
&self.rt_attr.priority as *const MuPriority
)
.unwrap();
#[cfg(feature = "realtime")]
write!(
f,
"- affinity @{:?}\n",
&self.rt_attr.affinity as *const MuAffinityMask
)
.unwrap();
#[cfg(feature = "realtime")]
write!(
f,
"- affinity size @{:?}\n",
&self.rt_attr.affinity_size as *const MuAffinitySize
)
.unwrap();
write!(
f,
"- allocator @{:?}\n",
&self.allocator as *const mm::Mutator
)
.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();
write!(
f,
"- user_tls @{:?}: {}\n",
&self.user_tls as *const Address, self.user_tls
)
.unwrap();
write!(
f,
"- exc obj @{:?}: {}\n",
&self.exception_obj as *const Address, self.exception_obj
)
.unwrap();
Ok(())
}
}
/// PrimordialThreadInfo stores information about primordial thread/entry function for a boot image
......
......@@ -16,151 +16,6 @@
/// Currently it's empty
use super::*;
impl MuThread {
/// creates a new Mu thread with normal execution
pub fn new_thread_normal(
mut stack: Box<MuStack>,
threadlocal: Address,
vals: Vec<ValueLocation>,
vm: Arc<VM>,
) {
// set up arguments on stack
stack.setup_args(vals);
let (join_handle, _) =
MuThread::mu_thread_launch(vm.next_id(), stack, threadlocal, None, vm.clone());
vm.push_join_handle(join_handle);
}
/// creates and launches a mu thread, returns a JoinHandle and address to its MuThread structure
fn mu_thread_launch(
id: MuID,
stack: Box<MuStack>,
user_tls: Address,
exception: Option<Address>,
vm: Arc<VM>,
) -> (JoinHandle<()>, *mut MuThread) {
let new_sp = stack.sp;
let mut thread = 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;
thread.allocator.update_mutator_ptr(mutator_ptr);
}
// we need to return the pointer, but we cannot send it to other thread
let muthread_ptr = Box::into_raw(thread);
let muthread = unsafe { Box::from_raw(muthread_ptr) };
(
match thread::Builder::new()
.name(format!("Mu Thread #{}", id))
.spawn(move || {
let muthread = Box::into_raw(muthread);
// set thread local
unsafe { set_thread_local(muthread) };
let addr = unsafe { muentry_get_thread_local() };
let sp_threadlocal_loc = addr + *NATIVE_SP_LOC_OFFSET;
debug!("new sp: 0x{:x}", new_sp);
debug!("sp_store: 0x{:x}", sp_threadlocal_loc);
unsafe {
match exception {
Some(e) => muthread_start_exceptional(e, new_sp, sp_threadlocal_loc),
None => muthread_start_normal(new_sp, sp_threadlocal_loc),
}
// Thread finished, delete it's data
Box::from_raw(muthread);
}
}) {
Ok(handle) => handle,
Err(_) => panic!("failed to create a thread"),
},
muthread_ptr,
)
}
/// creates metadata for a Mu thread
fn new(
id: MuID,
allocator: mm::Mutator,
stack: Box<MuStack>,
user_tls: Address,
vm: Arc<VM>,
) -> MuThread {
MuThread {
hdr: MuEntityHeader::unnamed(id),
allocator,
stack: Box::into_raw(stack),
native_sp_loc: unsafe { Address::zero() },
user_tls,
vm,
exception_obj: unsafe { Address::zero() },
}
}
/// disguises current thread as a Mu thread (setup MuThread metadata, thread local for it),
/// returns true if we have created a MuThread on this call, false means we had MuThread
/// for current thread before.
pub unsafe fn current_thread_as_mu_thread(threadlocal: Address, vm: Arc<VM>) -> bool {
use std::usize;
// 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;
}
// fake a stack for current thread
let fake_mu_stack_for_cur = Box::new(MuStack {
hdr: MuEntityHeader::unnamed(vm.next_id()),
// active state
state: MuStackState::Active,
// we do not know anything about current stack
// treat it as max size
size: usize::MAX,
overflow_guard: Address::zero(),
lower_bound: Address::zero(),
upper_bound: Address::max(),
underflow_guard: Address::max(),
// these will only be used when stack is not active (we still save to these fields)
// their values do not matter now
sp: Address::zero(),
bp: Address::zero(),
ip: Address::zero(),
// we are not responsible for keeping the memory alive
mmap: None,
});
// fake a thread for current thread
let mut fake_mu_thread = Box::new(MuThread {
hdr: MuEntityHeader::unnamed(vm.next_id()),
// we need a valid allocator and stack
allocator: mm::new_mutator(),
stack: Box::into_raw(fake_mu_stack_for_cur),
// we do not need native_sp_loc (we do not expect the thread to call THREADEXIT)
native_sp_loc: Address::zero(),
// valid thread local from user
user_tls: threadlocal,
vm,
exception_obj: Address::zero(),
});
{
let mutator_ptr = &mut fake_mu_thread.allocator as *mut mm::Mutator;
fake_mu_thread.allocator.update_mutator_ptr(mutator_ptr);
}
// set thread local
let ptr_fake_mu_thread: *mut MuThread = Box::into_raw(fake_mu_thread);
set_thread_local(ptr_fake_mu_thread);
true
}
}
// Creates a new thread
#[no_mangle]
pub unsafe extern "C" fn muentry_new_thread_exceptional(
......@@ -198,41 +53,3 @@ pub unsafe extern "C" fn muentry_new_thread_normal(
muthread
}
impl fmt::Display for MuThread {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"MuThread @{:?}: {}\n",
self as *const MuThread, self.hdr
)
.unwrap();
write!(f, "- header @{:?}\n", &self.hdr as *const MuEntityHeader).unwrap();
write!(
f,
"- allocator @{:?}\n",
&self.allocator as *const mm::Mutator
)
.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();
write!(
f,
"- user_tls @{:?}: {}\n",
&self.user_tls as *const Address, self.user_tls
)
.unwrap();
write!(
f,
"- exc obj @{:?}: {}\n",
&self.exception_obj as *const Address, self.exception_obj
)
.unwrap();
Ok(())
}
}
This diff is collapsed.
......@@ -31,28 +31,6 @@ pub const MU_SCHED_FIFO: MuSchedPolicy = libc::SCHED_FIFO;
pub const MU_DEFAULT_PRIORITY: MuPriority = 50;
pub const MU_DEFAULT_AFF_SIZE: MuAffinitySize = libc::CPU_SETSIZE as MuAffinitySize;
//pub fn sys_thread_attr_init(attr: *mut RTMuThreadAttr) -> RTMuResult {
// unsafe { libc::pthread_attr_init(attr) }
//}
//
//pub fn sys_thread_attr_set_affinity(
// attr: *mut RTMuThreadAttr,
// mask_size: RTMuAffinitySize,
// mask: *const RTMuAffinityMask,
//) -> RTMuResult {
// unsafe { libc::pthread_attr_setaffinity_np(attr, mask_size, mask) }
//}
//
//pub fn sys_thread_attr_set_priority(
// attr: *mut RTMuThreadAttr,
// priority: RTMuPriority,
//) -> RTMuResult {
// let sch_param = libc::sched_param {
// sched_priority: priority,
// };
// unsafe { libc::pthread_attr_setschedparam(&attr, &sch_param as *const libc::sched_param) }
//}
pub fn sys_thread_apply_rtattr(native: MuThreadID, attr: Arc<RTAttr>) -> MuResult {
let sch_param = libc::sched_param {
sched_priority: attr.priority,
......
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