Created
April 17, 2015 12:45
-
-
Save sustrik/b19562329a713970a66c to your computer and use it in GitHub Desktop.
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 <stddef.h> | |
#include <setjmp.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <stdio.h> | |
/******************************************************************************/ | |
/* The "library" */ | |
/******************************************************************************/ | |
#define STACK_SIZE 16384 | |
struct cr_ { | |
struct cr_ *next; | |
jmp_buf ctx; | |
}; | |
struct cr_ main_cr_ = {NULL}; | |
struct cr_ *first_cr_ = &main_cr_; | |
struct cr_ *last_cr_ = &main_cr_; | |
#define set_sp_(ptr) \ | |
volatile int unoptimisable_ = 1;\ | |
int filler1_[unoptimisable_];\ | |
char filler2_[(char*)&filler1_ - (char*)(ptr)]; | |
struct cr_ *go_prologue_(void) { | |
if(setjmp(first_cr_->ctx)) | |
return NULL; | |
char *stack = malloc(STACK_SIZE); | |
assert(stack); | |
struct cr_ *cr = (struct cr_*)(stack + STACK_SIZE - sizeof (struct cr_)); | |
cr->next = first_cr_; | |
first_cr_ = cr; | |
return cr; | |
} | |
void go_epilogue_(void) | |
{ | |
struct cr_ *cr = first_cr_; | |
first_cr_ = cr->next; | |
free(((char*)(cr + 1)) - STACK_SIZE); | |
longjmp(first_cr_->ctx, 1); | |
} | |
#define go(fn) \ | |
{\ | |
struct cr_ *cr = go_prologue_();\ | |
if(cr) {\ | |
set_sp_(cr);\ | |
fn;\ | |
go_epilogue_();\ | |
}\ | |
} | |
void yield(void) { | |
if(first_cr_ == last_cr_) | |
return; | |
if(setjmp(first_cr_->ctx)) | |
return; | |
struct cr_ *cr = first_cr_; | |
first_cr_ = cr->next; | |
cr->next = NULL; | |
last_cr_->next = cr; | |
last_cr_ = cr; | |
longjmp(first_cr_->ctx, 1); | |
} | |
/******************************************************************************/ | |
/* Test program */ | |
/******************************************************************************/ | |
void printer(int count, const char *text) { | |
int i; | |
for(i = 0; i != count; ++i) { | |
printf("%s\n", text); | |
yield(); | |
} | |
} | |
int main() { | |
go(printer(3, "a")); | |
go(printer(2, "b")); | |
printer(5, "c"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment