diff options
author | Twinaphex | 2014-12-09 13:28:17 +0100 |
---|---|---|
committer | Twinaphex | 2014-12-09 13:28:17 +0100 |
commit | 988c2e2655c7c1f724ba727f008d84e3faa6cd24 (patch) | |
tree | da7bf131f33b9ae16d2a93a0a7615a3c0b9c7535 /libco/ucontext.c | |
parent | 7bb77f4fc090cadc23c3e05998ccebac7156e3cf (diff) | |
parent | e2d6ea9082a5ff977f834eda0bbb2362397422df (diff) | |
download | picogpsp-988c2e2655c7c1f724ba727f008d84e3faa6cd24.tar.gz picogpsp-988c2e2655c7c1f724ba727f008d84e3faa6cd24.tar.bz2 picogpsp-988c2e2655c7c1f724ba727f008d84e3faa6cd24.zip |
Merge pull request #2 from aliaspider/master
initial port of gpsp to libretro.
Diffstat (limited to 'libco/ucontext.c')
-rw-r--r-- | libco/ucontext.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/libco/ucontext.c b/libco/ucontext.c new file mode 100644 index 0000000..3e21816 --- /dev/null +++ b/libco/ucontext.c @@ -0,0 +1,81 @@ +/* + libco.ucontext (2008-01-28) + author: Nach + license: public domain +*/ + +/* + * WARNING: the overhead of POSIX ucontext is very high, + * assembly versions of libco or libco_sjlj should be much faster + * + * This library only exists for two reasons: + * 1 - as an initial test for the viability of a ucontext implementation + * 2 - to demonstrate the power and speed of libco over existing implementations, + * such as pth (which defaults to wrapping ucontext on unix targets) + * + * Use this library only as a *last resort* + */ + +#define LIBCO_C +#include <libco.h> +#include <stdlib.h> +#include <ucontext.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local ucontext_t co_primary; +static thread_local ucontext_t *co_running = 0; + +cothread_t co_active(void) +{ + if (!co_running) + co_running = &co_primary; + return (cothread_t)co_running; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) +{ + if (!co_running) + co_running = &co_primary; + ucontext_t *thread = (ucontext_t*)malloc(sizeof(ucontext_t)); + + if(thread) + { + if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) + { + thread->uc_link = co_running; + thread->uc_stack.ss_size = heapsize; + makecontext(thread, coentry, 0); + } + else + { + co_delete((cothread_t)thread); + thread = 0; + } + } + return (cothread_t)thread; +} + +void co_delete(cothread_t cothread) +{ + if (!cothread) + return; + + if(((ucontext_t*)cothread)->uc_stack.ss_sp) + free(((ucontext_t*)cothread)->uc_stack.ss_sp); + free(cothread); +} + +void co_switch(cothread_t cothread) +{ + ucontext_t *old_thread = co_running; + + co_running = (ucontext_t*)cothread; + swapcontext(old_thread, co_running); +} + +#ifdef __cplusplus +} +#endif |