Last active
February 28, 2024 08:49
-
-
Save LevitatingBusinessMan/0ac98c5e4d7c4c8d07defd0b296168e1 to your computer and use it in GitHub Desktop.
A totally sane implementation of a coroutine in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#define COROUTINE static long ip = 0; if (ip) asm ("jmp *%0" : : "r" (ip + 7)); | |
#define YIELD_32(i) asm volatile("movl %1, %%eax \n pop %%rbp \n call 1f\n 1: pop %0 \n ret" : "=m" (ip) : "r" (i)); | |
int fibonacci() { | |
COROUTINE | |
YIELD_32(0); | |
YIELD_32(1); | |
YIELD_32(1); | |
YIELD_32(2); | |
YIELD_32(3); | |
YIELD_32(5); | |
YIELD_32(8); | |
YIELD_32(13); | |
YIELD_32(21); | |
YIELD_32(34); | |
} | |
int main(int argc, char** argv) { | |
for (int i = 0; i < 10; i ++) { | |
printf("%d\n", fibonacci()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::arch::asm; | |
use std::ptr::addr_of; | |
macro_rules! coroutine { | |
() => { | |
static mut IP: usize = 0; | |
unsafe { | |
if IP != 0 { | |
asm!( | |
"jmp *%rax", | |
in("rax") IP + 7, | |
options(att_syntax) | |
) | |
} | |
} | |
} | |
} | |
macro_rules! yielt { | |
($e:expr) => { unsafe { asm!( | |
"pop %rbp", | |
"call 1f", | |
"1: popq {}(%rip)", | |
"ret", | |
sym IP, | |
in("rax") $e, | |
options(att_syntax) | |
) } } | |
} | |
unsafe extern fn fibonacci() -> u32 { | |
coroutine!(); | |
yielt!(0); | |
yielt!(1); | |
yielt!(1); | |
yielt!(2); | |
yielt!(3); | |
yielt!(5); | |
yielt!(8); | |
yielt!(13); | |
yielt!(21); | |
yielt!(34); | |
panic!(); | |
} | |
fn main() { | |
for i in 0..10 { | |
unsafe { | |
println!("{}", fibonacci()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment