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 co_active(void)31cothread_t co_active(void) 32 { 33 if (!co_running) 34 co_running = &co_primary; 35 return (cothread_t)co_running; 36 } 37 co_create(unsigned int heapsize,void (* coentry)(void))38cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) 39 { 40 if (!co_running) 41 co_running = &co_primary; 42 ucontext_t *thread = (ucontext_t*)malloc(sizeof(ucontext_t)); 43 44 if(thread) 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 co_delete(cothread_t cothread)61void 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 co_switch(cothread_t cothread)71void co_switch(cothread_t cothread) 72 { 73 ucontext_t *old_thread = co_running; 74 75 co_running = (ucontext_t*)cothread; 76 swapcontext(old_thread, co_running); 77 } 78 79 #ifdef __cplusplus 80 } 81 #endif 82