|
|
@ -29,20 +29,26 @@ static mut THREAD_ID: libc::pthread_t = MAIN_THREAD_ID; |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)] |
|
|
|
#[derive(Copy, Clone)] |
|
|
|
struct PThread { |
|
|
|
struct PThread { |
|
|
|
thread: SendableThreadPtr, |
|
|
|
thread: SendPtr<ctru_sys::Thread_tag>, |
|
|
|
os_thread_id: u32, |
|
|
|
os_thread_id: u32, |
|
|
|
is_detached: bool, |
|
|
|
is_detached: bool, |
|
|
|
is_finished: bool, |
|
|
|
is_finished: bool, |
|
|
|
result: *mut libc::c_void, |
|
|
|
result: SendPtr<libc::c_void>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Pointers are not Send (though it's really just a lint). But we want to share
|
|
|
|
/// Pointers are not Send, though it's really just a lint. This struct lets us
|
|
|
|
/// the `ctru_sys::Thread` pointer types in the global THREADS map. This struct
|
|
|
|
/// ignore that "lint".
|
|
|
|
/// lets us ignore that "lint".
|
|
|
|
struct SendPtr<T>(*mut T); |
|
|
|
#[derive(Copy, Clone)] |
|
|
|
unsafe impl<T> Send for SendPtr<T> {} |
|
|
|
struct SendableThreadPtr(ctru_sys::Thread); |
|
|
|
unsafe impl<T> Sync for SendPtr<T> {} |
|
|
|
unsafe impl Send for SendableThreadPtr {} |
|
|
|
|
|
|
|
unsafe impl Sync for SendableThreadPtr {} |
|
|
|
// We can't use the derives because they add an unnecessary T: Copy/Clone bound.
|
|
|
|
|
|
|
|
impl<T> Copy for SendPtr<T> {} |
|
|
|
|
|
|
|
impl<T> Clone for SendPtr<T> { |
|
|
|
|
|
|
|
fn clone(&self) -> Self { |
|
|
|
|
|
|
|
*self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle] |
|
|
|
#[no_mangle] |
|
|
|
pub unsafe extern "C" fn pthread_create( |
|
|
|
pub unsafe extern "C" fn pthread_create( |
|
|
@ -83,7 +89,7 @@ pub unsafe extern "C" fn pthread_create( |
|
|
|
let mut thread_map = THREADS.write(); |
|
|
|
let mut thread_map = THREADS.write(); |
|
|
|
if let Some(mut pthread) = thread_map.get_mut(&thread_id) { |
|
|
|
if let Some(mut pthread) = thread_map.get_mut(&thread_id) { |
|
|
|
pthread.is_finished = true; |
|
|
|
pthread.is_finished = true; |
|
|
|
pthread.result = result; |
|
|
|
pthread.result.0 = result; |
|
|
|
|
|
|
|
|
|
|
|
if pthread.is_detached { |
|
|
|
if pthread.is_detached { |
|
|
|
// libctru will call threadFree once this thread dies
|
|
|
|
// libctru will call threadFree once this thread dies
|
|
|
@ -122,11 +128,11 @@ pub unsafe extern "C" fn pthread_create( |
|
|
|
THREADS.write().insert( |
|
|
|
THREADS.write().insert( |
|
|
|
thread_id, |
|
|
|
thread_id, |
|
|
|
PThread { |
|
|
|
PThread { |
|
|
|
thread: SendableThreadPtr(thread), |
|
|
|
thread: SendPtr(thread), |
|
|
|
os_thread_id, |
|
|
|
os_thread_id, |
|
|
|
is_detached: false, |
|
|
|
is_detached: false, |
|
|
|
is_finished: false, |
|
|
|
is_finished: false, |
|
|
|
result: ptr::null_mut(), |
|
|
|
result: SendPtr(ptr::null_mut()), |
|
|
|
}, |
|
|
|
}, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
@ -171,7 +177,7 @@ pub unsafe extern "C" fn pthread_join( |
|
|
|
// This should always be Some, but we use an if let just in case.
|
|
|
|
// This should always be Some, but we use an if let just in case.
|
|
|
|
if let Some(thread_data) = thread_data { |
|
|
|
if let Some(thread_data) = thread_data { |
|
|
|
if !return_value.is_null() { |
|
|
|
if !return_value.is_null() { |
|
|
|
*return_value = thread_data.result; |
|
|
|
*return_value = thread_data.result.0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -226,11 +232,11 @@ pub unsafe extern "C" fn pthread_self() -> libc::pthread_t { |
|
|
|
PThread { |
|
|
|
PThread { |
|
|
|
// This null pointer is safe because we return before ever using
|
|
|
|
// This null pointer is safe because we return before ever using
|
|
|
|
// it (in pthread_join and pthread_detach).
|
|
|
|
// it (in pthread_join and pthread_detach).
|
|
|
|
thread: SendableThreadPtr(ptr::null_mut()), |
|
|
|
thread: SendPtr(ptr::null_mut()), |
|
|
|
os_thread_id, |
|
|
|
os_thread_id, |
|
|
|
is_detached: true, |
|
|
|
is_detached: true, |
|
|
|
is_finished: false, |
|
|
|
is_finished: false, |
|
|
|
result: ptr::null_mut(), |
|
|
|
result: SendPtr(ptr::null_mut()), |
|
|
|
}, |
|
|
|
}, |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|