Get rid of raw pointers and UnsafeCell in cloudabi condvar.

This commit is contained in:
Mara Bos 2020-10-07 18:17:46 +02:00
parent 41066beb4d
commit 060e8cbaf1
3 changed files with 16 additions and 25 deletions

View File

@ -1,4 +1,3 @@
use crate::cell::UnsafeCell;
use crate::mem; use crate::mem;
use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sync::atomic::{AtomicU32, Ordering};
use crate::sys::cloudabi::abi; use crate::sys::cloudabi::abi;
@ -12,7 +11,7 @@ extern "C" {
} }
pub struct Condvar { pub struct Condvar {
condvar: UnsafeCell<AtomicU32>, condvar: AtomicU32,
} }
pub type MovableCondvar = Condvar; pub type MovableCondvar = Condvar;
@ -20,29 +19,24 @@ pub type MovableCondvar = Condvar;
unsafe impl Send for Condvar {} unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {} unsafe impl Sync for Condvar {}
const NEW: Condvar =
Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
impl Condvar { impl Condvar {
pub const fn new() -> Condvar { pub const fn new() -> Condvar {
NEW Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
} }
pub unsafe fn init(&mut self) {} pub unsafe fn init(&mut self) {}
pub unsafe fn notify_one(&self) { pub unsafe fn notify_one(&self) {
let condvar = self.condvar.get(); if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 { let ret = abi::condvar_signal(&self.condvar as *const AtomicU32 as *mut abi::condvar, abi::scope::PRIVATE, 1);
let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable"); assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
} }
} }
pub unsafe fn notify_all(&self) { pub unsafe fn notify_all(&self) {
let condvar = self.condvar.get(); if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
let ret = abi::condvar_signal( let ret = abi::condvar_signal(
condvar as *mut abi::condvar, &self.condvar as *const AtomicU32 as *mut abi::condvar,
abi::scope::PRIVATE, abi::scope::PRIVATE,
abi::nthreads::MAX, abi::nthreads::MAX,
); );
@ -53,20 +47,19 @@ impl Condvar {
pub unsafe fn wait(&self, mutex: &Mutex) { pub unsafe fn wait(&self, mutex: &Mutex) {
let mutex = mutex::raw(mutex); let mutex = mutex::raw(mutex);
assert_eq!( assert_eq!(
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0, mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This lock is not write-locked by this thread" "This lock is not write-locked by this thread"
); );
// Call into the kernel to wait on the condition variable. // Call into the kernel to wait on the condition variable.
let condvar = self.condvar.get();
let subscription = abi::subscription { let subscription = abi::subscription {
type_: abi::eventtype::CONDVAR, type_: abi::eventtype::CONDVAR,
union: abi::subscription_union { union: abi::subscription_union {
condvar: abi::subscription_condvar { condvar: abi::subscription_condvar {
condvar: condvar as *mut abi::condvar, condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
condvar_scope: abi::scope::PRIVATE, condvar_scope: abi::scope::PRIVATE,
lock: mutex as *mut abi::lock, lock: mutex as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE, lock_scope: abi::scope::PRIVATE,
}, },
}, },
@ -86,13 +79,12 @@ impl Condvar {
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
let mutex = mutex::raw(mutex); let mutex = mutex::raw(mutex);
assert_eq!( assert_eq!(
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0, mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This lock is not write-locked by this thread" "This lock is not write-locked by this thread"
); );
// Call into the kernel to wait on the condition variable. // Call into the kernel to wait on the condition variable.
let condvar = self.condvar.get();
let timeout = let timeout =
checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds"); checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
let subscriptions = [ let subscriptions = [
@ -100,9 +92,9 @@ impl Condvar {
type_: abi::eventtype::CONDVAR, type_: abi::eventtype::CONDVAR,
union: abi::subscription_union { union: abi::subscription_union {
condvar: abi::subscription_condvar { condvar: abi::subscription_condvar {
condvar: condvar as *mut abi::condvar, condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
condvar_scope: abi::scope::PRIVATE, condvar_scope: abi::scope::PRIVATE,
lock: mutex as *mut abi::lock, lock: mutex as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE, lock_scope: abi::scope::PRIVATE,
}, },
}, },
@ -144,9 +136,8 @@ impl Condvar {
} }
pub unsafe fn destroy(&self) { pub unsafe fn destroy(&self) {
let condvar = self.condvar.get();
assert_eq!( assert_eq!(
(*condvar).load(Ordering::Relaxed), self.condvar.load(Ordering::Relaxed),
abi::CONDVAR_HAS_NO_WAITERS.0, abi::CONDVAR_HAS_NO_WAITERS.0,
"Attempted to destroy a condition variable with blocked threads" "Attempted to destroy a condition variable with blocked threads"
); );

View File

@ -17,7 +17,7 @@ pub struct Mutex(RWLock);
pub type MovableMutex = Mutex; pub type MovableMutex = Mutex;
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 { pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
rwlock::raw(&m.0) rwlock::raw(&m.0)
} }

View File

@ -15,8 +15,8 @@ pub struct RWLock {
lock: AtomicU32, lock: AtomicU32,
} }
pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 { pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
&r.lock as *const AtomicU32 as *mut AtomicU32 &r.lock
} }
unsafe impl Send for RWLock {} unsafe impl Send for RWLock {}