Skip to content

Commit

Permalink
Merge pull request #29 from rust3ds/feature/tls-dtors
Browse files Browse the repository at this point in the history
  • Loading branch information
Meziu authored May 5, 2024
2 parents c885d8c + 949d8d9 commit b15d26d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 12 deletions.
12 changes: 6 additions & 6 deletions src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ pub unsafe extern "C" fn pthread_mutex_destroy(_lock: *mut libc::pthread_mutex_t
pub unsafe extern "C" fn pthread_mutex_lock(lock: *mut libc::pthread_mutex_t) -> libc::c_int {
let lock = lock as *const u8;

if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_NORMAL as u8 {
if *(lock.offset(39)) == libc::PTHREAD_MUTEX_NORMAL as u8 {
ctru_sys::LightLock_Lock(lock as _);
} else if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
} else if *(lock.offset(39)) == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
ctru_sys::RecursiveLock_Lock(lock as _);
}

Expand All @@ -61,9 +61,9 @@ pub unsafe extern "C" fn pthread_mutex_lock(lock: *mut libc::pthread_mutex_t) ->
pub unsafe extern "C" fn pthread_mutex_trylock(lock: *mut libc::pthread_mutex_t) -> libc::c_int {
let lock = lock as *const u8;

if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_NORMAL as u8 {
if *(lock.offset(39)) == libc::PTHREAD_MUTEX_NORMAL as u8 {
return ctru_sys::LightLock_TryLock(lock as _);
} else if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
} else if *(lock.offset(39)) == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
return ctru_sys::RecursiveLock_TryLock(lock as _);
}

Expand All @@ -74,9 +74,9 @@ pub unsafe extern "C" fn pthread_mutex_trylock(lock: *mut libc::pthread_mutex_t)
pub unsafe extern "C" fn pthread_mutex_unlock(lock: *mut libc::pthread_mutex_t) -> libc::c_int {
let lock = lock as *const u8;

if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_NORMAL as u8 {
if *(lock.offset(39)) == libc::PTHREAD_MUTEX_NORMAL as u8 {
ctru_sys::LightLock_Unlock(lock as _);
} else if *(lock.offset(39)) as u8 == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
} else if *(lock.offset(39)) == libc::PTHREAD_MUTEX_RECURSIVE as u8 {
ctru_sys::RecursiveLock_Unlock(lock as _);
}

Expand Down
14 changes: 9 additions & 5 deletions src/thread.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::collections::BTreeMap;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering};

use crate::thread_keys;

pub mod attr;

/// The main thread's pthread ID
Expand Down Expand Up @@ -83,10 +85,12 @@ pub unsafe extern "C" fn pthread_create(
// check is_detached and it's still false, so thread is never
// removed from the map)
let mut thread_map = THREADS.write();
if let Some(mut pthread) = thread_map.get_mut(&thread_id) {
if let Some(pthread) = thread_map.get_mut(&thread_id) {
pthread.is_finished = true;
pthread.result.0 = result;

thread_keys::run_local_destructors();

if pthread.is_detached {
// libctru will call threadFree once this thread dies
thread_map.remove(&thread_id);
Expand Down Expand Up @@ -150,7 +154,7 @@ pub unsafe extern "C" fn pthread_join(
let thread_map = THREADS.read();
let Some(&pthread) = thread_map.get(&thread_id) else {
// This is not a valid thread ID
return libc::ESRCH
return libc::ESRCH;
};
// We need to drop our read guard so it doesn't stay locked while joining
// the thread.
Expand Down Expand Up @@ -188,9 +192,9 @@ pub unsafe extern "C" fn pthread_detach(thread_id: libc::pthread_t) -> libc::c_i
}

let mut thread_map = THREADS.write();
let Some(mut pthread) = thread_map.get_mut(&thread_id) else {
let Some(pthread) = thread_map.get_mut(&thread_id) else {
// This is not a valid thread ID
return libc::ESRCH
return libc::ESRCH;
};

if pthread.is_detached {
Expand Down Expand Up @@ -249,7 +253,7 @@ impl TryFrom<libc::pthread_t> for Handle {
fn try_from(thread_id: libc::pthread_t) -> Result<Self, Self::Error> {
let Some(&pthread) = THREADS.read().get(&thread_id) else {
// This is not a valid thread ID
return Err(libc::ESRCH)
return Err(libc::ESRCH);
};

if pthread.is_finished {
Expand Down
4 changes: 3 additions & 1 deletion src/thread/attr.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ impl Default for PThreadAttr {
// Note: we are ignoring the result here, but errors shouldn't occur
// since we're using a valid handle.
let mut priority = 0;
unsafe { ctru_sys::svcGetThreadPriority(&mut priority, ctru_sys::CUR_THREAD_HANDLE) };
unsafe {
let _ = ctru_sys::svcGetThreadPriority(&mut priority, ctru_sys::CUR_THREAD_HANDLE);
}

PThreadAttr {
stack_size: libc::PTHREAD_STACK_MIN,
Expand Down
24 changes: 24 additions & 0 deletions src/thread_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@ fn is_valid_key(key: Key) -> bool {
KEYS.read().contains_key(&(key as Key))
}

pub(crate) fn run_local_destructors() {
unsafe {
// We iterate all the thread-local keys set.
//
// When using `std` and the `thread_local!` macro there should be only one key registered here,
// which is the list of keys to destroy.
for (key, value) in LOCALS.iter() {
// We retrieve the destructor for a key from the static list.
if let Some(destructor) = KEYS.write().get_mut(key) {
// If the destructor is registered for a key, run it.
if let Some(d) = destructor {
// Hold the function pointer.
let dtor = *d;

// Set the destructor as null to avoid reentrancy.
*destructor = None;

dtor(*value);
}
}
}
};
}

#[no_mangle]
pub unsafe extern "C" fn pthread_key_create(
key: *mut libc::pthread_key_t,
Expand Down

0 comments on commit b15d26d

Please sign in to comment.