forked from M-Labs/libfringe
use Void to ensure closure diverges
This commit is contained in:
parent
c83143511e
commit
5411f10460
|
@ -7,6 +7,9 @@ build = "build.rs"
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3.3"
|
gcc = "0.3.3"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
void = "0.0.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["os", "valgrind"]
|
default = ["os", "valgrind"]
|
||||||
os = ["libc"]
|
os = ["libc"]
|
||||||
|
|
|
@ -15,6 +15,7 @@ fn main() {
|
||||||
let mut ctx = Context::new(stack, move || {
|
let mut ctx = Context::new(stack, move || {
|
||||||
println!("it's alive!");
|
println!("it's alive!");
|
||||||
(*ctx_slot).swap();
|
(*ctx_slot).swap();
|
||||||
|
panic!("Do not come back!")
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx_slot = &mut ctx;
|
ctx_slot = &mut ctx;
|
||||||
|
|
|
@ -5,10 +5,13 @@ use core::mem::{size_of, align_of};
|
||||||
use core::cmp::max;
|
use core::cmp::max;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
use void::{self, Void};
|
||||||
|
|
||||||
use super::imp::STACK_ALIGN;
|
use super::imp::STACK_ALIGN;
|
||||||
|
|
||||||
pub unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
|
pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
|
||||||
ptr::read(f)()
|
where F: FnOnce() -> Void {
|
||||||
|
void::unreachable(ptr::read(f)())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
|
pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
|
use void::Void;
|
||||||
|
|
||||||
use stack::Stack;
|
use stack::Stack;
|
||||||
use super::common::{push, rust_trampoline};
|
use super::common::{push, rust_trampoline};
|
||||||
|
|
||||||
|
@ -16,7 +18,8 @@ pub struct Registers {
|
||||||
|
|
||||||
impl Registers {
|
impl Registers {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
|
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers
|
||||||
|
where S: Stack, F: FnOnce() -> Void {
|
||||||
let sp_limit = stack.limit();
|
let sp_limit = stack.limit();
|
||||||
let mut sp = stack.top() as *mut usize;
|
let mut sp = stack.top() as *mut usize;
|
||||||
let f_ptr = push(&mut sp, f);
|
let f_ptr = push(&mut sp, f);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Copyright (c) 2015, edef <edef@edef.eu>
|
// Copyright (c) 2015, edef <edef@edef.eu>
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
use stack::Stack;
|
use stack::Stack;
|
||||||
|
use void::Void;
|
||||||
use super::common::{push, rust_trampoline};
|
use super::common::{push, rust_trampoline};
|
||||||
|
|
||||||
pub const STACK_ALIGN: usize = 16;
|
pub const STACK_ALIGN: usize = 16;
|
||||||
|
@ -14,7 +15,8 @@ pub struct Registers {
|
||||||
|
|
||||||
impl Registers {
|
impl Registers {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
|
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers
|
||||||
|
where S: Stack, F: FnOnce() -> Void {
|
||||||
let sp_limit = stack.limit();
|
let sp_limit = stack.limit();
|
||||||
let mut sp = stack.top() as *mut usize;
|
let mut sp = stack.top() as *mut usize;
|
||||||
let f_ptr = push(&mut sp, f);
|
let f_ptr = push(&mut sp, f);
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
// Copyright (c) 2015, edef <edef@edef.eu>
|
// Copyright (c) 2015, edef <edef@edef.eu>
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use void::Void;
|
||||||
|
|
||||||
use arch::Registers;
|
use arch::Registers;
|
||||||
use stack;
|
use stack;
|
||||||
use debug::StackId;
|
use debug::StackId;
|
||||||
|
@ -27,10 +30,9 @@ unsafe impl<'a, Stack> Send for Context<'a, Stack>
|
||||||
impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
|
impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
|
||||||
/// Create a new Context. When it is swapped into,
|
/// Create a new Context. When it is swapped into,
|
||||||
/// it will call the passed closure.
|
/// it will call the passed closure.
|
||||||
/// The closure shouldn't return - doing that will abort the process.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
|
pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
|
||||||
where F: FnOnce() + Send + 'a {
|
where F: FnOnce() -> Void + Send + 'a {
|
||||||
let stack_id = StackId::register(&mut stack);
|
let stack_id = StackId::register(&mut stack);
|
||||||
let regs = Registers::new(&mut stack, f);
|
let regs = Registers::new(&mut stack, f);
|
||||||
Context {
|
Context {
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
extern crate void;
|
||||||
|
|
||||||
pub use context::Context;
|
pub use context::Context;
|
||||||
pub use stack::Stack;
|
pub use stack::Stack;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue