summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ecore/Ecore_Common.h21
-rw-r--r--src/lib/ecore/ecore.c2
-rw-r--r--src/lib/ecore/ecore_coroutine.c347
3 files changed, 0 insertions, 370 deletions
diff --git a/src/lib/ecore/Ecore_Common.h b/src/lib/ecore/Ecore_Common.h
index eceb4ed34e..5536d22cd4 100644
--- a/src/lib/ecore/Ecore_Common.h
+++ b/src/lib/ecore/Ecore_Common.h
@@ -2216,27 +2216,6 @@ typedef Eo Ecore_Job; /**< A job handle */
2216 * @} 2216 * @}
2217 */ 2217 */
2218 2218
2219typedef struct _Ecore_Coroutine Ecore_Coroutine;
2220typedef int (*Ecore_Coroutine_Cb)(void *data, Ecore_Coroutine *coro);
2221
2222typedef enum {
2223 ECORE_COROUTINE_NEW,
2224 ECORE_COROUTINE_RUNNING,
2225 ECORE_COROUTINE_FINISHED
2226} Ecore_Coroutine_State;
2227
2228EAPI Ecore_Coroutine *ecore_coroutine_add(int stack_size, Ecore_Coroutine_Cb func, void *data);
2229EAPI void *ecore_coroutine_del(Ecore_Coroutine *coro);
2230
2231EAPI int ecore_coroutine_resume(Ecore_Coroutine *coro);
2232EAPI void ecore_coroutine_yield(Ecore_Coroutine *coro, int value);
2233
2234EAPI void *ecore_coroutine_data_get(Ecore_Coroutine *coro);
2235EAPI Ecore_Coroutine_State ecore_coroutine_state_get(Ecore_Coroutine *coro);
2236
2237EAPI void ecore_coroutine_defer(Ecore_Coroutine *coro, Eina_Free_Cb func, void *data);
2238EAPI void *ecore_coroutine_alloc(Ecore_Coroutine *coro, size_t size);
2239
2240#ifdef __cplusplus 2219#ifdef __cplusplus
2241} 2220}
2242#endif 2221#endif
diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c
index d0e98ad895..bbe51babf5 100644
--- a/src/lib/ecore/ecore.c
+++ b/src/lib/ecore/ecore.c
@@ -272,7 +272,6 @@ ecore_init(void)
272 _ecore_glib_init(); 272 _ecore_glib_init();
273 _ecore_job_init(); 273 _ecore_job_init();
274 _ecore_time_init(); 274 _ecore_time_init();
275 _ecore_coroutine_init();
276 275
277 eina_lock_new(&_thread_mutex); 276 eina_lock_new(&_thread_mutex);
278 eina_condition_new(&_thread_cond, &_thread_mutex); 277 eina_condition_new(&_thread_cond, &_thread_mutex);
@@ -385,7 +384,6 @@ ecore_shutdown(void)
385#endif 384#endif
386 385
387 if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); 386 if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
388 _ecore_coroutine_shutdown();
389 _ecore_poller_shutdown(); 387 _ecore_poller_shutdown();
390 _ecore_animator_shutdown(); 388 _ecore_animator_shutdown();
391 _ecore_glib_shutdown(); 389 _ecore_glib_shutdown();
diff --git a/src/lib/ecore/ecore_coroutine.c b/src/lib/ecore/ecore_coroutine.c
deleted file mode 100644
index 07a277a3af..0000000000
--- a/src/lib/ecore/ecore_coroutine.c
+++ /dev/null
@@ -1,347 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <sys/time.h>
7#include <assert.h>
8#include <sys/types.h>
9#include <unistd.h>
10
11#if defined(USE_UCONTEXT)
12# include <sys/time.h>
13# include <sys/resource.h>
14# include <ucontext.h>
15#elif defined(USE_SETJMP)
16# include <sys/time.h>
17# if HAVE_SYS_RESOURCE_H
18# include <sys/resource.h>
19# endif
20# include <setjmp.h>
21#endif
22
23#ifdef HAVE_EVIL
24# include <Evil.h>
25#endif
26
27#ifdef _WIN32
28# define USE_FIBERS
29# undef USE_UCONTEXT
30# undef USE_SETJMP
31#endif
32
33#include "Ecore.h"
34#include "ecore_private.h"
35
36typedef struct _Ecore_Coroutine_Defer Ecore_Coroutine_Defer;
37struct _Ecore_Coroutine_Defer
38{
39 Eina_Free_Cb func;
40 void *data;
41};
42
43struct _Ecore_Coroutine
44{
45#if defined(USE_FIBERS)
46 void *context;
47#elif defined(USE_UCONTEXT)
48 ucontext_t context;
49#elif defined(USE_SETJMP)
50 jmp_buf context;
51#else
52# error "No coroutine implementation !"
53#endif
54
55 Eina_Inarray defer;
56
57 Ecore_Coroutine_Cb func;
58 void *data;
59
60 Ecore_Coroutine_State state;
61
62#ifdef USE_VALGRIND
63 int vg_stack_id;
64#endif
65 int yield_value;
66
67 unsigned char stack[1];
68};
69
70#ifdef __x86_64__
71static const int _ecore_coroutine_default_stack_size = 16 * 1024;
72#else
73static const int _ecore_coroutine_default_stack_size = 12 * 1024;
74#endif
75
76static void
77_ecore_coroutine_finish(Ecore_Coroutine *coro)
78{
79 int return_value = coro->func(coro->data, coro);
80
81 coro->state = ECORE_COROUTINE_FINISHED;
82 ecore_coroutine_yield(coro, return_value);
83}
84
85#if defined(USE_UCONTEXT)
86# ifdef __x86_64__
87union ptr_splitter {
88 void *ptr;
89 uint32_t part[sizeof(void *) / sizeof(uint32_t)];
90};
91
92static void
93_ecore_coroutine_entry_point(uint32_t part0, uint32_t part1)
94{
95 union ptr_splitter p = {
96 .part = { part0, part1 }
97 };
98 Ecore_Coroutine *coro = p.ptr;
99
100 _ecore_coroutine_finish(coro);
101}
102# else
103static void
104_ecore_coroutine_entry_point(Ecore_Coroutine *coro)
105{
106 _ecore_coroutine_finish(coro);
107}
108# endif
109#else
110static void
111_ecore_coroutine_entry_point(Ecore_Coroutine *coro)
112{
113 _ecore_coroutine_finish(coro);
114}
115# if defined(USE_SETJMP)
116static void
117_ecore_coroutine_setjmp(Ecore_Coroutine *coro)
118{
119 setjmp(coro->context);
120
121 /* The idea of this trick come from libcoroutine */
122 /* __jmpbuf[6] == stack pointer */
123 /* __jmpbuf[7] == program counter */
124 coro->context->env[0].__jmpbuf[6] = ((uintptr_t)(&coro->stack));
125 coro->context->env[0].__jmpbuf[7] = ((uintptr_t)_ecore_coroutine_entry_point);
126}
127# endif
128#endif
129
130#if defined(USE_FIBERS)
131static void *caller;
132#elif defined(USE_UCONTEXT)
133static ucontext_t caller;
134static ucontext_t callee;
135#elif defined(USE_SETJMP)
136static jmp_buf caller;
137static jmp_buf callee;
138#endif
139
140void
141_ecore_coroutine_init(void)
142{
143#if defined(USE_FIBERS)
144 caller = GetCurrentFiber();
145 if (caller == (LPVOID) 0x1e00)
146 {
147 caller = ConvertThreadToFiber(NULL);
148 }
149#else
150 memset(&caller, 0, sizeof (caller));
151 memset(&callee, 0, sizeof (callee));
152#endif
153}
154
155void
156_ecore_coroutine_shutdown(void)
157{
158#ifdef USE_FIBERS
159 ConvertFiberToThread();
160#endif
161
162 // FIXME: should we track lost coroutine ?
163}
164
165EAPI Ecore_Coroutine *
166ecore_coroutine_add(int stack_size, Ecore_Coroutine_Cb func, void *data)
167{
168 Ecore_Coroutine *coro;
169#ifndef USE_FIBERS
170 unsigned char *stack;
171#endif
172
173 if (stack_size <= 0)
174 {
175#if defined(USE_UCONTEXT) || defined(USE_SETJMP)
176 struct rlimit check;
177
178 if (getrlimit(RLIMIT_STACK, &check))
179 check.rlim_cur = _ecore_coroutine_default_stack_size;
180 stack_size = check.rlim_cur;
181#elif defined(USE_FIBERS)
182 stack_size = _ecore_coroutine_default_stack_size;
183#endif
184 if (stack_size < _ecore_coroutine_default_stack_size)
185 stack_size = _ecore_coroutine_default_stack_size;
186 }
187
188 coro = malloc(sizeof (Ecore_Coroutine) + stack_size - 1);
189 if (!coro) return NULL;
190
191#ifndef USE_FIBERS
192 stack = coro->stack;
193#endif
194
195#ifdef USE_VALGRIND
196 coro->vg_stack_id = VALGRIND_STACK_REGISTER(stack, stack + stack_size);
197#endif
198
199 coro->state = ECORE_COROUTINE_NEW;
200 coro->func = func;
201 coro->data = data;
202 eina_inarray_step_set(&coro->defer,
203 sizeof (Eina_Inarray), sizeof (Ecore_Coroutine_Defer),
204 8);
205
206#if defined(USE_UCONTEXT)
207 getcontext(&coro->context);
208
209 coro->context.uc_stack.ss_sp = stack;
210 coro->context.uc_stack.ss_size = stack_size;
211 coro->context.uc_stack.ss_flags = 0;
212 coro->context.uc_link = NULL;
213
214# ifdef __x86_64__
215 union ptr_splitter p = { .ptr = coro };
216 makecontext(&coro->context, (void (*)())_ecore_coroutine_entry_point,
217 2, p.part[0], p.part[1]);
218# else
219 makecontext(&coro->context, (void (*)())_ecore_coroutine_entry_point,
220 1, coro);
221# endif
222#elif defined(USE_FIBERS)
223 coro->context = CreateFiber(stack_size,
224 (LPFIBER_START_ROUTINE)_ecore_coroutine_entry_point,
225 coro);
226 if (!coro->context)
227 {
228 free(coro);
229 return NULL;
230 }
231#elif defined(USE_SETJMP)
232 /* We use an intermediate function call to setup the stack with the right arguments */
233 _ecore_coroutine_setjmp(coro);
234#endif
235
236 return coro;
237}
238
239EAPI void *
240ecore_coroutine_del(Ecore_Coroutine *coro)
241{
242 void *data;
243
244 data = coro->data;
245
246 while (eina_inarray_count(&coro->defer))
247 {
248 Ecore_Coroutine_Defer *defer;
249
250 defer = eina_inarray_pop(&coro->defer);
251 defer->func(defer->data);
252 }
253 eina_inarray_flush(&coro->defer);
254
255#ifdef USE_VALGRIND
256 VALGRIND_STACK_DEREGISTER(coro->vg_stack_id);
257#endif
258
259#ifdef USE_FIBERS
260 DeleteFiber(coro->context);
261#endif
262
263 free(coro);
264 return data;
265}
266
267EAPI int
268ecore_coroutine_resume(Ecore_Coroutine *coro)
269{
270#if defined(USE_FIBERS)
271 void *prev_caller;
272#elif defined(USE_UCONTEXT)
273 ucontext_t prev_caller;
274#elif defined(USE_SETJMP)
275 jmp_buf prev_caller;
276#endif
277
278 if (coro->state == ECORE_COROUTINE_FINISHED)
279 return 0;
280 coro->state = ECORE_COROUTINE_RUNNING;
281
282 prev_caller = caller;
283#if defined(USE_FIBERS)
284 SwitchToFiber(coro->context);
285#elif defined(USE_UCONTEXT)
286 swapcontext(&caller, &coro->context);
287#elif defined(USE_SETJMP)
288 setjmp(caller);
289 longjmp(coro->context);
290#endif
291#ifndef USE_FIBERS
292 // As fiber do handle the callee stack for us, no need here
293 coro->context = callee;
294#endif
295 caller = prev_caller;
296
297 return coro->yield_value;
298}
299
300EAPI void
301ecore_coroutine_yield(Ecore_Coroutine *coro, int value)
302{
303 coro->yield_value = value;
304#if defined(USE_FIBERS)
305 SwitchToFiber(caller);
306#elif defined(USE_UCONTEXT)
307 swapcontext(&callee, &caller);
308#elif defined(USE_SETJMP)
309 setjmp(callee);
310 longjmp(caller);
311#endif
312}
313
314EAPI void *
315ecore_coroutine_data_get(Ecore_Coroutine *coro)
316{
317 return coro->data;
318}
319
320EAPI Ecore_Coroutine_State
321ecore_coroutine_state_get(Ecore_Coroutine *coro)
322{
323 return coro->state;
324}
325
326EAPI void
327ecore_coroutine_defer(Ecore_Coroutine *coro, Eina_Free_Cb func, void *data)
328{
329 Ecore_Coroutine_Defer *defer;
330
331 defer = eina_inarray_grow(&coro->defer, 1);
332 if (!defer) return;
333 defer->func = func;
334 defer->data = data;
335}
336
337EAPI void *
338ecore_coroutine_alloc(Ecore_Coroutine *coro, size_t size)
339{
340 void *data;
341
342 data = malloc(size);
343 ecore_coroutine_defer(coro, free, data);
344 return data;
345}
346
347