1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
#[inline(never)]
fn fib(n: usize, stack_limit: *mut u8) -> Option<u64> {
// match psm::StackDirection::new() {
// psm::StackDirection::Ascending => if psm::stack_pointer() > stack_limit {
// return None;
// }
// psm::StackDirection::Descending => if psm::stack_pointer() < stack_limit {
// return None;
// }
// }
match n {
0 => Some(0),
1 => Some(1),
_ => fib(n - 1, stack_limit).and_then(|x| fib(n - 2, stack_limit).map(|y| x + y)),
}
}
const STACK_ALIGN: usize = 4096;
const STACK_REDLINE: usize = 512;
const FIB_COUNTS: [(usize, u64); 3] = [
(8, 21),
(16, 987),
(32, 2178309),
];
fn main() {
let mut stack_size = 1024 * 128;
unsafe {
for &(n, expected) in FIB_COUNTS.iter() {
loop {
println!("fib({}) with {} bytes of stack", n, stack_size - STACK_REDLINE);
let layout = alloc::Layout::from_size_align(stack_size, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let max_stack = match psm::StackDirection::new() {
psm::StackDirection::Ascending =>
new_stack.offset((stack_size - STACK_REDLINE) as isize),
psm::StackDirection::Descending =>
new_stack.offset(STACK_REDLINE as isize),
};
let result = psm::on_stack(new_stack, stack_size, || {
fib(n, max_stack)
});
alloc::dealloc(new_stack, layout);
if let Some(res) = result {
assert_eq!(res, expected);
println!("fib({}) = {}", n, res);
break;
} else {
println!("Stack not large enough!");
stack_size *= 2;
}
}
}
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
main()
}
|