Fix wvstreams so that it builds with uClibc, which does not have the getcontext() and setcontext() functions. Signed-off-by: Simon Dawson diff -Nurp a/include/wvtask.h b/include/wvtask.h --- a/include/wvtask.h 2008-07-14 20:11:35.000000000 +0100 +++ b/include/wvtask.h 2012-07-28 12:29:53.559981240 +0100 @@ -28,6 +28,13 @@ #define WVTASK_MAGIC 0x123678 +#undef HAVE_GETCONTEXT +#ifdef HAVE_GETCONTEXT +typedef ucontext_t TaskContext; +#else +typedef jmp_buf TaskContext; +#endif + class WvTaskMan; /** Represents a single thread of control. */ @@ -54,8 +61,8 @@ class WvTask bool running, recycled; WvTaskMan &man; - ucontext_t mystate; // used for resuming the task - ucontext_t func_call, func_return; + TaskContext mystate; // used for resuming the task + TaskContext func_call, func_return; TaskFunc *func; void *userdata; @@ -94,13 +101,13 @@ class WvTaskMan static void call_func(WvTask *task); static char *stacktop; - static ucontext_t stackmaster_task; + static TaskContext stackmaster_task; static WvTask *stack_target; - static ucontext_t get_stack_return; + static TaskContext get_stack_return; static WvTask *current_task; - static ucontext_t toplevel; + static TaskContext toplevel; WvTaskMan(); virtual ~WvTaskMan(); diff -Nurp a/utils/wvtask.cc b/utils/wvtask.cc --- a/utils/wvtask.cc 2009-05-13 22:42:52.000000000 +0100 +++ b/utils/wvtask.cc 2012-07-28 12:32:23.855974538 +0100 @@ -60,12 +60,14 @@ int WvTask::taskcount, WvTask::numtasks, WvTaskMan *WvTaskMan::singleton; int WvTaskMan::links, WvTaskMan::magic_number; WvTaskList WvTaskMan::all_tasks, WvTaskMan::free_tasks; -ucontext_t WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return, +TaskContext WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return, WvTaskMan::toplevel; WvTask *WvTaskMan::current_task, *WvTaskMan::stack_target; char *WvTaskMan::stacktop; +#ifdef HAVE_GETCONTEXT static int context_return; +#endif static bool use_shared_stack() @@ -198,9 +200,13 @@ WvTaskMan::WvTaskMan() stacktop = (char *)alloca(0); +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(&get_stack_return) == 0); if (context_return == 0) +#else + if (setjmp(get_stack_return) == 0) +#endif { // initial setup - start the stackmaster() task (never returns!) stackmaster(); @@ -257,22 +263,30 @@ int WvTaskMan::run(WvTask &task, int val WvTask *old_task = current_task; current_task = &task; - ucontext_t *state; + TaskContext *state; if (!old_task) state = &toplevel; // top-level call (not in an actual task yet) else state = &old_task->mystate; +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(state) == 0); int newval = context_return; +#else + int newval = setjmp(*state); +#endif if (newval == 0) { // saved the state, now run the task. +#ifdef HAVE_GETCONTEXT context_return = val; setcontext(&task.mystate); return -1; +#else + longjmp(task.mystate, val); +#endif } else { @@ -317,16 +331,24 @@ int WvTaskMan::yield(int val) (long)current_task->stacksize); } #endif - + +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(¤t_task->mystate) == 0); int newval = context_return; +#else + int newval = setjmp(current_task->mystate); +#endif if (newval == 0) { // saved the task state; now yield to the toplevel. +#ifdef HAVE_GETCONTEXT context_return = val; setcontext(&toplevel); return -1; +#else + longjmp(toplevel, val); +#endif } else { @@ -340,9 +362,13 @@ int WvTaskMan::yield(int val) void WvTaskMan::get_stack(WvTask &task, size_t size) { +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(&get_stack_return) == 0); if (context_return == 0) +#else + if (setjmp(get_stack_return) == 0) +#endif { assert(magic_number == -WVTASK_MAGIC); assert(task.magic_number == WVTASK_MAGIC); @@ -358,6 +384,7 @@ void WvTaskMan::get_stack(WvTask &task, static char *next_stack_addr = NULL; #endif +#ifndef HAVE_GETCONTEXT task.stack = mmap(next_stack_addr, task.stacksize, PROT_READ | PROT_WRITE, #ifndef MACOS @@ -366,12 +393,17 @@ void WvTaskMan::get_stack(WvTask &task, MAP_PRIVATE, #endif -1, 0); +#endif // !HAVE_GETCONTEXT } // initial setup stack_target = &task; +#ifdef HAVE_GETCONTEXT context_return = size/1024 + (size%1024 > 0); setcontext(&stackmaster_task); +#else + longjmp(stackmaster_task, size/1024 + (size%1024 > 0)); +#endif } else { @@ -408,9 +440,13 @@ void WvTaskMan::_stackmaster() { assert(magic_number == -WVTASK_MAGIC); +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(&stackmaster_task) == 0); val = context_return; +#else + val = setjmp(stackmaster_task); +#endif if (val == 0) { assert(magic_number == -WVTASK_MAGIC); @@ -418,8 +454,12 @@ void WvTaskMan::_stackmaster() // just did setjmp; save stackmaster's current state (with // all current stack allocations) and go back to get_stack // (or the constructor, if that's what called us) +#ifdef HAVE_GETCONTEXT context_return = 1; setcontext(&get_stack_return); +#else + longjmp(get_stack_return, 1); +#endif } else { @@ -462,7 +502,9 @@ void WvTaskMan::call_func(WvTask *task) task->func(task->userdata); Dprintf("WvTaskMan: returning from task #%d (%s)\n", task->tid, (const char *)task->name); +#ifdef HAVE_GETCONTEXT context_return = 1; +#endif } @@ -473,9 +515,13 @@ void WvTaskMan::do_task() assert(task->magic_number == WVTASK_MAGIC); // back here from longjmp; someone wants stack space. +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(&task->mystate) == 0); if (context_return == 0) +#else + if (setjmp(task->mystate) == 0) +#endif { // done the setjmp; that means the target task now has // a working jmp_buf all set up. Leave space on the stack @@ -510,6 +556,7 @@ void WvTaskMan::do_task() } else { +#ifdef HAVE_GETCONTEXT assert(getcontext(&task->func_call) == 0); task->func_call.uc_stack.ss_size = task->stacksize; task->func_call.uc_stack.ss_sp = task->stack; @@ -519,11 +566,19 @@ void WvTaskMan::do_task() task->tid, (const char *)task->name); makecontext(&task->func_call, (void (*)(void))call_func, 1, task); +#else + assert(setjmp(task->func_call) == 0); +#endif +#ifdef HAVE_GETCONTEXT context_return = 0; assert(getcontext(&task->func_return) == 0); if (context_return == 0) setcontext(&task->func_call); +#else + if (setjmp(task->func_return) == 0) + longjmp(task->func_call, 0); +#endif } // the task's function terminated. @@ -544,8 +599,12 @@ const void *WvTaskMan::current_top_of_st if (use_shared_stack() || current_task == NULL) return __libc_stack_end; else +#ifdef HAVE_GETCONTEXT return (const char *)current_task->stack + current_task->stacksize; #else + return 0; +#endif +#else return 0; #endif }