added timeval type, gettime and settime

parent c6557f98
......@@ -88,24 +88,22 @@ impl Instruction {
| NewThread { .. }
| NewRTThread { .. }
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_, _, _)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_, _)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NotifyThread(_) // TODO remove - not needed anymore
| SetPriority(_,_)
| GetPriority(_)
| AffinitySet(_,_)
| AffinityClear(_,_)
| AffinityEqual(_,_)
| AffinityIsset(_,_)
| AffinityZero(_)
| GetTime
| SetTime(_)
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -164,16 +162,14 @@ impl Instruction {
| NewHybrid(_, _)
| AllocAHybrid(_, _)
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_,_)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
......@@ -181,7 +177,8 @@ impl Instruction {
| SetPriority(_, _)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityZero(_)
// | AffinityZero(_)
| SetTime(_)
| NewFrameCursor(_)
| Fence(_)
| Return(_)
......@@ -232,8 +229,9 @@ impl Instruction {
| CurrentStack
| GetVMThreadLocal
| GetPriority(_)
| AffinityIsset(_, _)
| AffinityEqual(_, _) => false,
| GetTime
| AffinityIsset(_, _) => false,
// | AffinityEqual(_, _)
}
}
......@@ -264,26 +262,24 @@ impl Instruction {
| AllocAHybrid(_, _)
| NewStack(_)
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_, _)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
| SetPriority(_, _)
| GetPriority(_)
| AffinityZero(_)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityEqual(_, _)
| AffinityIsset(_, _)
| GetTime
| SetTime(_)
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -356,6 +352,7 @@ impl Instruction {
| AllocA(_)
| NewHybrid(_, _)
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
......@@ -374,10 +371,12 @@ impl Instruction {
| SetPriority(_,_) // FIXME - Not sure about these
| GetPriority(_)
| AffinityClear(_,_)
| AffinityEqual(_,_)
// | AffinityEqual(_,_)
| AffinityIsset(_,_)
| AffinitySet(_,_)
| AffinityZero(_)
// | AffinityZero(_)
| SetTime(_)
| GetTime
| NewFrameCursor(_)
| GetIRef(_)
| GetFieldIRef { .. }
......@@ -630,6 +629,9 @@ impl Instruction {
&Instruction_::AllocAU(ref ty) => {
format!("COMMINST @uvm.AllocAU({})", ty.id())
}
&Instruction_::AllocAUHybrid(ref ty, var_len) => {
format!("COMMINST @uvm.AllocAUHybrid({}, {})", ty.id(), ops[var_len])
}
&Instruction_::rAlloc(regref, ref ty) => {
format!("COMMINST @uvm.rAlloc({}, {})", ops[regref], ty.id())
}
......@@ -716,17 +718,17 @@ impl Instruction {
"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_::GetTime => format!(
"COMMINST @uvm.gettime()",
),
&Instruction_::SetTime(time) => format!(
"COMMINST @uvm.settime({})",
ops[time]
),
&Instruction_::NewFrameCursor(stack) => {
format!("COMMINST @uvm.meta.new_cursor({})", ops[stack])
}
......@@ -1130,6 +1132,7 @@ pub enum Instruction_ {
/// allocate an object (non hybrid type) on the stack, yields an uptr of
/// the type
AllocAU(P<MuType>),
AllocAUHybrid(P<MuType>, OpIndex),
/// allocate a hybrid type object in the heap, yields ref
/// args: the type of the hybrid, hybrid part length
......@@ -1165,22 +1168,10 @@ pub enum Instruction_ {
/// args: an uptr to the object
eDelete(OpIndex),
// /// allocate a traced object on the emm
// /// args: type of the object
// /// returns: an iref to the object
// eAllocT(P<MuType>),
// /// deallocate a traced emm object
// /// args: an iref to the object
// eDeleteT(OpIndex),
/// allocate a hybrid type object on the stack, yields iref
/// args: the type of the hybrid, hybrid part length
AllocAHybrid(P<MuType>, OpIndex),
// TODO add hybrid versions
// /// allocate a hybrid type object on the stack, yields uptr
// /// args: the type of the hybrid, hybrid part length
// AllocAUHybrid(P<MuType>, OpIndex),
/// create a new Mu stack, yields stack ref
/// args: functionref of the entry function
NewStack(OpIndex),
......@@ -1228,11 +1219,7 @@ pub enum Instruction_ {
/// - 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), /* TODO Check aff zero and equal and probably
* remove them */
// AffinityZero(OpIndex),
/// add a cpu to the cpu set of a thread
/// args:
......@@ -1251,11 +1238,10 @@ pub enum Instruction_ {
/// - 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),
// AffinityEqual(OpIndex, OpIndex),
GetTime,
SetTime(OpIndex),
/// create a frame cursor reference
/// args: stackref of a Mu stack
......
......@@ -105,6 +105,10 @@ lazy_static! {
));
pub static ref REGREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::regionref()));
pub static ref TIMERREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::timerref()));
pub static ref TIMEVAL_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::timeval()));
pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT1_TYPE.clone(),
......@@ -304,7 +308,10 @@ impl MuType {
| MuType_::Tagref64
| MuType_::UPtr(_) => true,
#[cfg(feature = "realtime")]
MuType_::RTAttr | MuType_::RegionRef => true,
MuType_::RTAttr
| MuType_::RegionRef
| MuType_::TimeVal
| MuType_::TimerRef => true,
_ => false
}
}
......@@ -534,6 +541,10 @@ impl MuType {
#[cfg(feature = "realtime")]
RegionRef => Some(64),
#[cfg(feature = "realtime")]
TimeVal => Some(64),
#[cfg(feature = "realtime")]
TimerRef => Some(64),
_ => None
}
......@@ -661,7 +672,11 @@ pub enum MuType_ {
#[cfg(feature = "realtime")]
RTAttr,
#[cfg(feature = "realtime")]
RegionRef
RegionRef,
#[cfg(feature = "realtime")]
TimerRef,
#[cfg(feature = "realtime")]
TimeVal
}
impl MuType_ {
......@@ -680,7 +695,7 @@ rodal_enum!(MuType_{(Int: size), Float, Double, (Ref: ty), (IRef: ty), (WeakRef:
#[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, RTAttr, StackRef, Tagref64,
(Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, RegionRef, TimerRef, TimeVal, RTAttr, StackRef, Tagref64,
(Vector: ty, size), (FuncRef: ty), (UFuncPtr: ty)});
impl fmt::Display for MuType {
......@@ -709,6 +724,10 @@ impl fmt::Display for MuType_ {
&MuType_::RTAttr => write!(f, "rtattr"),
#[cfg(feature = "realtime")]
&MuType_::RegionRef => write!(f, "regionref"),
#[cfg(feature = "realtime")]
&MuType_::TimerRef => write!(f, "timerref"),
#[cfg(feature = "realtime")]
&MuType_::TimeVal => write!(f, "timeval"),
&MuType_::StackRef => write!(f, "stackref"),
&MuType_::Tagref64 => write!(f, "tagref64"),
......@@ -891,6 +910,14 @@ impl MuType_ {
pub fn regionref() -> MuType_ {
MuType_::RegionRef
}
#[cfg(feature = "realtime")]
pub fn timerref() -> MuType_ {
MuType_::TimerRef
}
#[cfg(feature = "realtime")]
pub fn timeval() -> MuType_ {
MuType_::TimeVal
}
pub fn stackref() -> MuType_ {
MuType_::StackRef
......
......@@ -2930,27 +2930,6 @@ impl<'a> InstructionSelection {
);
}
#[cfg(feature = "realtime")]
Instruction_::AffinityZero(thread) => {
trace!("instsel on AffinityZero");
let ref ops = inst.ops;
let ref thread = ops[thread];
let tmp_thread =
self.emit_ireg(thread, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::AFF_ZERO,
vec![tmp_thread],
None,
Some(node),
f_content,
f_context,
vm
);
}
#[cfg(feature = "realtime")]
Instruction_::AffinityClear(thread, cpu) => {
trace!("instsel on AffinityClear");
......@@ -3025,22 +3004,14 @@ impl<'a> InstructionSelection {
}
#[cfg(feature = "realtime")]
Instruction_::AffinityEqual(thread1, thread2) => {
trace!("instsel on AffinityEqual");
let ref ops = inst.ops;
let ref t1 = ops[thread1];
let ref t2 = ops[thread2];
Instruction_::GetTime => {
trace!("instsel on GetTime");
let res = self.get_result_value(node);
let tmp_t1 =
self.emit_ireg(t1, f_content, f_context, vm);
let tmp_t2 =
self.emit_ireg(t2, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::AFF_EQUAL,
vec![tmp_t1, tmp_t2],
&entrypoints::GETTIME,
vec![],
Some(vec![res.clone()]),
Some(node),
f_content,
......@@ -3049,6 +3020,27 @@ impl<'a> InstructionSelection {
);
}
#[cfg(feature = "realtime")]
Instruction_::SetTime(time) => {
trace!("instsel on SetTime");
let ref ops = inst.ops;
let ref time = ops[time];
// let (time_h, time_l) =
let tmp_time= self.emit_ireg(time, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::SETTIME,
vec![tmp_time],
Some(vec![]),
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::CurrentStack => {
trace!("instsel on CURRENT_STACK");
......
......@@ -693,6 +693,7 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
AllocA(_) => 1,
AllocAHybrid(_, _) => 1,
AllocAU(_) => 1,
AllocAUHybrid(_,_) => 1,
Fence(_) => 1,
// memory addressing
......@@ -709,12 +710,9 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_, _, _)
// | rAllocT(_, _)
| eAlloc(_)
| eAllocHybrid(_, _)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
=> 10,
NewStack(_)
| NewThread { .. }
......@@ -722,8 +720,8 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
| NotifyThread(_)
| SetPriority(_, _)
| GetPriority(_)
| AffinityEqual(_, _)
| AffinityZero(_)
| GetTime
| SetTime(_)
| AffinityClear(_, _)
| AffinitySet(_, _)
| AffinityIsset(_, _)
......
......@@ -272,12 +272,18 @@ impl BackendType {
// RTMu-specific
#[cfg(feature = "realtime")]
MuType_::RegionRef => TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1),
MuType_::RegionRef
| MuType_::TimerRef => {
TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1)
},
#[cfg(feature = "realtime")]
MuType_::RTAttr => TypeEncode::short_noref(
MINIMAL_ALIGNMENT,
::runtime::thread::RTAttr::get_size() as u8
),
// TimeVal is 128bits (64bit for now) and in nano-seconds
#[cfg(feature = "realtime")]
MuType_::TimeVal => TypeEncode::short_noref(MINIMAL_ALIGNMENT, 1),
// tag ref
MuType_::Tagref64 => TypeEncode::short_tagref(),
......@@ -400,7 +406,7 @@ impl BackendType {
}
#[cfg(feature = "realtime")]
MuType_::RTAttr | MuType_::RegionRef => {
MuType_::RTAttr | MuType_::RegionRef | MuType_::TimeVal | MuType_::TimerRef => {
debug_assert!(pointer_aligned);
res.push(WordType::NonRef);
}
......@@ -548,6 +554,26 @@ impl BackendType {
gc_type: None,
gc_type_hybrid_full: None
},
#[cfg(feature = "realtime")]
MuType_::TimerRef => BackendType {
ty: ty.clone(),
size: 8,
alignment: 8,
struct_layout: None,
elem_size: None,
gc_type: None,
gc_type_hybrid_full: None
},
#[cfg(feature = "realtime")]
MuType_::TimeVal => BackendType {
ty: ty.clone(),
size: 8,
alignment: 8,
struct_layout: None,
elem_size: None,
gc_type: None,
gc_type_hybrid_full: None
},
// rtattr
#[cfg(feature = "realtime")]
MuType_::RTAttr => BackendType {
......@@ -959,6 +985,10 @@ impl RegGroup {
#[cfg(feature = "realtime")]
MuType_::RegionRef => RegGroup::GPR,
#[cfg(feature = "realtime")]
MuType_::TimerRef => RegGroup::GPR,
#[cfg(feature = "realtime")]
MuType_::TimeVal => RegGroup::GPR,
MuType_::Float => RegGroup::FPR,
MuType_::Double => RegGroup::FPR,
......
......@@ -79,16 +79,14 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| NewHybrid(_, _)
| AllocAHybrid(_, _)
| AllocAU(_)
| AllocAUHybrid(_,_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_,_)
// | rAllocT(_, _)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
......@@ -98,8 +96,8 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| AffinityIsset(_, _)
| AffinitySet(_, _)
| AffinityClear(_, _)
| AffinityZero(_)
| AffinityEqual(_, _)
| GetTime
| SetTime(_)
| NewFrameCursor(_)
| Select { .. }
| Fence(_)
......
// Copyright 2017 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 mod posix;
pub mod rust_std;
\ No newline at end of file
// 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 mod thread;
// 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 std::mem;
pub use std::os::raw::c_void;
pub use std::ptr;
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();
#[derive(Debug)]
#[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;
let muthread_boxed: Box<MuThread> =
unsafe { Box::from_raw(_arg as *mut MuThread) };
debug!("PTHREAD_ENTRY THREAD: {}", muthread_boxed);
// let muthread_ptr = Box::into_raw(context);
// let context = unsafe { Box::from_raw(context) };
let context = unsafe {
Box::from_raw(muthread_boxed.sys_thread_context as *mut MuThreadContext)
};
debug!("PTHREAD_ENTRY input context:{:#?}", context);
let _muthread = Box::into_raw(muthread_boxed);
let muthread_ptr: *mut MuThread = context.muthread.to_ptr_mut();
let new_sp = context.new_sp;
let exception = context.exception;
let _context = Box::into_raw(context);
let exception = {
if exception == Address::from_ptr(std::ptr::null() as *const Address) {
None
} else {
Some(exception)
}
};
// let muth_ptr = Box::into_raw(muthread);
//
// let muthread = unsafe { Box::from_raw(muth_ptr) };
// let muthread = Box::into_raw(muthread);
// let muthread = muthread as *const MuThread as *mut MuThread;
// set thread local
unsafe { set_thread_local(muthread_ptr) };
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_ptr);
}
std::ptr::null() as *const SysVoid as *mut SysVoid
}
pub(super) unsafe fn sys_thread_join(thread: SysThreadID) -> SysResult {
libc::pthread_join(
thread,
std::ptr::null() as *const c_void as *mut c_void as *mut *mut c_void
)
}
pub(super) fn sys_thread_self() -> SysThreadID {
unsafe { libc::pthread_self() }
}
// 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.
// 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.
use super::*;
use std::alloc::{alloc, dealloc, Layout};
pub type SysMemBackStore = *mut u8;
pub fn sys_get_base_addr(ptr: SysMemBackStore) -> Address {
Address::from_mut_ptr(ptr)
}
pub fn sys_new_raw_mem(size: usize) -> SysMemBackStore {
sys_allocate_by_size(size)
}
pub fn sys_delete_raw_mem(backstore: SysMemBackStore, size: usize) {
sys_delete_mem(backstore, size)
}
pub fn sys_ealloc(size: usize) -> Address {
sys_get_base_addr(sys_allocate_by_size(size))
}
pub fn sys_edelete(backstore: Address, size: usize) {
sys_delete_mem(backstore.to_ptr_mut() as *const u8 as *mut u8, size)
}
pub fn sys_get_aligned_size(size: usize, align: usize) -> usize {
if size % align == 0 {
size
} else {
size + (align - (size % align))
}
}
fn sys_allocate_by_size(size: usize) -> SysMemBackStore {
let mem_layout =
Box::new(match Layout::from_size_align(size, POINTER_SIZE) {
Ok(LO) => LO,
Err(ERR) => panic!("Allocating region failed with err: {}", ERR)
});
unsafe { alloc(*mem_layout) }
}
fn sys_delete_mem(backstore: SysMemBackStore, size: usize) {
let bbbox = unsafe { Box::from_raw(backstore) };
let mem_layout =
Box::new(match Layout::from_size_align(size, POINTER_SIZE) {
Ok(LO) => LO,
Err(ERR) => panic!("Allocating region failed with err: {}", ERR)
});
unsafe { dealloc(backstore, *mem_layout) };