Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]: Add experimental fibers #42

Draft
wants to merge 33 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
08c4ece
Initial executions draft
zetanumbers Sep 20, 2024
8c29fd0
Implement executions
zetanumbers Sep 23, 2024
09051b5
fix inline asm typo
zetanumbers Sep 23, 2024
8764fbd
Add execution example
zetanumbers Sep 23, 2024
48c1827
Use a single `fiber_switch` function
zetanumbers Sep 25, 2024
f10d21c
fix: `Execution` implementation
zetanumbers Sep 26, 2024
e07f501
change example's strings and names
zetanumbers Sep 26, 2024
5422922
Make execution thread and unwind unsafe
zetanumbers Sep 26, 2024
4b10cd9
docs: Document Execution's constructors
zetanumbers Oct 1, 2024
44f2274
rename `Execution` into a `Fiber`
zetanumbers Oct 2, 2024
064e6d4
Expand fiber's documentation
zetanumbers Oct 3, 2024
74edac1
rename fiber source and example files
zetanumbers Oct 10, 2024
6b9a2dd
rename execution to fiber in the fiber example source code
zetanumbers Oct 10, 2024
4021b9f
Add comments to the code
zetanumbers Oct 10, 2024
8caeddb
declare fiber function ABIs
zetanumbers Oct 10, 2024
8bafe87
Add `Fiber::switch_in_place` method
zetanumbers Oct 22, 2024
eb50d76
Add fiber benchmark
zetanumbers Oct 22, 2024
43cbd29
optimize fiber_switch with inline assembly
zetanumbers Oct 22, 2024
0f0f997
Further optimize fiber_switch
zetanumbers Oct 22, 2024
78a2286
Initial aarch64 implementation
zetanumbers Oct 24, 2024
238eee6
fix aarch64 implementation
zetanumbers Oct 28, 2024
a0cd97f
Add risc-v support
zetanumbers Oct 29, 2024
f59d07c
Copy and modify some coroutine tests for fibers
zetanumbers Nov 2, 2024
98f7da3
Fix fiber backtrace test
zetanumbers Nov 2, 2024
7d4334e
simplify fiber API
zetanumbers Nov 2, 2024
c7aa183
remove RecursiveFiber macro and instead use F shorthand
zetanumbers Nov 7, 2024
d1a1f24
Add support for unwinding from `Fiber::switch` call
zetanumbers Nov 7, 2024
f02216b
Add `fiber_unchecked` constructor
zetanumbers Nov 7, 2024
67da390
remove x28 register clobber copy-paste typo on risc-v
zetanumbers Nov 8, 2024
0c114c2
Fix risc-v segfault bug
zetanumbers Nov 8, 2024
bc26ead
Simplify fiber_switch function declaration
zetanumbers Nov 11, 2024
22b5814
Add from_raw and into_raw methods to Fiber
zetanumbers Dec 4, 2024
eee8403
update fiber documentation
zetanumbers Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
update fiber documentation
  • Loading branch information
zetanumbers committed Dec 5, 2024
commit eee84034bd51e450035709e923dd13d834dd70eb
63 changes: 41 additions & 22 deletions src/fiber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,17 @@ pub struct Fiber<Yield> {
_unwind_unsafe: PhantomData<&'static mut ()>,
}

// TODO: update docs
/// Create a new `Fiber`.
///
/// Create a fiber by using a default-initialized [`DefaultStack`] instance.
/// Create a fiber with default-initialized [`DefaultStack`].
/// After switching to it, it immediately switches back after [`intermediate`](`Fiber::switch`) returns another fiber to switch to.
/// `Return` type can be used to send objects between fibers.
///
/// For more details see [`Fiber::with_stack`].
/// To specify a custom stack and to recover it after fiber's destruction use [`fiber_with_stack`].
///
/// # Unwinding
///
/// In case fiber catches a panic, it aborts current execution (using double-panic).
pub fn fiber<Return>() -> Fiber<(Fiber<Return>, Return)>
where
Return: 'static,
Expand All @@ -49,28 +54,18 @@ where
)
}

// TODO: docs
pub unsafe fn fiber_unchecked(stack_base: StackPointer) -> Fiber<Infallible> {
let sp = unsafe { arch::fiber_init_stack(stack_base) };
Fiber::<Infallible> {
sp,
_arg: PhantomData,
_thread_unsafe: PhantomData,
_unwind_unsafe: PhantomData,
}
}

// TODO: update docs
/// Create a new `Fiber` with some specified `stack`
/// Create a new `Fiber` with custom `stack`.
///
/// Similar to [`fiber`] except for the explicit stack control.
/// After switching to it, it immediately switches back after [`intermediate`](`Fiber::switch`) returns another fiber to switch to.
/// Then `after_exit` is called, from which you can recover and save used stack by storing it into the `Return` object.
/// `Arg` and `Return` types can be used to send objects between fibers, including the used stack.
///
/// Initializes the stack to be ready for the initial switch, but doesn't call the `f` closure argument yet.
/// Closure `f` is expected to return a pair of two objects: an `Fiber` to switch to after `f` returns, and a closure of type `Q` that is run on that `Fiber`'s stack.
/// The `Q` closure converts previously used stack into some payload of type `Return`.
/// It has similar purpose as the input closure of [`Fiber::switch`], see its documentation for more details.
/// If you don't care about managing stacks, see [`fiber`].
///
/// # Unwinding
///
/// If call to `f` ever panics or unwinds then the entire process is aborted.
/// In case fiber catches a panic, it aborts current execution (using double-panic).
pub fn fiber_with_stack<Arg, Return, F, Stack>(
after_exit: F,
stack: Stack,
Expand All @@ -81,7 +76,8 @@ where
Return: 'static,
Stack: stack::Stack + 'static,
{
// SAFETY: TODO
// SAFETY: We never return from the intermediate function and do not reference any of the stack
// variables from outside.
let exec = unsafe { fiber_unchecked(stack.base()) };
// Never return from this as this is the "main" function of any `Fiber`
exec.switch(|execution| {
Expand All @@ -97,6 +93,27 @@ where
})
}

/// Unsafely create a `Fiber`.
///
/// A stronger version of [`fiber`] and [`fiber_with_stack`] constructors.
/// After switching to it, you cannot return from the [`intermediate`](`Fiber::switch`) closure.
/// The only way to get rid of this fiber is to switch to another fiber and drop this one.
///
/// # Safety
///
/// The `stack_base` must be the stack's base pointer, which you can get from `Stack::base`.
/// Used stack can be deallocated or reused only if you ensure fiber's stack variables aren't
/// referenced from somewhere else.
pub unsafe fn fiber_unchecked(stack_base: StackPointer) -> Fiber<Infallible> {
let sp = unsafe { arch::fiber_init_stack(stack_base) };
Fiber::<Infallible> {
sp,
_arg: PhantomData,
_thread_unsafe: PhantomData,
_unwind_unsafe: PhantomData,
}
}

impl<Arg> Fiber<Arg> {
/// Context switch
///
Expand Down Expand Up @@ -205,3 +222,5 @@ impl<Arg> Fiber<Arg> {
}
}
}

// TODO: BorrowingFiber
Loading