diff --git a/core/src/co_pool/mod.rs b/core/src/co_pool/mod.rs index a0a80eb1..5d2f8b2c 100644 --- a/core/src/co_pool/mod.rs +++ b/core/src/co_pool/mod.rs @@ -70,9 +70,8 @@ impl Drop for CoroutinePool<'_> { self.get_running_size(), "There are still tasks in progress !" ); - assert_eq!( - 0, - self.task_queue.len(), + assert!( + self.task_queue.is_empty(), "There are still tasks to be carried out !" ); } diff --git a/core/src/coroutine/korosensei.rs b/core/src/coroutine/korosensei.rs index 45381406..4743e69e 100644 --- a/core/src/coroutine/korosensei.rs +++ b/core/src/coroutine/korosensei.rs @@ -8,7 +8,7 @@ use crate::coroutine::StackInfo; use corosensei::stack::Stack; use corosensei::trap::TrapHandlerRegs; use corosensei::CoroutineResult; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, UnsafeCell}; use std::collections::VecDeque; use std::ffi::c_longlong; use std::fmt::Debug; @@ -29,7 +29,7 @@ pub struct Coroutine<'c, Param, Yield, Return> { pub(crate) name: String, inner: corosensei::Coroutine, PooledStack>, pub(crate) state: Cell>, - pub(crate) stack_infos: RefCell>, + stack_infos: UnsafeCell>, pub(crate) listeners: VecDeque<&'c dyn Listener>, pub(crate) local: CoroutineLocal<'c>, pub(crate) priority: Option, @@ -291,6 +291,25 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { self.listeners.push_back(listener); } + pub(crate) fn stack_infos_ref(&self) -> &VecDeque { + unsafe { + self.stack_infos + .get() + .as_ref() + .expect("StackInfo not init !") + } + } + + #[allow(clippy::mut_from_ref)] + pub(crate) fn stack_infos_mut(&self) -> &mut VecDeque { + unsafe { + self.stack_infos + .get() + .as_mut() + .expect("StackInfo not init !") + } + } + /// Grows the call stack if necessary. /// /// This function is intended to be called at manually instrumented points in a program where @@ -314,12 +333,12 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { return Ok(callback()); } return stack_pool.allocate(stack_size).map(|stack| { - co.stack_infos.borrow_mut().push_back(StackInfo { + co.stack_infos_mut().push_back(StackInfo { stack_top: stack.base().get(), stack_bottom: stack.limit().get(), }); let r = corosensei::on_stack(stack, callback); - _ = co.stack_infos.borrow_mut().pop_back(); + _ = co.stack_infos_mut().pop_back(); r }); } @@ -380,7 +399,7 @@ where { let stack_size = stack_size.max(crate::common::page_size()); let stack = MemoryPool::get_instance().allocate(stack_size)?; - let stack_infos = RefCell::new(VecDeque::from([StackInfo { + let stack_infos = UnsafeCell::new(VecDeque::from([StackInfo { stack_top: stack.base().get(), stack_bottom: stack.limit().get(), }])); diff --git a/core/src/coroutine/mod.rs b/core/src/coroutine/mod.rs index fcc6abc8..71aa8891 100644 --- a/core/src/coroutine/mod.rs +++ b/core/src/coroutine/mod.rs @@ -107,15 +107,15 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { /// /// This can only be done safely in coroutine. pub unsafe fn remaining_stack(&self) -> usize { - let current_ptr = psm::stack_pointer() as usize; - current_ptr - self.stack_infos.borrow().back().unwrap().stack_bottom + let current_sp = psm::stack_pointer() as usize; + current_sp - self.stack_infos_ref().back().unwrap().stack_bottom } /// Queries the current stack info of this coroutine. /// /// The first used stack index is 0 and increases with usage. pub fn stack_infos(&self) -> VecDeque { - self.stack_infos.borrow().clone() + self.stack_infos_ref().clone() } /// Checks whether the stack pointer at the point where a trap occurred is @@ -126,7 +126,7 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> { /// The result of this function is only meaningful if the coroutine has not /// been dropped yet. pub fn stack_ptr_in_bounds(&self, stack_ptr: u64) -> bool { - for info in self.stack_infos.borrow().iter() { + for info in self.stack_infos_ref() { if info.stack_bottom as u64 <= stack_ptr && stack_ptr < info.stack_top as u64 { return true; } @@ -202,7 +202,7 @@ where f.debug_struct("Coroutine") .field("name", &self.name()) .field("state", &self.state()) - .field("stack_infos", &self.stack_infos) + .field("stack_infos", &self.stack_infos()) .field("local", &self.local) .field("priority", &self.priority) .finish() diff --git a/core/src/coroutine/stack_pool.rs b/core/src/coroutine/stack_pool.rs index a756e0c8..bf6c03de 100644 --- a/core/src/coroutine/stack_pool.rs +++ b/core/src/coroutine/stack_pool.rs @@ -186,7 +186,7 @@ impl MemoryPool { } pub(crate) fn allocate(&self, stack_size: usize) -> std::io::Result { - let heap = unsafe { self.pool.get().as_mut().expect("StackPool is not unique") }; + let heap = unsafe { self.pool.get().as_mut().expect("MemoryPool is not unique") }; // find min stack let mut not_use = Vec::new(); while let Some(stack) = heap.peek() { @@ -265,7 +265,7 @@ impl MemoryPool { /// Clean the expired stack. #[allow(dead_code)] pub(crate) fn clean(&self) { - let heap = unsafe { self.pool.get().as_mut().expect("StackPool is not unique") }; + let heap = unsafe { self.pool.get().as_mut().expect("MemoryPool is not unique") }; let mut maybe_free = Vec::new(); while let Some(stack) = heap.peek() { if Rc::strong_count(&stack.stack) > 1 {