|
@@ -0,0 +1,273 @@
|
|
|
+Fix wvstreams so that it builds with uClibc, which does not have the
|
|
|
+getcontext() and setcontext() functions.
|
|
|
+
|
|
|
+Signed-off-by: Simon Dawson <spdawson@gmail.com>
|
|
|
+
|
|
|
+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
|
|
|
+ }
|