Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/libco/sjlj.c
2 views
1
/*
2
libco.sjlj (2008-01-28)
3
author: Nach
4
license: public domain
5
*/
6
7
/*
8
* Note this was designed for UNIX systems. Based on ideas expressed in a paper
9
* by Ralf Engelschall.
10
* For SJLJ on other systems, one would want to rewrite springboard() and
11
* co_create() and hack the jmb_buf stack pointer.
12
*/
13
14
#define LIBCO_C
15
#include "libco.h"
16
#include <stdlib.h>
17
#include <signal.h>
18
#include <setjmp.h>
19
20
#ifdef __cplusplus
21
extern "C" {
22
#endif
23
24
typedef struct {
25
sigjmp_buf context;
26
void (*coentry)(void);
27
void *stack;
28
} cothread_struct;
29
30
static thread_local cothread_struct co_primary;
31
static thread_local cothread_struct *creating, *co_running = 0;
32
33
static void springboard(int ignored) {
34
if(sigsetjmp(creating->context, 0)) {
35
co_running->coentry();
36
}
37
}
38
39
cothread_t co_active() {
40
if(!co_running) co_running = &co_primary;
41
return (cothread_t)co_running;
42
}
43
44
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
45
if(!co_running) co_running = &co_primary;
46
47
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
48
if(thread) {
49
struct sigaction handler;
50
struct sigaction old_handler;
51
52
stack_t stack;
53
stack_t old_stack;
54
55
thread->coentry = thread->stack = 0;
56
57
stack.ss_flags = 0;
58
stack.ss_size = size;
59
thread->stack = stack.ss_sp = malloc(size);
60
if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) {
61
handler.sa_handler = springboard;
62
handler.sa_flags = SA_ONSTACK;
63
sigemptyset(&handler.sa_mask);
64
creating = thread;
65
66
if(!sigaction(SIGUSR1, &handler, &old_handler)) {
67
if(!raise(SIGUSR1)) {
68
thread->coentry = coentry;
69
}
70
sigaltstack(&old_stack, 0);
71
sigaction(SIGUSR1, &old_handler, 0);
72
}
73
}
74
75
if(thread->coentry != coentry) {
76
co_delete(thread);
77
thread = 0;
78
}
79
}
80
81
return (cothread_t)thread;
82
}
83
84
void co_delete(cothread_t cothread) {
85
if(cothread) {
86
if(((cothread_struct*)cothread)->stack) {
87
free(((cothread_struct*)cothread)->stack);
88
}
89
free(cothread);
90
}
91
}
92
93
void co_switch(cothread_t cothread) {
94
if(!sigsetjmp(co_running->context, 0)) {
95
co_running = (cothread_struct*)cothread;
96
siglongjmp(co_running->context, 1);
97
}
98
}
99
100
#ifdef __cplusplus
101
}
102
#endif
103
104