0001-fix-uClibc-compile-getcontext.patch 7.57 KB
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(&current_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
 }