0001-fix-uClibc-compile-getcontext.patch 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. Fix wvstreams so that it builds with uClibc, which does not have the
  2. getcontext() and setcontext() functions.
  3. Signed-off-by: Simon Dawson <spdawson@gmail.com>
  4. diff -Nurp a/include/wvtask.h b/include/wvtask.h
  5. --- a/include/wvtask.h 2008-07-14 20:11:35.000000000 +0100
  6. +++ b/include/wvtask.h 2012-07-28 12:29:53.559981240 +0100
  7. @@ -28,6 +28,13 @@
  8. #define WVTASK_MAGIC 0x123678
  9. +#undef HAVE_GETCONTEXT
  10. +#ifdef HAVE_GETCONTEXT
  11. +typedef ucontext_t TaskContext;
  12. +#else
  13. +typedef jmp_buf TaskContext;
  14. +#endif
  15. +
  16. class WvTaskMan;
  17. /** Represents a single thread of control. */
  18. @@ -54,8 +61,8 @@ class WvTask
  19. bool running, recycled;
  20. WvTaskMan &man;
  21. - ucontext_t mystate; // used for resuming the task
  22. - ucontext_t func_call, func_return;
  23. + TaskContext mystate; // used for resuming the task
  24. + TaskContext func_call, func_return;
  25. TaskFunc *func;
  26. void *userdata;
  27. @@ -94,13 +101,13 @@ class WvTaskMan
  28. static void call_func(WvTask *task);
  29. static char *stacktop;
  30. - static ucontext_t stackmaster_task;
  31. + static TaskContext stackmaster_task;
  32. static WvTask *stack_target;
  33. - static ucontext_t get_stack_return;
  34. + static TaskContext get_stack_return;
  35. static WvTask *current_task;
  36. - static ucontext_t toplevel;
  37. + static TaskContext toplevel;
  38. WvTaskMan();
  39. virtual ~WvTaskMan();
  40. diff -Nurp a/utils/wvtask.cc b/utils/wvtask.cc
  41. --- a/utils/wvtask.cc 2009-05-13 22:42:52.000000000 +0100
  42. +++ b/utils/wvtask.cc 2012-07-28 12:32:23.855974538 +0100
  43. @@ -60,12 +60,14 @@ int WvTask::taskcount, WvTask::numtasks,
  44. WvTaskMan *WvTaskMan::singleton;
  45. int WvTaskMan::links, WvTaskMan::magic_number;
  46. WvTaskList WvTaskMan::all_tasks, WvTaskMan::free_tasks;
  47. -ucontext_t WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return,
  48. +TaskContext WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return,
  49. WvTaskMan::toplevel;
  50. WvTask *WvTaskMan::current_task, *WvTaskMan::stack_target;
  51. char *WvTaskMan::stacktop;
  52. +#ifdef HAVE_GETCONTEXT
  53. static int context_return;
  54. +#endif
  55. static bool use_shared_stack()
  56. @@ -198,9 +200,13 @@ WvTaskMan::WvTaskMan()
  57. stacktop = (char *)alloca(0);
  58. +#ifdef HAVE_GETCONTEXT
  59. context_return = 0;
  60. assert(getcontext(&get_stack_return) == 0);
  61. if (context_return == 0)
  62. +#else
  63. + if (setjmp(get_stack_return) == 0)
  64. +#endif
  65. {
  66. // initial setup - start the stackmaster() task (never returns!)
  67. stackmaster();
  68. @@ -257,22 +263,30 @@ int WvTaskMan::run(WvTask &task, int val
  69. WvTask *old_task = current_task;
  70. current_task = &task;
  71. - ucontext_t *state;
  72. + TaskContext *state;
  73. if (!old_task)
  74. state = &toplevel; // top-level call (not in an actual task yet)
  75. else
  76. state = &old_task->mystate;
  77. +#ifdef HAVE_GETCONTEXT
  78. context_return = 0;
  79. assert(getcontext(state) == 0);
  80. int newval = context_return;
  81. +#else
  82. + int newval = setjmp(*state);
  83. +#endif
  84. if (newval == 0)
  85. {
  86. // saved the state, now run the task.
  87. +#ifdef HAVE_GETCONTEXT
  88. context_return = val;
  89. setcontext(&task.mystate);
  90. return -1;
  91. +#else
  92. + longjmp(task.mystate, val);
  93. +#endif
  94. }
  95. else
  96. {
  97. @@ -317,16 +331,24 @@ int WvTaskMan::yield(int val)
  98. (long)current_task->stacksize);
  99. }
  100. #endif
  101. -
  102. +
  103. +#ifdef HAVE_GETCONTEXT
  104. context_return = 0;
  105. assert(getcontext(&current_task->mystate) == 0);
  106. int newval = context_return;
  107. +#else
  108. + int newval = setjmp(current_task->mystate);
  109. +#endif
  110. if (newval == 0)
  111. {
  112. // saved the task state; now yield to the toplevel.
  113. +#ifdef HAVE_GETCONTEXT
  114. context_return = val;
  115. setcontext(&toplevel);
  116. return -1;
  117. +#else
  118. + longjmp(toplevel, val);
  119. +#endif
  120. }
  121. else
  122. {
  123. @@ -340,9 +362,13 @@ int WvTaskMan::yield(int val)
  124. void WvTaskMan::get_stack(WvTask &task, size_t size)
  125. {
  126. +#ifdef HAVE_GETCONTEXT
  127. context_return = 0;
  128. assert(getcontext(&get_stack_return) == 0);
  129. if (context_return == 0)
  130. +#else
  131. + if (setjmp(get_stack_return) == 0)
  132. +#endif
  133. {
  134. assert(magic_number == -WVTASK_MAGIC);
  135. assert(task.magic_number == WVTASK_MAGIC);
  136. @@ -358,6 +384,7 @@ void WvTaskMan::get_stack(WvTask &task,
  137. static char *next_stack_addr = NULL;
  138. #endif
  139. +#ifndef HAVE_GETCONTEXT
  140. task.stack = mmap(next_stack_addr, task.stacksize,
  141. PROT_READ | PROT_WRITE,
  142. #ifndef MACOS
  143. @@ -366,12 +393,17 @@ void WvTaskMan::get_stack(WvTask &task,
  144. MAP_PRIVATE,
  145. #endif
  146. -1, 0);
  147. +#endif // !HAVE_GETCONTEXT
  148. }
  149. // initial setup
  150. stack_target = &task;
  151. +#ifdef HAVE_GETCONTEXT
  152. context_return = size/1024 + (size%1024 > 0);
  153. setcontext(&stackmaster_task);
  154. +#else
  155. + longjmp(stackmaster_task, size/1024 + (size%1024 > 0));
  156. +#endif
  157. }
  158. else
  159. {
  160. @@ -408,9 +440,13 @@ void WvTaskMan::_stackmaster()
  161. {
  162. assert(magic_number == -WVTASK_MAGIC);
  163. +#ifdef HAVE_GETCONTEXT
  164. context_return = 0;
  165. assert(getcontext(&stackmaster_task) == 0);
  166. val = context_return;
  167. +#else
  168. + val = setjmp(stackmaster_task);
  169. +#endif
  170. if (val == 0)
  171. {
  172. assert(magic_number == -WVTASK_MAGIC);
  173. @@ -418,8 +454,12 @@ void WvTaskMan::_stackmaster()
  174. // just did setjmp; save stackmaster's current state (with
  175. // all current stack allocations) and go back to get_stack
  176. // (or the constructor, if that's what called us)
  177. +#ifdef HAVE_GETCONTEXT
  178. context_return = 1;
  179. setcontext(&get_stack_return);
  180. +#else
  181. + longjmp(get_stack_return, 1);
  182. +#endif
  183. }
  184. else
  185. {
  186. @@ -462,7 +502,9 @@ void WvTaskMan::call_func(WvTask *task)
  187. task->func(task->userdata);
  188. Dprintf("WvTaskMan: returning from task #%d (%s)\n",
  189. task->tid, (const char *)task->name);
  190. +#ifdef HAVE_GETCONTEXT
  191. context_return = 1;
  192. +#endif
  193. }
  194. @@ -473,9 +515,13 @@ void WvTaskMan::do_task()
  195. assert(task->magic_number == WVTASK_MAGIC);
  196. // back here from longjmp; someone wants stack space.
  197. +#ifdef HAVE_GETCONTEXT
  198. context_return = 0;
  199. assert(getcontext(&task->mystate) == 0);
  200. if (context_return == 0)
  201. +#else
  202. + if (setjmp(task->mystate) == 0)
  203. +#endif
  204. {
  205. // done the setjmp; that means the target task now has
  206. // a working jmp_buf all set up. Leave space on the stack
  207. @@ -510,6 +556,7 @@ void WvTaskMan::do_task()
  208. }
  209. else
  210. {
  211. +#ifdef HAVE_GETCONTEXT
  212. assert(getcontext(&task->func_call) == 0);
  213. task->func_call.uc_stack.ss_size = task->stacksize;
  214. task->func_call.uc_stack.ss_sp = task->stack;
  215. @@ -519,11 +566,19 @@ void WvTaskMan::do_task()
  216. task->tid, (const char *)task->name);
  217. makecontext(&task->func_call,
  218. (void (*)(void))call_func, 1, task);
  219. +#else
  220. + assert(setjmp(task->func_call) == 0);
  221. +#endif
  222. +#ifdef HAVE_GETCONTEXT
  223. context_return = 0;
  224. assert(getcontext(&task->func_return) == 0);
  225. if (context_return == 0)
  226. setcontext(&task->func_call);
  227. +#else
  228. + if (setjmp(task->func_return) == 0)
  229. + longjmp(task->func_call, 0);
  230. +#endif
  231. }
  232. // the task's function terminated.
  233. @@ -544,8 +599,12 @@ const void *WvTaskMan::current_top_of_st
  234. if (use_shared_stack() || current_task == NULL)
  235. return __libc_stack_end;
  236. else
  237. +#ifdef HAVE_GETCONTEXT
  238. return (const char *)current_task->stack + current_task->stacksize;
  239. #else
  240. + return 0;
  241. +#endif
  242. +#else
  243. return 0;
  244. #endif
  245. }