Skip to content

Instantly share code, notes, and snippets.

@jaz303
Created September 13, 2015 16:01
Show Gist options
  • Save jaz303/f39dc365b85d2bb78fa5 to your computer and use it in GitHub Desktop.
Save jaz303/f39dc365b85d2bb78fa5 to your computer and use it in GitHub Desktop.
#define _XOPEN_SOURCE
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
// If I make this 16KiB the program crashes. why?
#define STACK_SIZE (32 * 1024)
void task(int);
typedef void (task_entry_f)(int);
struct task;
struct task {
int id;
ucontext_t ctx;
struct task *prev;
struct task *next;
};
int next_task_id = 1;
struct task *active = 0;
void spawn(task_entry_f fn, int arg) {
struct task *t = malloc(sizeof(struct task));
t->id = next_task_id++;
if (getcontext(&t->ctx) != 0) {
printf("getcontext failed\n");
exit(1);
}
t->ctx.uc_link = 0;
t->ctx.uc_stack.ss_sp = malloc(STACK_SIZE);
t->ctx.uc_stack.ss_size = STACK_SIZE;
t->ctx.uc_stack.ss_flags = 0;
if (t->ctx.uc_stack.ss_sp == 0) {
printf("no stack\n");
exit(1);
}
makecontext(&t->ctx, fn, 1, arg);
if (active == 0) {
t->next = t;
t->prev = t;
active = t;
} else {
t->next = active;
t->prev = active->prev;
active->prev->next = t;
active->prev = t;
}
printf("spawned task %d\n", t->id);
}
void yield() {
struct task *yielder = active;
active = yielder->next;
if (yielder == active) {
return;
}
swapcontext(&yielder->ctx, &active->ctx);
}
void task(int n) {
printf("initialising task %d\n", n);
for (;;) {
printf("hello task %d\n", n);
yield();
}
}
void start() {
printf("starting...\n");
setcontext(&active->ctx);
printf("you will never see this.\n");
}
int main(int argc, char *argv[]) {
spawn(&task, 1);
spawn(&task, 2);
spawn(&task, 3);
spawn(&task, 4);
start();
printf("you will never see me either!\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment