Implemented and tested: RTAttr, NewRTThread, Get/SetPriority.

Plus fixing rust source code warnings
parent e226933e
Pipeline #3806 failed with stages
......@@ -84,7 +84,15 @@ impl Instruction {
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
| NotifyThread(_)
| NewRTThread { .. }
| NotifyThread(_) // TODO remove - not needed anymore
| SetPriority(_,_)
| GetPriority(_)
| AffinitySet(_,_)
| AffinityClear(_,_)
| AffinityEqual(_,_)
| AffinityIsset(_,_)
| AffinityZero(_)
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -143,7 +151,12 @@ impl Instruction {
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_, _)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityZero(_)
| NewFrameCursor(_)
| Fence(_)
| Return(_)
......@@ -191,7 +204,10 @@ impl Instruction {
| CommonInst_Tr64ToTag(_)
| Move(_)
| CurrentStack
| GetVMThreadLocal => false,
| GetVMThreadLocal
| GetPriority(_)
| AffinityIsset(_, _)
| AffinityEqual(_, _) => false,
}
}
......@@ -222,7 +238,15 @@ impl Instruction {
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_, _)
| GetPriority(_)
| AffinityZero(_)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityEqual(_, _)
| AffinityIsset(_, _)
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -296,7 +320,15 @@ impl Instruction {
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_,_) // FIXME - Not sure about these
| GetPriority(_)
| AffinityClear(_,_)
| AffinityEqual(_,_)
| AffinityIsset(_,_)
| AffinitySet(_,_)
| AffinityZero(_)
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -372,7 +404,9 @@ impl Instruction {
AllocAHybrid(_, _) |
NewStack(_) |
NewThread { .. } |
NewRTThread { .. } |
NotifyThread(_) |
SetPriority(_,_) |
NewFrameCursor(_) |
GetIRef(_) |
GetFieldIRef { .. } |
......@@ -544,13 +578,54 @@ impl Instruction {
.map(|t| format!(" THREADLOCAL({})", ops[t]))
.unwrap_or("".to_string());
format!(
"NEWSTACK {}{} {}",
"NEWTHREAD {}{} {}",
ops[stack], thread_local, new_stack_clause,
)
}
&Instruction_::NewRTThread {
attr,
stack,
thread_local,
is_exception,
ref args,
} => {
let new_stack_clause = format_new_stack_clause(is_exception, args, ops);
let thread_local = thread_local
.map(|t| format!(" THREADLOCAL({})", ops[t]))
.unwrap_or("".to_string());
format!(
"NEWRTTHREAD {}, {}, {}, {}",
ops[attr], ops[stack], thread_local, new_stack_clause,
)
}
&Instruction_::NotifyThread(thread) => {
format!("COMMINST @uvm.notifythread({})", ops[thread])
}
&Instruction_::SetPriority(thread, priority) => format!(
"COMMINST @uvm.setpriority({}, {})",
ops[thread], ops[priority]
),
&Instruction_::GetPriority(thread) => {
format!("COMMINST @uvm.getpriority({})", ops[thread])
}
&Instruction_::AffinityClear(thread, cpu) => {
format!("COMMINST @uvm.affinityclear({}, {})", ops[thread], ops[cpu])
}
&Instruction_::AffinitySet(thread, cpu) => {
format!("COMMINST @uvm.affinityset({}, {})", ops[thread], ops[cpu])
}
&Instruction_::AffinityEqual(thread1, thread2) => format!(
"COMMINST @uvm.affinityequal({}, {})",
ops[thread1], ops[thread2]
),
&Instruction_::AffinityIsset(thread, cpu) => {
format!("COMMINST @uvm.affinityisset({}, {})", ops[thread], ops[cpu])
}
&Instruction_::AffinityZero(thread) => {
format!("COMMINST @uvm.affinityzero({})", ops[thread])
}
&Instruction_::NewFrameCursor(stack) => {
format!("COMMINST @uvm.meta.new_cursor({})", ops[stack])
}
......@@ -868,10 +943,7 @@ pub enum Instruction_ {
/// a non-terminating CCall instruction (the call does not have an exceptional branch)
/// This instruction is not in the Mu spec, but is documented in the HOL formal spec
ExprCCall {
data: CallData,
is_abort: bool,
},
ExprCCall { data: CallData, is_abort: bool },
/// load instruction
Load {
......@@ -934,6 +1006,7 @@ pub enum Instruction_ {
/// create a new Mu thread, yields thread reference
/// args: stackref of a Mu stack, a list of arguments
// #[cfg(not(feature = "realtime"))]
NewThread {
stack: OpIndex,
thread_local: Option<OpIndex>,
......@@ -941,8 +1014,60 @@ pub enum Instruction_ {
args: Vec<OpIndex>,
},
/// create a new Mu thread, yields thread reference
/// args: stackref of a Mu stack, a list of arguments
// #[cfg(feature = "realtime")]
NewRTThread {
attr: OpIndex,
stack: OpIndex,
thread_local: Option<OpIndex>,
is_exception: bool,
args: Vec<OpIndex>,
},
// #[cfg(feature = "realtime")]
/// notify a thread to start running
/// args: threadref for the target thread
NotifyThread(OpIndex),
/// set the priority of a target thread
/// args:
/// - threadref for the target thread
/// - the new priority value (int64)
SetPriority(OpIndex, OpIndex),
/// get the current priority of a target thread
/// args:
/// - threadref for the target thread
/// returns:
/// - an int64 representing the current priority value
GetPriority(OpIndex),
/// clear the cpu set of a thread, so that it contains not CPUs
/// args:
/// - threadref for the target thread
AffinityZero(OpIndex),
/// add a cpu to the cpu set of a thread
/// args:
/// - threadref of the target thread
/// - number of the cpu to add (e.g. #0 is the 1st cpu)
AffinitySet(OpIndex, OpIndex),
/// remove a cpu from the cpu set of a thread
/// args:
/// - threadref of the target thread
/// - number of the cpu to remove (e.g. #0 is the 1st cpu)
AffinityClear(OpIndex, OpIndex),
/// check whether a cpu is a member of the cpu set of a thread
/// args:
/// - threadref of the target thread
/// - number of the cpu to check (e.g. #0 is the 1st cpu)
AffinityIsset(OpIndex, OpIndex),
/// check whether two cpu sets contain exactly the same CPUs
/// args:
/// - threadref of the thread #1
/// - threadref of the thread #2
AffinityEqual(OpIndex, OpIndex),
/// create a frame cursor reference
/// args: stackref of a Mu stack
......@@ -974,10 +1099,7 @@ pub enum Instruction_ {
},
/// get internal reference to an element in hybrid var part
GetVarPartIRef {
is_ptr: bool,
base: OpIndex,
},
GetVarPartIRef { is_ptr: bool, base: OpIndex },
/// a fence of certain memory order
Fence(MemoryOrder),
......
......@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[cfg(feature = "realtime")]
pub use ir_rt::*;
use inst::*;
use ptr::P;
use types::*;
......
......@@ -11,13 +11,3 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[cfg(target_os = "linux")]
pub use ir_rt_linux::*;
pub type MuThreadID = SysThreadID;
pub type MuThreadAttr = SysThreadAttr;
pub type MuPriority = SysPriority;
pub type MuTime = SysTime;
pub type MuAffinityMask = SysAffinityMask;
pub type MuAffinitySize = SysAffinitySize;
......@@ -11,12 +11,3 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate libc;
pub type SysThreadID = libc::pthread_t;
pub type SysThreadAttr = libc::pthread_attr_t;
pub type SysPriority = libc::c_int;
pub type SysTime = libc::timespec;
pub type SysAffinityMask = libc::cpu_set_t;
pub type SysAffinitySize = libc::size_t;
......@@ -83,4 +83,4 @@ pub mod types;
pub mod ir_rt;
#[cfg(all(feature = "realtime", target_os = "linux"))]
pub mod ir_rt_linux;
pub mod ir_rt_posix;
......@@ -26,7 +26,7 @@ use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::RwLock;
// some common types that the compiler may use internally
#[cfg(not(feature = "realtime"))]
//#[cfg(not(feature = "realtime"))]
lazy_static! {
pub static ref ADDRESS_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
......@@ -57,9 +57,14 @@ lazy_static! {
new_internal_id(),
MuType_::uptr(UINT64_TYPE.clone())
));
pub static ref STACKREF_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::StackRef));
pub static ref STACKREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::stackref()));
pub static ref THREADREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::ThreadRef));
P(MuType::new(new_internal_id(), MuType_::threadref()));
}
#[cfg(not(feature = "realtime"))]
lazy_static! {
pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT1_TYPE.clone(),
......@@ -83,39 +88,11 @@ lazy_static! {
#[cfg(feature = "realtime")]
lazy_static! {
pub static ref ADDRESS_TYPE: P<MuType> = P(MuType::new(
pub static ref RTATTR_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::rtattr()));
pub static ref UPTR_RTATTR_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::int(POINTER_SIZE * 8)
MuType_::uptr(RTATTR_TYPE.clone())
));
pub static ref UINT1_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(1)));
pub static ref UINT8_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(8)));
pub static ref UINT16_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(16)));
pub static ref UINT32_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(32)));
pub static ref UINT64_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(64)));
pub static ref UINT128_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(128)));
pub static ref FLOAT_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::float()));
pub static ref DOUBLE_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::double()));
pub static ref VOID_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::void()));
pub static ref REF_VOID_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::muref(VOID_TYPE.clone())
));
pub static ref IREF_VOID_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::iref(VOID_TYPE.clone())
));
pub static ref UPTR_U8_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::uptr(UINT8_TYPE.clone())
));
pub static ref UPTR_U64_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::uptr(UINT64_TYPE.clone())
));
pub static ref RTATTR_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::RTAttr));
pub static ref STACKREF_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::StackRef));
pub static ref THREADREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::ThreadRef));
pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT1_TYPE.clone(),
......@@ -134,7 +111,8 @@ lazy_static! {
THREADREF_TYPE.clone(),
UPTR_U8_TYPE.clone(),
UPTR_U64_TYPE.clone(),
RTATTR_TYPE.clone()
RTATTR_TYPE.clone(),
UPTR_RTATTR_TYPE.clone()
];
}
......
......@@ -685,7 +685,18 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
// runtime call
New(_) | NewHybrid(_, _) => 10,
NewStack(_) | NewThread { .. } | NotifyThread(_) | NewFrameCursor(_) => 10,
NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_, _)
| GetPriority(_)
| AffinityEqual(_, _)
| AffinityZero(_)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityIsset(_, _)
| NewFrameCursor(_) => 10,
ThreadExit => 10,
CurrentStack => 10,
KillStack(_) => 10,
......
......@@ -79,7 +79,15 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_, _)
| GetPriority(_)
| AffinityIsset(_, _)
| AffinitySet(_, _)
| AffinityClear(_, _)
| AffinityZero(_)
| AffinityEqual(_, _)
| NewFrameCursor(_)
| Select { .. }
| Fence(_)
......
......@@ -13,7 +13,6 @@
// limitations under the License.
use heap::*;
use utils::*;
mod immix_mutator;
mod immix_space;
......
......@@ -35,6 +35,7 @@ extern crate num;
pub extern crate mu_ast as ast;
#[macro_use]
pub extern crate mu_utils as utils;
extern crate core;
pub extern crate mu_gc as gc;
extern crate proc_macro;
......
......@@ -73,24 +73,85 @@ lazy_static! {
"muentry_safecall_kill_stack",
vec![STACKREF_TYPE.clone()],
vec![]);
// pub static ref NEW_THREAD_NORMAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
// "muentry_new_thread_normal",
// vec![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![STACKREF_TYPE.clone(), REF_VOID_TYPE.clone(), REF_VOID_TYPE.clone()],
// vec![THREADREF_TYPE.clone()]);
}
#[cfg(not(feature = "realtime"))]
lazy_static! {
pub static ref NEW_THREAD_NORMAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_thread_normal",
vec![STACKREF_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
vec![THREADREF_TYPE.clone()]
);
pub static ref NEW_THREAD_EXCEPTIONAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_thread_exceptional",
vec![STACKREF_TYPE.clone(), REF_VOID_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
vec![
STACKREF_TYPE.clone(),
REF_VOID_TYPE.clone(),
REF_VOID_TYPE.clone()
],
vec![THREADREF_TYPE.clone()]
);
}
// decl: thread/mod.rs
#[cfg(feature = "realtime")]
lazy_static! {
pub static ref NOTIFY_THREAD: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_notify_to_run",
pub static ref NEW_RT_THREAD_NORMAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_rt_thread_normal",
vec![UPTR_RTATTR_TYPE.clone(), STACKREF_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
pub static ref NEW_RT_THREAD_EXCEPTIONAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_new_rt_thread_exceptional",
vec![UPTR_RTATTR_TYPE.clone(), STACKREF_TYPE.clone(), REF_VOID_TYPE.clone(), REF_VOID_TYPE.clone()],
vec![THREADREF_TYPE.clone()]);
// pub static ref NOTIFY_THREAD: RuntimeEntrypoint = RuntimeEntrypoint::new(
// "muentry_notify_to_run",
// vec![THREADREF_TYPE.clone()],
// vec![]
// );
pub static ref SET_PRIORITY: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_set_priority",
vec![THREADREF_TYPE.clone(), UINT64_TYPE.clone()],
vec![]
);
pub static ref GET_PRIORITY: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_get_priority",
vec![THREADREF_TYPE.clone()],
vec![UINT64_TYPE.clone()]
);
pub static ref AFF_ZERO: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_affinity_zero",
vec![THREADREF_TYPE.clone()],
vec![]
);
pub static ref AFF_CLEAR: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_affinity_clear",
vec![THREADREF_TYPE.clone(), UINT64_TYPE.clone()],
vec![]
);
pub static ref AFF_SET: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_affinity_set",
vec![THREADREF_TYPE.clone(), UINT64_TYPE.clone()],
vec![]
);
pub static ref AFF_ISSET: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_affinity_isset",
vec![THREADREF_TYPE.clone(), UINT64_TYPE.clone()],
vec![UINT1_TYPE.clone()]
);
pub static ref AFF_EQUAL: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muthread_affinity_equal",
vec![THREADREF_TYPE.clone(), THREADREF_TYPE.clone()],
vec![UINT1_TYPE.clone()]
);
}
// impl/decl: gc/lib.rs
......
......@@ -29,10 +29,6 @@ use std::sync::Arc;
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)
pub mod entrypoints;
......@@ -301,16 +297,17 @@ pub extern "C" fn mu_main(
.as_ref()
.map(|name| resolve_symbol(Arc::new(name.clone())))
.unwrap_or(unsafe { Address::zero() });
let muthread = thread::MuThread::new_thread_normal(stack, threadlocal, args, vm.clone());
MuThread::notify_to_run(muthread);
let _muthread = thread::MuThread::new_thread_normal(stack, threadlocal, args, vm.clone());
loop {
let thread = vm.pop_join_handle();
if thread.is_none() {
break;
}
thread.unwrap().join().unwrap();
unsafe {
(*thread.unwrap()).join();
};
}
info!("All threads have exited, quiting...");
......
This diff is collapsed.
......@@ -15,3 +15,75 @@
/// MU (non-real-time) specific threading stuff goes to this module
/// Currently it's empty
use super::*;
//pub(super) use super::thread_posix::*;
pub(super) use super::thread_mu_posix::*;
use core::borrow::BorrowMut;
impl MuThread {
/// creates and launches a mu thread, returns a JoinHandle and address to its MuThread structure
pub(super) fn mu_thread_launch(
id: MuID,
stack: Box<MuStack>,
user_tls: Address,
exception: Option<Address>,
vm: Arc<VM>,
) -> *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) };
let res = unsafe { sys_thread_launch(muthread, new_sp, exception) };
assert_eq!(res, MU_SUCCESS);
muthread_ptr
}
}
// 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 muthread = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
Some(exception),
vm.clone(),
);
vm.push_join_handle(muthread);
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 muthread = MuThread::mu_thread_launch(
vm.next_id(),
Box::from_raw(stack),
thread_local,
None,
vm.clone(),
);
vm.push_join_handle(muthread);
muthread
}
// Copyright 2019 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub(super) use super::thread_posix::*;
pub unsafe fn sys_thread_launch(
muthread: Box<MuThread>,
new_sp: Address,
exception: Option<Address>,
) -> SysResult {
let _sys_thread_id = &muthread.sys_thread_id as *const SysThreadID as *mut SysThreadID;
let exception = {
if exception.is_none() {
Address::from_ptr(std::ptr::null() as *const Address)
} else {
exception.unwrap()
}
};
let muthread_ptr = Box::into_raw(muthread);
let muthread_add = Address::from_mut_ptr(muthread_ptr);
let mut muthread_box = Box::from_raw(muthread_ptr);
{
muthread_box.sys_thread_context = (&MuThreadContext {
muthread: muthread_add,
new_sp,
exception,
} as *const MuThreadContext as *const SysVoid
as *mut SysVoid);
}
let muthread_ptr = Box::into_raw(muthread_box);
let res = libc::pthread_create(
_sys_thread_id,
SYSNULL as *const SysThreadAttr,
_pthread_entry_point,
muthread_ptr as *mut SysVoid,
);
res
}
// Copyright 2019 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate libc;
pub use super::*;
pub use ast::ir::*;
//pub use ast::ir_rt::*;
//pub use ast::ir_rt_posix::*;
pub use std::mem;
pub use std::os::raw::c_void;
pub use std::ptr;
//use rodal::Address;
pub type SysThreadID = libc::pthread_t;
pub type SysThreadAttr = libc::pthread_attr_t;
pub type SysResult = libc::c_int;
pub type SysVoid = libc::c_void;
pub const MU_SUCCESS: SysResult = 0;
pub const SYSNULL: *const i32 = ptr::null();
#[repr(C)]
pub(super) struct MuThreadContext {
pub muthread: Address,
// attr: Option<RTAttr>,
pub new_sp: Address,
pub exception: Address,
}
pub(super) extern "C" fn _pthread_entry_point(_arg: *mut SysVoid) -> *mut SysVoid {
// let muthread_ptr = _arg as *mut MuThread;