Created
March 26, 2022 12:49
-
-
Save ssrlive/dc8cd2d61bf1e4993f5b75caeeac8959 to your computer and use it in GitHub Desktop.
longjmp usage.
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 <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <setjmp.h> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <time.h> | |
#include "list.h" | |
struct task { | |
jmp_buf env; | |
struct list_head list; | |
}; | |
static LIST_HEAD(tasklist); | |
static void (*tasks[2])(void *); | |
static int ntasks; | |
static jmp_buf sched; | |
static void task_add(struct list_head *tasklist, jmp_buf env) | |
{ | |
struct task *t = malloc(sizeof(*t)); | |
memcpy(t->env, env, sizeof(jmp_buf)); | |
INIT_LIST_HEAD(&t->list); | |
list_add_tail(&t->list, tasklist); | |
} | |
static void task_switch(struct list_head *tasklist) | |
{ | |
jmp_buf env; | |
if (!list_empty(tasklist)) { | |
struct task *t = list_first_entry(tasklist, struct task, list); | |
list_del(&t->list); | |
memcpy(env, t->env, sizeof(jmp_buf)); | |
free(t); | |
longjmp(env, 1); | |
} | |
} | |
static void task_join(struct list_head *tasklist) | |
{ | |
jmp_buf env; | |
while (!list_empty(tasklist)) { | |
struct task *t = list_first_entry(tasklist, struct task, list); | |
list_del(&t->list); | |
memcpy(env, t->env, sizeof(jmp_buf)); | |
free(t); | |
longjmp(env, 1); | |
} | |
} | |
void schedule(void) | |
{ | |
static int i; | |
srand(time(NULL)); | |
setjmp(sched); | |
while (ntasks-- > 0) { | |
int n = rand() % 5; | |
tasks[i++](&n); | |
printf("Never reached\n"); | |
} | |
task_join(&tasklist); | |
} | |
// A task yields control n times | |
void task0(void *arg) | |
{ | |
jmp_buf env; | |
static int n; | |
static int i; | |
n = *(int *)arg; | |
printf("Task 0: n = %d\n", n); | |
if (setjmp(env) == 0) { | |
task_add(&tasklist, env); | |
// Jump back to scheduler | |
longjmp(sched, 1); | |
} | |
for (i = 0; i < n; i++) { | |
if (setjmp(env) == 0) { | |
task_add(&tasklist, env); | |
task_switch(&tasklist); | |
} | |
printf("Task 0: resume\n"); | |
} | |
printf("Task 0: complete\n"); | |
longjmp(sched, 1); | |
} | |
void task1(void *arg) | |
{ | |
jmp_buf env; | |
static int n; | |
static int i; | |
n = *(int *)arg; | |
printf("Task 1: n = %d\n", n); | |
if (setjmp(env) == 0) { | |
task_add(&tasklist, env); | |
// Jump back to scheduler | |
longjmp(sched, 1); | |
} | |
for (i = 0; i < n; i++) { | |
if (setjmp(env) == 0) { | |
task_add(&tasklist, env); | |
task_switch(&tasklist); | |
} | |
printf("Task 1: resume\n"); | |
} | |
printf("Task 1: complete\n"); | |
longjmp(sched, 1); | |
} | |
int main(void) | |
{ | |
tasks[0] = task0; | |
tasks[1] = task1; | |
ntasks = 2; | |
schedule(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment