diff options
| author | Fenrir <[email protected]> | 2017-03-05 00:25:16 -0700 |
|---|---|---|
| committer | Fenrir <[email protected]> | 2017-03-05 02:19:40 -0700 |
| commit | 5299b505b79c48e788067d66a727636ff933de92 (patch) | |
| tree | e882dbf4591a81bdefd7c721038eac3562eaacaf /ctr-std/src/sys | |
| parent | Merge pull request #24 from FenrirWolf/unit_type (diff) | |
| download | ctru-rs-5299b505b79c48e788067d66a727636ff933de92.tar.xz ctru-rs-5299b505b79c48e788067d66a727636ff933de92.zip | |
Initial thread support
Diffstat (limited to 'ctr-std/src/sys')
| -rw-r--r-- | ctr-std/src/sys/unix/condvar.rs | 111 | ||||
| -rw-r--r-- | ctr-std/src/sys/unix/mod.rs | 3 | ||||
| -rw-r--r-- | ctr-std/src/sys/unix/rwlock.rs | 61 | ||||
| -rw-r--r-- | ctr-std/src/sys/unix/thread.rs | 90 |
4 files changed, 265 insertions, 0 deletions
diff --git a/ctr-std/src/sys/unix/condvar.rs b/ctr-std/src/sys/unix/condvar.rs new file mode 100644 index 0000000..f19922c --- /dev/null +++ b/ctr-std/src/sys/unix/condvar.rs @@ -0,0 +1,111 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// *Implementation adapted from `/sys/redox/condvar.rs` + +use cell::UnsafeCell; +use intrinsics::atomic_cxchg; +use ptr; +use time::Duration; + +use sys::mutex::{self, Mutex}; + +use libctru::synchronization::{__sync_get_arbiter, LightLock}; +use libctru::svc::{svcArbitrateAddress, ArbitrationType}; + +pub struct Condvar { + lock: UnsafeCell<*mut LightLock>, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { + lock: UnsafeCell::new(ptr::null_mut()), + } + } + + #[inline] + pub unsafe fn init(&self) { + *self.lock.get() = ptr::null_mut(); + } + + #[inline] + pub fn notify_one(&self) { + unsafe { + let arbiter = __sync_get_arbiter(); + + svcArbitrateAddress(arbiter, + *self.lock.get() as u32, + ArbitrationType::ARBITRATION_SIGNAL, + 1, + 0); + } + } + + #[inline] + pub fn notify_all(&self) { + unsafe { + let lock = self.lock.get(); + + if *lock == ptr::null_mut() { + return; + } + + let arbiter = __sync_get_arbiter(); + + svcArbitrateAddress(arbiter, + *self.lock.get() as u32, + ArbitrationType::ARBITRATION_SIGNAL, + -1, + 0); + } + } + + #[inline] + pub fn wait(&self, mutex: &Mutex) { + unsafe { + let lock = self.lock.get(); + + if *lock != mutex::raw(mutex) { + if *lock != ptr::null_mut() { + panic!("Condvar used with more than one Mutex"); + } + + atomic_cxchg(lock as *mut usize, 0, mutex::raw(mutex) as usize); + } + + mutex.unlock(); + + let arbiter = __sync_get_arbiter(); + + svcArbitrateAddress(arbiter, + *self.lock.get() as u32, + ArbitrationType::ARBITRATION_WAIT_IF_LESS_THAN, + 0, + 0); + + mutex.lock(); + } + } + + #[inline] + pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n")); + unimplemented!(); + } + + #[inline] + pub unsafe fn destroy(&self) { + *self.lock.get() = ptr::null_mut(); + } +} diff --git a/ctr-std/src/sys/unix/mod.rs b/ctr-std/src/sys/unix/mod.rs index 0da1d3b..76a4555 100644 --- a/ctr-std/src/sys/unix/mod.rs +++ b/ctr-std/src/sys/unix/mod.rs @@ -13,6 +13,7 @@ use io::{self, ErrorKind}; use libc; +pub mod condvar; pub mod ext; pub mod fast_thread_local; pub mod fd; @@ -22,6 +23,8 @@ pub mod mutex; pub mod os; pub mod os_str; pub mod path; +pub mod rwlock; +pub mod thread; pub mod thread_local; pub mod time; diff --git a/ctr-std/src/sys/unix/rwlock.rs b/ctr-std/src/sys/unix/rwlock.rs new file mode 100644 index 0000000..d74b614 --- /dev/null +++ b/ctr-std/src/sys/unix/rwlock.rs @@ -0,0 +1,61 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::mutex::Mutex; + +pub struct RWLock { + mutex: Mutex +} + +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + +impl RWLock { + pub const fn new() -> RWLock { + RWLock { + mutex: Mutex::new() + } + } + + #[inline] + pub unsafe fn read(&self) { + self.mutex.lock(); + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + self.mutex.try_lock() + } + + #[inline] + pub unsafe fn write(&self) { + self.mutex.lock(); + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + self.mutex.try_lock() + } + + #[inline] + pub unsafe fn read_unlock(&self) { + self.mutex.unlock(); + } + + #[inline] + pub unsafe fn write_unlock(&self) { + self.mutex.unlock(); + } + + #[inline] + pub unsafe fn destroy(&self) { + self.mutex.destroy(); + } +} diff --git a/ctr-std/src/sys/unix/thread.rs b/ctr-std/src/sys/unix/thread.rs new file mode 100644 index 0000000..4eac345 --- /dev/null +++ b/ctr-std/src/sys/unix/thread.rs @@ -0,0 +1,90 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use alloc::boxed::FnBox; +use libc; +use cmp; +use ffi::CStr; +use io; +use mem; +use ptr; +use sys_common::thread::start_thread; +use time::Duration; + +use libctru::svc::svcSleepThread; +use libctru::thread::{threadCreate, threadJoin, threadFree}; +use libctru::thread::Thread as ThreadHandle; + +pub struct Thread { + handle: ThreadHandle, +} + +// Some platforms may have pthread_t as a pointer in which case we still want +// a thread to be Send/Sync +unsafe impl Send for Thread {} +unsafe impl Sync for Thread {} + +impl Thread { + pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> { + let p = box p; + let stack_size = cmp::max(stack, 4 * 1024); + + let handle = threadCreate(Some(thread_func), &*p as *const _ as *mut _, + stack_size, 0x29, -2, 0); + + return if handle == ptr::null_mut() { + Err(io::Error::from_raw_os_error(libc::EAGAIN)) + } else { + mem::forget(p); // ownership passed to the new thread + Ok(Thread { handle: handle }) + }; + + extern "C" fn thread_func(start: *mut libc::c_void) { + unsafe { start_thread(start) } + } + } + + pub fn yield_now() { + unimplemented!() + } + + pub fn set_name(_name: &CStr) { + // can't set thread names on the 3DS + } + + pub fn sleep(dur: Duration) { + unsafe { + let nanos = dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64; + svcSleepThread(nanos as i64) + } + } + + pub fn join(self) { + unsafe { + let ret = threadJoin(self.handle, u64::max_value()); + threadFree(self.handle); + mem::forget(self); + debug_assert_eq!(ret, 0); + } + } + + pub fn id(&self) -> usize { + unimplemented!() + } + + pub fn into_id(self) -> usize { + unimplemented!() + } +} + +pub mod guard { + pub unsafe fn current() -> Option<usize> { None } + pub unsafe fn init() -> Option<usize> { None } +} |