-
-
Save chunseoklee/87af719b18f460ae62ed6738d410451f to your computer and use it in GitHub Desktop.
Simple C coroutines on AMD64/SysV
This file contains hidden or 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
#pragma once | |
/* Each coroutine is represented by a pointer to its stack bottom. */ | |
typedef void *co_coro; | |
/* The coroutine procedure takes the calling coroutine as its first argument. */ | |
typedef void (*co_proc)(co_coro back); | |
/* Switch to new coroutine. The stack top must be 16 byte aligned.*/ | |
void * | |
co_boot(void *stack_top, co_proc proc); | |
/* Switch to coro. In coro return self. */ | |
void * | |
co_back(co_coro coro); | |
/* Switch to coro. In coro return data. */ | |
void * | |
co_jump(co_coro coro, void *data); |
This file contains hidden or 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
# context %rbp %rbx %r12 %r13 %r14 %r15 | |
# argument order %rdi %rsi %rdx %rcx %r8 %r9 | |
.macro save_ctx | |
push %rbp | |
push %rbx | |
push %r12 | |
push %r13 | |
push %r14 | |
push %r15 | |
.endm | |
.macro load_ctx | |
pop %r15 | |
pop %r14 | |
pop %r13 | |
pop %r12 | |
pop %rbx | |
pop %rbp | |
.endm | |
.text | |
.global co_boot | |
co_boot: | |
save_ctx | |
# switch | |
xchg %rsp, %rdi | |
# enter | |
call *%rsi | |
# if we have no other choice | |
mov $0, %rdi | |
call exit | |
.global co_back | |
co_back: | |
save_ctx | |
# switch | |
mov %rsp, %rax | |
mov %rdi, %rsp | |
load_ctx | |
ret | |
.global co_jump | |
co_jump: | |
save_ctx | |
# switch | |
mov %rsi, %rax | |
mov %rdi, %rsp | |
load_ctx | |
ret | |
# vim: ft=asm |
This file contains hidden or 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
#!/bin/bash -e | |
gcc -m64 -mabi=sysv -Wall -o ping_pong ping_pong.c amd64_sysv_asm.s |
This file contains hidden or 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 <stdlib.h> | |
#include <unistd.h> | |
#include "amd64_sysv.h" | |
static unsigned long ping_stack[128]; | |
static unsigned long pong_stack[128]; | |
static unsigned long rounds = -1; | |
static void * | |
stack_top(void *bot, size_t len) | |
{ | |
return bot + len; | |
} | |
static void | |
ping_proc(co_coro boot) | |
{ | |
co_coro pong; | |
write(1, "ping init\n", 10); | |
pong = co_back(boot); | |
while (rounds-- > 0) { | |
write(1, "ping\n", 5); | |
pong = co_back(pong); | |
} | |
} | |
static void | |
pong_proc(co_coro boot) | |
{ | |
co_coro ping; | |
write(1, "pong init\n", 10); | |
ping = co_back(boot); | |
while (rounds-- > 0) { | |
write(1, "pong\n", 5); | |
ping = co_back(ping); | |
} | |
} | |
int | |
main() | |
{ | |
co_coro ping, pong; | |
ping = co_boot(stack_top(ping_stack, sizeof ping_stack), ping_proc); | |
pong = co_boot(stack_top(pong_stack, sizeof pong_stack), pong_proc); | |
co_jump(ping, pong); | |
exit(EXIT_SUCCESS); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment