Commit | Line | Data |
---|---|---|
3719602c PC |
1 | /* |
2 | libco.ucontext (2008-01-28) | |
3 | author: Nach | |
4 | license: public domain | |
5 | */ | |
6 | ||
7 | /* | |
8 | * WARNING: the overhead of POSIX ucontext is very high, | |
9 | * assembly versions of libco or libco_sjlj should be much faster | |
10 | * | |
11 | * This library only exists for two reasons: | |
12 | * 1 - as an initial test for the viability of a ucontext implementation | |
13 | * 2 - to demonstrate the power and speed of libco over existing implementations, | |
14 | * such as pth (which defaults to wrapping ucontext on unix targets) | |
15 | * | |
16 | * Use this library only as a *last resort* | |
17 | */ | |
18 | ||
19 | #define LIBCO_C | |
20 | #include <libco.h> | |
21 | #include <stdlib.h> | |
22 | #include <ucontext.h> | |
23 | ||
24 | #ifdef __cplusplus | |
25 | extern "C" { | |
26 | #endif | |
27 | ||
28 | static thread_local ucontext_t co_primary; | |
29 | static thread_local ucontext_t *co_running = 0; | |
30 | ||
31 | cothread_t co_active(void) | |
32 | { | |
33 | if (!co_running) | |
34 | co_running = &co_primary; | |
35 | return (cothread_t)co_running; | |
36 | } | |
37 | ||
38 | cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) | |
39 | { | |
40 | ucontext_t *thread; | |
41 | if (!co_running) | |
42 | co_running = &co_primary; | |
43 | ||
44 | if ((thread = (ucontext_t*)malloc(sizeof(ucontext_t)))) | |
45 | { | |
46 | if ((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) | |
47 | { | |
48 | thread->uc_link = co_running; | |
49 | thread->uc_stack.ss_size = heapsize; | |
50 | makecontext(thread, coentry, 0); | |
51 | } | |
52 | else | |
53 | { | |
54 | co_delete((cothread_t)thread); | |
55 | thread = 0; | |
56 | } | |
57 | } | |
58 | return (cothread_t)thread; | |
59 | } | |
60 | ||
61 | void co_delete(cothread_t cothread) | |
62 | { | |
63 | if (!cothread) | |
64 | return; | |
65 | ||
66 | if (((ucontext_t*)cothread)->uc_stack.ss_sp) | |
67 | free(((ucontext_t*)cothread)->uc_stack.ss_sp); | |
68 | free(cothread); | |
69 | } | |
70 | ||
71 | void co_switch(cothread_t cothread) | |
72 | { | |
73 | ucontext_t *old_thread = co_running; | |
74 | co_running = (ucontext_t*)cothread; | |
75 | swapcontext(old_thread, co_running); | |
76 | } | |
77 | ||
78 | #ifdef __cplusplus | |
79 | } | |
80 | #endif |