2 libco.sjlj (2008-01-28)
8 * Note this was designed for UNIX systems. Based on ideas expressed in a paper
10 * For SJLJ on other systems, one would want to rewrite springboard() and
11 * co_create() and hack the jmb_buf stack pointer.
27 void (*coentry)(void);
31 static thread_local cothread_struct co_primary;
32 static thread_local cothread_struct *creating, *co_running = 0;
34 static void springboard(int ignored)
36 if (sigsetjmp(creating->context, 0))
37 co_running->coentry();
40 cothread_t co_active(void)
43 co_running = &co_primary;
44 return (cothread_t)co_running;
47 cothread_t co_create(unsigned int size, void (*coentry)(void))
49 cothread_struct *thread;
51 co_running = &co_primary;
53 if ((thread = (cothread_struct*)malloc(sizeof(cothread_struct))))
58 thread->coentry = thread->stack = 0;
62 thread->stack = stack.ss_sp = malloc(size);
64 if (stack.ss_sp && !sigaltstack(&stack, &old_stack))
66 struct sigaction old_handler = {{0}};
67 struct sigaction handler = {{0}};
68 handler.sa_handler = springboard;
69 handler.sa_flags = SA_ONSTACK;
70 sigemptyset(&handler.sa_mask);
73 if (!sigaction(SIGUSR1, &handler, &old_handler))
76 thread->coentry = coentry;
77 sigaltstack(&old_stack, 0);
78 sigaction(SIGUSR1, &old_handler, 0);
82 if (thread->coentry != coentry)
89 return (cothread_t)thread;
92 void co_delete(cothread_t cothread)
96 if (((cothread_struct*)cothread)->stack)
97 free(((cothread_struct*)cothread)->stack);
102 void co_switch(cothread_t cothread)
104 if (!sigsetjmp(co_running->context, 0))
106 co_running = (cothread_struct*)cothread;
107 siglongjmp(co_running->context, 1);