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. 3
      Cargo.toml
  2. 142
      src/lib.rs

3
Cargo.toml

@ -8,4 +8,5 @@ edition = "2021" @@ -8,4 +8,5 @@ edition = "2021"
[dependencies]
libc = "0.2.116"
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 @@ @@ -3,6 +3,8 @@
#![allow(non_camel_case_types)]
#![allow(clippy::missing_safety_doc)]
use std::ptr;
/// Call this somewhere to force Rust to link this module.
/// The call doesn't need to execute, just exist.
///
@ -13,48 +15,153 @@ pub fn init() {} @@ -13,48 +15,153 @@ pub fn init() {}
#[no_mangle]
pub unsafe extern "C" fn pthread_create(
_native: *mut libc::pthread_t,
_attr: *const libc::pthread_attr_t,
_f: extern "C" fn(_: *mut libc::c_void) -> *mut libc::c_void,
_value: *mut libc::c_void,
native: *mut libc::pthread_t,
attr: *const libc::pthread_attr_t,
entrypoint: extern "C" fn(_: *mut libc::c_void) -> *mut libc::c_void,
value: *mut libc::c_void,
) -> 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]
pub unsafe extern "C" fn pthread_join(
_native: libc::pthread_t,
native: libc::pthread_t,
_value: *mut *mut libc::c_void,
) -> 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]
pub unsafe extern "C" fn pthread_detach(_thread: libc::pthread_t) -> libc::c_int {
1
pub unsafe extern "C" fn pthread_detach(thread: libc::pthread_t) -> libc::c_int {
ctru_sys::threadDetach(thread as ctru_sys::Thread);
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_attr_init(_attr: *mut libc::pthread_attr_t) -> libc::c_int {
1
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]
pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut libc::pthread_attr_t) -> libc::c_int {
1
pub unsafe extern "C" fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int {
let attr = attr as *mut PThreadAttr;
*attr = PThreadAttr {
stack_size: None,
priority: None,
affinity: None,
};
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int {
ptr::drop_in_place(attr as *mut PThreadAttr);
0
}
#[no_mangle]
pub unsafe extern "C" fn pthread_attr_setstacksize(
_attr: *mut libc::pthread_attr_t,
_stack_size: libc::size_t,
attr: *mut libc::pthread_attr_t,
stack_size: libc::size_t,
) -> libc::c_int {
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 {
1
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]
pub unsafe extern "C" fn sched_yield() -> libc::c_int {
1
ctru_sys::svcSleepThread(0);
0
}
#[no_mangle]
@ -407,7 +514,6 @@ pub unsafe extern "C" fn pthread_sigmask( @@ -407,7 +514,6 @@ pub unsafe extern "C" fn pthread_sigmask(
use spin::rwlock::RwLock;
use std::collections::BTreeMap;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering};
type Key = usize;

Loading…
Cancel
Save