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"
[dependencies] [dependencies]
libc = "0.2.116" 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(
lock: *mut libc::pthread_mutex_t, lock: *mut libc::pthread_mutex_t,
abstime: *const libc::timespec, abstime: *const libc::timespec,
) -> libc::c_int { ) -> 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] #[no_mangle]
@ -399,26 +430,24 @@ pub unsafe extern "C" fn pthread_rwlockattr_destroy(
// THREAD KEYS IMPLEMENTATION FOR RUST STD // THREAD KEYS IMPLEMENTATION FOR RUST STD
use once_cell::sync::Lazy; use spin::rwlock::RwLock;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ptr; use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{PoisonError, RwLock};
type Key = usize; type Key = usize;
type Destructor = unsafe extern "C" fn(*mut libc::c_void); type Destructor = unsafe extern "C" fn(*mut libc::c_void);
static NEXT_KEY: AtomicUsize = AtomicUsize::new(1); 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] #[thread_local]
static mut LOCALS: BTreeMap<Key, *mut libc::c_void> = BTreeMap::new(); static mut LOCALS: BTreeMap<Key, *mut libc::c_void> = BTreeMap::new();
fn is_valid_key(key: Key) -> bool { fn is_valid_key(key: Key) -> bool {
KEYS.read() KEYS.read().contains_key(&(key as Key))
.unwrap_or_else(PoisonError::into_inner)
.contains_key(&(key as Key))
} }
#[no_mangle] #[no_mangle]
@ -427,9 +456,7 @@ pub unsafe extern "C" fn pthread_key_create(
destructor: Option<Destructor>, destructor: Option<Destructor>,
) -> libc::c_int { ) -> libc::c_int {
let new_key = NEXT_KEY.fetch_add(1, Ordering::SeqCst); let new_key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
KEYS.write() KEYS.write().insert(new_key, destructor);
.unwrap_or_else(PoisonError::into_inner)
.insert(new_key, destructor);
*key = new_key as libc::pthread_key_t; *key = new_key as libc::pthread_key_t;
@ -438,11 +465,7 @@ pub unsafe extern "C" fn pthread_key_create(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn pthread_key_delete(key: libc::pthread_key_t) -> libc::c_int { pub unsafe extern "C" fn pthread_key_delete(key: libc::pthread_key_t) -> libc::c_int {
match KEYS match KEYS.write().remove(&(key as Key)) {
.write()
.unwrap_or_else(PoisonError::into_inner)
.remove(&(key as Key))
{
// We had a entry, so it was a valid key. // We had a entry, so it was a valid key.
// It's officially undefined behavior if they use the key after this, // 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 // so don't worry about cleaning up LOCALS, especially since we can't

Loading…
Cancel
Save