1 Fix wvstreams so that it builds with uClibc, which does not have the
2 getcontext() and setcontext() functions.
4 Signed-off-by: Simon Dawson <spdawson@gmail.com>
6 diff -Nurp a/include/wvtask.h b/include/wvtask.h
7 --- a/include/wvtask.h 2008-07-14 20:11:35.000000000 +0100
8 +++ b/include/wvtask.h 2012-07-28 12:29:53.559981240 +0100
11 #define WVTASK_MAGIC 0x123678
13 +#undef HAVE_GETCONTEXT
14 +#ifdef HAVE_GETCONTEXT
15 +typedef ucontext_t TaskContext;
17 +typedef jmp_buf TaskContext;
22 /** Represents a single thread of control. */
23 @@ -54,8 +61,8 @@ class WvTask
24 bool running, recycled;
27 - ucontext_t mystate; // used for resuming the task
28 - ucontext_t func_call, func_return;
29 + TaskContext mystate; // used for resuming the task
30 + TaskContext func_call, func_return;
34 @@ -94,13 +101,13 @@ class WvTaskMan
35 static void call_func(WvTask *task);
37 static char *stacktop;
38 - static ucontext_t stackmaster_task;
39 + static TaskContext stackmaster_task;
41 static WvTask *stack_target;
42 - static ucontext_t get_stack_return;
43 + static TaskContext get_stack_return;
45 static WvTask *current_task;
46 - static ucontext_t toplevel;
47 + static TaskContext toplevel;
51 diff -Nurp a/utils/wvtask.cc b/utils/wvtask.cc
52 --- a/utils/wvtask.cc 2009-05-13 22:42:52.000000000 +0100
53 +++ b/utils/wvtask.cc 2012-07-28 12:32:23.855974538 +0100
54 @@ -60,12 +60,14 @@ int WvTask::taskcount, WvTask::numtasks,
55 WvTaskMan *WvTaskMan::singleton;
56 int WvTaskMan::links, WvTaskMan::magic_number;
57 WvTaskList WvTaskMan::all_tasks, WvTaskMan::free_tasks;
58 -ucontext_t WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return,
59 +TaskContext WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return,
61 WvTask *WvTaskMan::current_task, *WvTaskMan::stack_target;
62 char *WvTaskMan::stacktop;
64 +#ifdef HAVE_GETCONTEXT
65 static int context_return;
69 static bool use_shared_stack()
70 @@ -198,9 +200,13 @@ WvTaskMan::WvTaskMan()
72 stacktop = (char *)alloca(0);
74 +#ifdef HAVE_GETCONTEXT
76 assert(getcontext(&get_stack_return) == 0);
77 if (context_return == 0)
79 + if (setjmp(get_stack_return) == 0)
82 // initial setup - start the stackmaster() task (never returns!)
84 @@ -257,22 +263,30 @@ int WvTaskMan::run(WvTask &task, int val
86 WvTask *old_task = current_task;
92 state = &toplevel; // top-level call (not in an actual task yet)
94 state = &old_task->mystate;
96 +#ifdef HAVE_GETCONTEXT
98 assert(getcontext(state) == 0);
99 int newval = context_return;
101 + int newval = setjmp(*state);
105 // saved the state, now run the task.
106 +#ifdef HAVE_GETCONTEXT
107 context_return = val;
108 setcontext(&task.mystate);
111 + longjmp(task.mystate, val);
116 @@ -317,16 +331,24 @@ int WvTaskMan::yield(int val)
117 (long)current_task->stacksize);
122 +#ifdef HAVE_GETCONTEXT
124 assert(getcontext(¤t_task->mystate) == 0);
125 int newval = context_return;
127 + int newval = setjmp(current_task->mystate);
131 // saved the task state; now yield to the toplevel.
132 +#ifdef HAVE_GETCONTEXT
133 context_return = val;
134 setcontext(&toplevel);
137 + longjmp(toplevel, val);
142 @@ -340,9 +362,13 @@ int WvTaskMan::yield(int val)
144 void WvTaskMan::get_stack(WvTask &task, size_t size)
146 +#ifdef HAVE_GETCONTEXT
148 assert(getcontext(&get_stack_return) == 0);
149 if (context_return == 0)
151 + if (setjmp(get_stack_return) == 0)
154 assert(magic_number == -WVTASK_MAGIC);
155 assert(task.magic_number == WVTASK_MAGIC);
156 @@ -358,6 +384,7 @@ void WvTaskMan::get_stack(WvTask &task,
157 static char *next_stack_addr = NULL;
160 +#ifndef HAVE_GETCONTEXT
161 task.stack = mmap(next_stack_addr, task.stacksize,
162 PROT_READ | PROT_WRITE,
164 @@ -366,12 +393,17 @@ void WvTaskMan::get_stack(WvTask &task,
168 +#endif // !HAVE_GETCONTEXT
172 stack_target = &task;
173 +#ifdef HAVE_GETCONTEXT
174 context_return = size/1024 + (size%1024 > 0);
175 setcontext(&stackmaster_task);
177 + longjmp(stackmaster_task, size/1024 + (size%1024 > 0));
182 @@ -408,9 +440,13 @@ void WvTaskMan::_stackmaster()
184 assert(magic_number == -WVTASK_MAGIC);
186 +#ifdef HAVE_GETCONTEXT
188 assert(getcontext(&stackmaster_task) == 0);
189 val = context_return;
191 + val = setjmp(stackmaster_task);
195 assert(magic_number == -WVTASK_MAGIC);
196 @@ -418,8 +454,12 @@ void WvTaskMan::_stackmaster()
197 // just did setjmp; save stackmaster's current state (with
198 // all current stack allocations) and go back to get_stack
199 // (or the constructor, if that's what called us)
200 +#ifdef HAVE_GETCONTEXT
202 setcontext(&get_stack_return);
204 + longjmp(get_stack_return, 1);
209 @@ -462,7 +502,9 @@ void WvTaskMan::call_func(WvTask *task)
210 task->func(task->userdata);
211 Dprintf("WvTaskMan: returning from task #%d (%s)\n",
212 task->tid, (const char *)task->name);
213 +#ifdef HAVE_GETCONTEXT
219 @@ -473,9 +515,13 @@ void WvTaskMan::do_task()
220 assert(task->magic_number == WVTASK_MAGIC);
222 // back here from longjmp; someone wants stack space.
223 +#ifdef HAVE_GETCONTEXT
225 assert(getcontext(&task->mystate) == 0);
226 if (context_return == 0)
228 + if (setjmp(task->mystate) == 0)
231 // done the setjmp; that means the target task now has
232 // a working jmp_buf all set up. Leave space on the stack
233 @@ -510,6 +556,7 @@ void WvTaskMan::do_task()
237 +#ifdef HAVE_GETCONTEXT
238 assert(getcontext(&task->func_call) == 0);
239 task->func_call.uc_stack.ss_size = task->stacksize;
240 task->func_call.uc_stack.ss_sp = task->stack;
241 @@ -519,11 +566,19 @@ void WvTaskMan::do_task()
242 task->tid, (const char *)task->name);
243 makecontext(&task->func_call,
244 (void (*)(void))call_func, 1, task);
246 + assert(setjmp(task->func_call) == 0);
249 +#ifdef HAVE_GETCONTEXT
251 assert(getcontext(&task->func_return) == 0);
252 if (context_return == 0)
253 setcontext(&task->func_call);
255 + if (setjmp(task->func_return) == 0)
256 + longjmp(task->func_call, 0);
260 // the task's function terminated.
261 @@ -544,8 +599,12 @@ const void *WvTaskMan::current_top_of_st
262 if (use_shared_stack() || current_task == NULL)
263 return __libc_stack_end;
265 +#ifdef HAVE_GETCONTEXT
266 return (const char *)current_task->stack + current_task->stacksize;