Skip to content

Commit

Permalink
Auto merge of rust-lang#116565 - Sword-Destiny:master, r=Amanieu
Browse files Browse the repository at this point in the history
add teeos std impl

add teeos std library implement.

this MR is draft untill the libc update to 0.2.150

this MR is the final step for suppot rust in teeos.
first step(add target): rust-lang#113480
second step(add teeos libc): rust-lang/libc#3333
  • Loading branch information
bors committed Dec 7, 2023
2 parents c9d85d6 + e353eb9 commit 568f6a8
Show file tree
Hide file tree
Showing 18 changed files with 1,190 additions and 10 deletions.
Expand Up @@ -4,7 +4,6 @@ pub fn target() -> Target {
let mut base = base::teeos::opts();
base.features = "+strict-align,+neon,+fp-armv8".into();
base.max_atomic_width = Some(128);
base.linker = Some("aarch64-linux-gnu-ld".into());

Target {
llvm_target: "aarch64-unknown-none".into(),
Expand Down
10 changes: 10 additions & 0 deletions library/panic_abort/src/lib.rs
Expand Up @@ -81,6 +81,16 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
}
core::intrinsics::unreachable();
}
} else if #[cfg(target_os = "teeos")] {
mod teeos {
extern "C" {
pub fn TEE_Panic(code: u32) -> !;
}
}

unsafe fn abort() -> ! {
teeos::TEE_Panic(1);
}
} else {
unsafe fn abort() -> ! {
core::intrinsics::abort();
Expand Down
1 change: 1 addition & 0 deletions library/std/build.rs
Expand Up @@ -34,6 +34,7 @@ fn main() {
|| target.contains("xous")
|| target.contains("hurd")
|| target.contains("uefi")
|| target.contains("teeos")
// See src/bootstrap/synthetic_targets.rs
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()
{
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/sys/mod.rs
Expand Up @@ -53,6 +53,9 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
pub use self::sgx::*;
} else if #[cfg(target_os = "teeos")] {
mod teeos;
pub use self::teeos::*;
} else {
mod unsupported;
pub use self::unsupported::*;
Expand Down
57 changes: 57 additions & 0 deletions library/std/src/sys/teeos/alloc.rs
@@ -0,0 +1,57 @@
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ptr;
use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// jemalloc provides alignment less than MIN_ALIGN for small allocations.
// So only rely on MIN_ALIGN if size >= align.
// Also see <https://github.com/rust-lang/rust/issues/45955> and
// <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>.
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
libc::malloc(layout.size()) as *mut u8
} else {
aligned_malloc(&layout)
}
}

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
// See the comment above in `alloc` for why this check looks the way it does.
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
libc::calloc(layout.size(), 1) as *mut u8
} else {
let ptr = self.alloc(layout);
if !ptr.is_null() {
ptr::write_bytes(ptr, 0, layout.size());
}
ptr
}
}

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
libc::free(ptr as *mut libc::c_void)
}

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
} else {
realloc_fallback(self, ptr, layout, new_size)
}
}
}

#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
let mut out = ptr::null_mut();
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
// Since these are all powers of 2, we can just use max.
let align = layout.align().max(crate::mem::size_of::<usize>());
let ret = libc::posix_memalign(&mut out, align, layout.size());
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
}
100 changes: 100 additions & 0 deletions library/std/src/sys/teeos/locks/condvar.rs
@@ -0,0 +1,100 @@
use crate::cell::UnsafeCell;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
use crate::sys::locks::mutex::{self, Mutex};
use crate::sys::time::TIMESPEC_MAX;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;

extern "C" {
pub fn pthread_cond_timedwait(
cond: *mut libc::pthread_cond_t,
lock: *mut libc::pthread_mutex_t,
adstime: *const libc::timespec,
) -> libc::c_int;
}

struct AllocatedCondvar(UnsafeCell<libc::pthread_cond_t>);

pub struct Condvar {
inner: LazyBox<AllocatedCondvar>,
mutex: AtomicPtr<libc::pthread_mutex_t>,
}

#[inline]
fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
c.inner.0.get()
}

unsafe impl Send for AllocatedCondvar {}
unsafe impl Sync for AllocatedCondvar {}

impl LazyInit for AllocatedCondvar {
fn init() -> Box<Self> {
let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER)));

let r = unsafe { libc::pthread_cond_init(condvar.0.get(), crate::ptr::null()) };
assert_eq!(r, 0);

condvar
}
}

impl Drop for AllocatedCondvar {
#[inline]
fn drop(&mut self) {
let r = unsafe { libc::pthread_cond_destroy(self.0.get()) };
debug_assert_eq!(r, 0);
}
}

impl Condvar {
pub const fn new() -> Condvar {
Condvar { inner: LazyBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) }
}

#[inline]
fn verify(&self, mutex: *mut libc::pthread_mutex_t) {
match self.mutex.compare_exchange(ptr::null_mut(), mutex, Relaxed, Relaxed) {
Ok(_) => {} // Stored the address
Err(n) if n == mutex => {} // Lost a race to store the same address
_ => panic!("attempted to use a condition variable with two mutexes"),
}
}

#[inline]
pub fn notify_one(&self) {
let r = unsafe { libc::pthread_cond_signal(raw(self)) };
debug_assert_eq!(r, 0);
}

#[inline]
pub fn notify_all(&self) {
let r = unsafe { libc::pthread_cond_broadcast(raw(self)) };
debug_assert_eq!(r, 0);
}

#[inline]
pub unsafe fn wait(&self, mutex: &Mutex) {
let mutex = mutex::raw(mutex);
self.verify(mutex);
let r = libc::pthread_cond_wait(raw(self), mutex);
debug_assert_eq!(r, 0);
}

pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
use crate::sys::time::Timespec;

let mutex = mutex::raw(mutex);
self.verify(mutex);

let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
.checked_add_duration(&dur)
.and_then(|t| t.to_timespec())
.unwrap_or(TIMESPEC_MAX);

let r = pthread_cond_timedwait(raw(self), mutex, &timeout);
assert!(r == libc::ETIMEDOUT || r == 0);
r == 0
}
}
8 changes: 8 additions & 0 deletions library/std/src/sys/teeos/locks/mod.rs
@@ -0,0 +1,8 @@
pub mod condvar;
#[path = "../../unix/locks/pthread_mutex.rs"]
pub mod mutex;
pub mod rwlock;

pub(crate) use condvar::Condvar;
pub(crate) use mutex::Mutex;
pub(crate) use rwlock::RwLock;
44 changes: 44 additions & 0 deletions library/std/src/sys/teeos/locks/rwlock.rs
@@ -0,0 +1,44 @@
use crate::sys::locks::mutex::Mutex;

/// we do not supported rwlock, so use mutex to simulate rwlock.
/// it's useful because so many code in std will use rwlock.
pub struct RwLock {
inner: Mutex,
}

impl RwLock {
#[inline]
pub const fn new() -> RwLock {
RwLock { inner: Mutex::new() }
}

#[inline]
pub fn read(&self) {
unsafe { self.inner.lock() };
}

#[inline]
pub fn try_read(&self) -> bool {
unsafe { self.inner.try_lock() }
}

#[inline]
pub fn write(&self) {
unsafe { self.inner.lock() };
}

#[inline]
pub unsafe fn try_write(&self) -> bool {
unsafe { self.inner.try_lock() }
}

#[inline]
pub unsafe fn read_unlock(&self) {
unsafe { self.inner.unlock() };
}

#[inline]
pub unsafe fn write_unlock(&self) {
unsafe { self.inner.unlock() };
}
}

0 comments on commit 568f6a8

Please sign in to comment.