Before we start, I want to make sure you understand that the code we write is quite unsafe and is not a “best practice” when writing Rust. I want to try to make this as safe as possible without introducing a lot of unnecessary complexity, but there is no way to avoid the fact that there will be a lot of unsafe code in this example. We will also prioritize focusing on how this works and explain it as simply as possible, which will be enough of a challenge in and of itself, so the focus on best practices and safety will have to take the back seat on this one.
Let’s start off by creating a whole new project called c-fibers and removing the code in main.rs so we start with a blank sheet.
Note
You will also find this example in the repository under the ch05/c-fibers folder. This example, as well as ch05/d-fibers-closure and ch05/e-fibers-windows, needs to be compiled using the nightly compiler since we use an unstable feature. You can do this in one of two ways:
• Override the default toolchain for the entire directory you’re in by writing rustup override set nightly (I personally prefer this option).
• Tell cargo to use the nightly toolchain every time you compile or run the program using cargo +nightly run.
We’ll create a simple runtime with a very simple scheduler. Our fibers will save/restore their state so they can be stopped and resumed at any point during execution. Each fiber will represent a task that we want to progress concurrently, and we simply create a new fiber for each task we want to run.
We start off the example by enabling a specific feature we need, importing the asm macro, and defining a few constants:
ch05/c-fibers/main.rs
#![feature(naked_functions)]
use std::arch::asm;
const DEFAULT_STACK_SIZE: usize = 1024 * 1024 * 2;
const MAX_THREADS: usize = 4;
static mut RUNTIME: usize = 0;
The feature we want to enable is called the naked_functions feature. Let’s explain what a naked function is right away.