Browse Source

Merge pull request #6 from AzureMarker/fix/tokio

Fix some bugs breaking Tokio
pull/8/head
Meziu 3 years ago committed by GitHub
parent
commit
67bb74bc52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Cargo.toml
  2. 55
      src/lib.rs

2
Cargo.toml

@ -7,4 +7,4 @@ edition = "2021" @@ -7,4 +7,4 @@ edition = "2021"
[dependencies]
libc = "0.2.116"
once_cell = "1.0"
spin = { version = "0.9", default-features = false, features = ["rwlock", "std"] }

55
src/lib.rs

@ -131,9 +131,40 @@ pub unsafe extern "C" fn pthread_cond_timedwait( @@ -131,9 +131,40 @@ pub unsafe extern "C" fn pthread_cond_timedwait(
lock: *mut libc::pthread_mutex_t,
abstime: *const libc::timespec,
) -> libc::c_int {
let nsec: i64 = ((*abstime).tv_sec as i64 * 1_000_000_000) + (*abstime).tv_nsec as i64;
// libctru expects a duration, but we have an absolute timestamp.
// Convert to a duration before calling libctru.
// Get the current time so we can make a duration
let mut now = libc::timeval {
tv_sec: 0,
tv_usec: 0,
};
let r = libc::gettimeofday(&mut now, ptr::null_mut());
if r != 0 {
return r;
}
CondVar_WaitTimeout(cond as _, lock as _, nsec)
// Calculate the duration
let duration_nsec = (*abstime)
.tv_sec
// Get the difference in seconds
.saturating_sub(now.tv_sec)
// Convert to nanoseconds
.saturating_mul(1_000_000_000)
// Add the difference in nanoseconds
.saturating_add((*abstime).tv_nsec as i64)
.saturating_sub(now.tv_usec as i64 * 1_000)
// Don't go negative
.max(0);
let r = CondVar_WaitTimeout(cond as _, lock as _, duration_nsec);
// CondVar_WaitTimeout returns a boolean which is true (nonzero) if it timed out
if r == 0 {
0
} else {
libc::ETIMEDOUT
}
}
#[no_mangle]
@ -399,26 +430,24 @@ pub unsafe extern "C" fn pthread_rwlockattr_destroy( @@ -399,26 +430,24 @@ pub unsafe extern "C" fn pthread_rwlockattr_destroy(
// THREAD KEYS IMPLEMENTATION FOR RUST STD
use once_cell::sync::Lazy;
use spin::rwlock::RwLock;
use std::collections::BTreeMap;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{PoisonError, RwLock};
type Key = usize;
type Destructor = unsafe extern "C" fn(*mut libc::c_void);
static NEXT_KEY: AtomicUsize = AtomicUsize::new(1);
static KEYS: Lazy<RwLock<BTreeMap<Key, Option<Destructor>>>> = Lazy::new(RwLock::default);
// This is a spin-lock RwLock which yields the thread every loop
static KEYS: RwLock<BTreeMap<Key, Option<Destructor>>, spin::Yield> = RwLock::new(BTreeMap::new());
#[thread_local]
static mut LOCALS: BTreeMap<Key, *mut libc::c_void> = BTreeMap::new();
fn is_valid_key(key: Key) -> bool {
KEYS.read()
.unwrap_or_else(PoisonError::into_inner)
.contains_key(&(key as Key))
KEYS.read().contains_key(&(key as Key))
}
#[no_mangle]
@ -427,9 +456,7 @@ pub unsafe extern "C" fn pthread_key_create( @@ -427,9 +456,7 @@ pub unsafe extern "C" fn pthread_key_create(
destructor: Option<Destructor>,
) -> libc::c_int {
let new_key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
KEYS.write()
.unwrap_or_else(PoisonError::into_inner)
.insert(new_key, destructor);
KEYS.write().insert(new_key, destructor);
*key = new_key as libc::pthread_key_t;
@ -438,11 +465,7 @@ pub unsafe extern "C" fn pthread_key_create( @@ -438,11 +465,7 @@ pub unsafe extern "C" fn pthread_key_create(
#[no_mangle]
pub unsafe extern "C" fn pthread_key_delete(key: libc::pthread_key_t) -> libc::c_int {
match KEYS
.write()
.unwrap_or_else(PoisonError::into_inner)
.remove(&(key as Key))
{
match KEYS.write().remove(&(key as Key)) {
// We had a entry, so it was a valid key.
// It's officially undefined behavior if they use the key after this,
// so don't worry about cleaning up LOCALS, especially since we can't

Loading…
Cancel
Save