Skip to content

Commit edbbffa

Browse files
committed
add test
1 parent e4ad8ee commit edbbffa

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

core/src/coroutine/korosensei.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,28 @@ impl<'c, Param, Yield, Return> Coroutine<'c, Param, Yield, Return> {
324324
r
325325
});
326326
}
327-
DefaultStack::new(stack_size).map(|stack| corosensei::on_stack(stack, callback))
327+
// in thread
328+
thread_local! {
329+
#[allow(clippy::missing_const_for_thread_local)]
330+
static STACK_INFOS: RefCell<VecDeque<StackInfo>> = const { RefCell::new(VecDeque::new()) };
331+
}
332+
if let Some(last_stack_info) = STACK_INFOS.with(|s| s.borrow().back().copied()) {
333+
let remaining_stack = psm::stack_pointer() as usize - last_stack_info.stack_bottom;
334+
if remaining_stack >= red_zone {
335+
return Ok(callback());
336+
}
337+
}
338+
DefaultStack::new(stack_size).map(|stack| {
339+
STACK_INFOS.with(|s| {
340+
s.borrow_mut().push_back(StackInfo {
341+
stack_top: stack.base().get(),
342+
stack_bottom: stack.limit().get(),
343+
});
344+
});
345+
let r = corosensei::on_stack(stack, callback);
346+
_ = STACK_INFOS.with(|s| s.borrow_mut().pop_back());
347+
r
348+
})
328349
}
329350
}
330351

core/tests/coroutine.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,47 @@ fn coroutine_delay() -> std::io::Result<()> {
7070
Ok(())
7171
}
7272

73+
#[test]
74+
fn sp_in_bounds() -> std::io::Result<()> {
75+
let mut coroutine = co!(|suspender, input| {
76+
let current = Coroutine::<(), (), ()>::current().unwrap();
77+
let stack_info = current.stack_infos().back().cloned().unwrap();
78+
assert!(current.stack_ptr_in_bounds(psm::stack_pointer() as u64));
79+
assert_eq!(
80+
current.stack_ptr_in_bounds(stack_info.stack_top as u64 + 1),
81+
false
82+
);
83+
assert_eq!(
84+
current.stack_ptr_in_bounds(stack_info.stack_bottom as u64 - 1),
85+
false
86+
);
87+
assert_eq!(1, input);
88+
assert_eq!(3, suspender.suspend_with(2));
89+
4
90+
})?;
91+
assert_eq!(CoroutineState::Suspend(2, 0), coroutine.resume_with(1)?);
92+
assert_eq!(CoroutineState::Complete(4), coroutine.resume_with(3)?);
93+
println!("{:?}", coroutine);
94+
println!("{}", coroutine);
95+
Ok(())
96+
}
97+
98+
#[test]
99+
fn thread_stack_growth() {
100+
fn recurse(i: u32, p: &mut [u8; 10240]) {
101+
Coroutine::<(), (), ()>::maybe_grow(|| {
102+
// Ensure the stack allocation isn't optimized away.
103+
unsafe { std::ptr::read_volatile(&p) };
104+
if i > 0 {
105+
recurse(i - 1, &mut [0; 10240]);
106+
}
107+
})
108+
.expect("allocate stack failed")
109+
}
110+
// Use 10MB of stack.
111+
recurse(1000, &mut [0; 10240]);
112+
}
113+
73114
#[test]
74115
fn coroutine_stack_growth() -> std::io::Result<()> {
75116
let mut coroutine = co!(|_: &Suspender<(), ()>, ()| {

0 commit comments

Comments
 (0)