Browse Source

Merge pull request #9 from Meziu/feature/pthread-threads

Add back threading support and implement extensions
pull/11/head
Meziu 3 years ago committed by GitHub
parent
commit
b3498da8a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.toml
  2. 142
      src/lib.rs

1
Cargo.toml

@ -9,3 +9,4 @@ edition = "2021"
libc = "0.2.116" libc = "0.2.116"
ctru-sys = { git = "https://github.com/Meziu/ctru-rs.git" } ctru-sys = { git = "https://github.com/Meziu/ctru-rs.git" }
spin = { version = "0.9", default-features = false, features = ["rwlock", "std"] } spin = { version = "0.9", default-features = false, features = ["rwlock", "std"] }
static_assertions = "1.0"

142
src/lib.rs

@ -3,6 +3,8 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
use std::ptr;
/// Call this somewhere to force Rust to link this module. /// Call this somewhere to force Rust to link this module.
/// The call doesn't need to execute, just exist. /// The call doesn't need to execute, just exist.
/// ///
@ -13,48 +15,153 @@ pub fn init() {}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_create( pub unsafe extern "C" fn pthread_create(
_native: *mut libc::pthread_t, native: *mut libc::pthread_t,
_attr: *const libc::pthread_attr_t, attr: *const libc::pthread_attr_t,
_f: extern "C" fn(_: *mut libc::c_void) -> *mut libc::c_void, entrypoint: extern "C" fn(_: *mut libc::c_void) -> *mut libc::c_void,
_value: *mut libc::c_void, value: *mut libc::c_void,
) -> libc::c_int { ) -> libc::c_int {
1 let attr = attr as *const PThreadAttr;
let stack_size = (*attr).stack_size.unwrap_or(libc::PTHREAD_STACK_MIN) as ctru_sys::size_t;
// If no priority value is specified, spawn with the same
// priority as the parent thread
let priority = (*attr).priority.unwrap_or_else(|| pthread_getpriority());
// If no affinity is specified, spawn on the default core (determined by
// the application's Exheader)
let affinity = (*attr).affinity.unwrap_or(-2);
extern "C" fn thread_start(main: *mut libc::c_void) {
unsafe {
Box::from_raw(main as *mut Box<dyn FnOnce() -> *mut libc::c_void>)();
}
}
// The closure needs a fat pointer (64 bits) to work since it captures a variable and is thus a
// trait object, but *mut void is only 32 bits. We need double indirection to pass along the
// full closure data.
// We make this closure in the first place because threadCreate expects a void return type, but
// entrypoint returns a pointer so the types are incompatible.
let main: *mut Box<dyn FnOnce() -> *mut libc::c_void> =
Box::into_raw(Box::new(Box::new(move || entrypoint(value))));
let handle = ctru_sys::threadCreate(
Some(thread_start),
main as *mut libc::c_void,
stack_size,
priority,
affinity,
false,
);
if handle.is_null() {
// There was some error, but libctru doesn't expose the result.
// We assume there was an incorrect parameter (such as too low of a priority).
// We also need to clean up the closure at this time.
drop(Box::from_raw(main));
return libc::EINVAL;
}
*native = handle as _;
0
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_join( pub unsafe extern "C" fn pthread_join(
_native: libc::pthread_t, native: libc::pthread_t,
_value: *mut *mut libc::c_void, _value: *mut *mut libc::c_void,
) -> libc::c_int { ) -> libc::c_int {
1 ctru_sys::threadJoin(native as ctru_sys::Thread, u64::MAX);
ctru_sys::threadFree(native as ctru_sys::Thread);
0
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_detach(_thread: libc::pthread_t) -> libc::c_int { pub unsafe extern "C" fn pthread_detach(thread: libc::pthread_t) -> libc::c_int {
1 ctru_sys::threadDetach(thread as ctru_sys::Thread);
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_getpriority() -> libc::c_int {
let mut priority = 0;
ctru_sys::svcGetThreadPriority(&mut priority, ctru_sys::CUR_THREAD_HANDLE);
priority
}
/// Internal struct for storing pthread attribute data
/// Must be less than or equal to the size of `libc::pthread_attr_t`. We assert
/// this below via static_assertions.
struct PThreadAttr {
stack_size: Option<libc::size_t>,
priority: Option<libc::c_int>,
affinity: Option<libc::c_int>,
} }
static_assertions::const_assert!(
std::mem::size_of::<PThreadAttr>() <= std::mem::size_of::<libc::pthread_attr_t>()
);
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_attr_init(_attr: *mut libc::pthread_attr_t) -> libc::c_int { pub unsafe extern "C" fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int {
1 let attr = attr as *mut PThreadAttr;
*attr = PThreadAttr {
stack_size: None,
priority: None,
affinity: None,
};
0
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut libc::pthread_attr_t) -> libc::c_int { pub unsafe extern "C" fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int {
1 ptr::drop_in_place(attr as *mut PThreadAttr);
0
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_attr_setstacksize( pub unsafe extern "C" fn pthread_attr_setstacksize(
_attr: *mut libc::pthread_attr_t, attr: *mut libc::pthread_attr_t,
_stack_size: libc::size_t, stack_size: libc::size_t,
) -> libc::c_int { ) -> libc::c_int {
1 let attr = attr as *mut PThreadAttr;
(*attr).stack_size = Some(stack_size);
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_attr_setpriority(
attr: *mut libc::pthread_attr_t,
priority: libc::c_int,
) -> libc::c_int {
let attr = attr as *mut PThreadAttr;
(*attr).priority = Some(priority);
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_attr_setaffinity(
attr: *mut libc::pthread_attr_t,
affinity: libc::c_int,
) -> libc::c_int {
let attr = attr as *mut PThreadAttr;
(*attr).affinity = Some(affinity);
0
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sched_yield() -> libc::c_int { pub unsafe extern "C" fn sched_yield() -> libc::c_int {
1 ctru_sys::svcSleepThread(0);
0
} }
#[no_mangle] #[no_mangle]
@ -407,7 +514,6 @@ pub unsafe extern "C" fn pthread_sigmask(
use spin::rwlock::RwLock; use spin::rwlock::RwLock;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
type Key = usize; type Key = usize;

Loading…
Cancel
Save