#![feature(naked_functions)]
const DEFAULT_STACK_SIZE: usize = 1024 * 1024 * 2;
const MAX_THREADS: usize = 4;
static mut RUNTIME: usize = 0;
#[derive(PartialEq, Eq, Debug)]
#[derive(Debug, Default)]
fn new(id: usize) -> Self {
stack: vec![0_u8; DEFAULT_STACK_SIZE],
ctx: ThreadContext::default(),
let base_thread = Thread {
stack: vec![0_u8; DEFAULT_STACK_SIZE],
ctx: ThreadContext::default(),
let mut threads = vec![base_thread];
let mut available_threads: Vec<Thread> = (1..MAX_THREADS).map(|i| Thread::new(i)).collect();
threads.append(&mut available_threads);
let r_ptr: *const Runtime = self;
RUNTIME = r_ptr as usize;
pub fn run(&mut self) -> ! {
self.threads[self.current].state = State::Available;
fn t_yield(&mut self) -> bool {
let mut pos = self.current;
while self.threads[pos].state != State::Ready {
if pos == self.threads.len() {
if self.threads[self.current].state != State::Available {
self.threads[self.current].state = State::Ready;
self.threads[pos].state = State::Running;
let old_pos = self.current;
let old: *mut ThreadContext = &mut self.threads[old_pos].ctx;
let new: *const ThreadContext = &self.threads[pos].ctx;
asm!("call switch", in("rdi") old, in("rsi") new, clobber_abi("C"));
pub fn spawn(&mut self, f: fn()) {
.find(|t| t.state == State::Available)
.expect("no available thread.");
let size = available.stack.len();
let s_ptr = available.stack.as_mut_ptr().offset(size as isize);
let s_ptr = (s_ptr as usize & !15) as *mut u8;
std::ptr::write(s_ptr.offset(-16) as *mut u64, guard as u64);
std::ptr::write(s_ptr.offset(-24) as *mut u64, skip as u64);
std::ptr::write(s_ptr.offset(-32) as *mut u64, f as u64);
available.ctx.rsp = s_ptr.offset(-32) as u64;
available.state = State::Ready;
unsafe extern "C" fn skip() {
asm!("ret", options(noreturn))
let rt_ptr = RUNTIME as *mut Runtime;
let rt_ptr = RUNTIME as *mut Runtime;
unsafe extern "C" fn switch() {
let mut runtime = Runtime::new();
println!("THREAD 1 STARTING");
println!("thread: {} counter: {}", id, i);
println!("THREAD 1 FINISHED");
println!("THREAD 2 STARTING");
println!("thread: {} counter: {}", id, i);
println!("THREAD 2 FINISHED");