Skip to content

Instantly share code, notes, and snippets.

@sustrik
Created April 17, 2015 12:45
Show Gist options
  • Save sustrik/b19562329a713970a66c to your computer and use it in GitHub Desktop.
Save sustrik/b19562329a713970a66c to your computer and use it in GitHub Desktop.
#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