2 #include "ucontext_stack.h"
\r
4 /* callback: context fetching */
\r
6 xbt_jcontext_ex_ctx(void);
\r
8 /* callback: termination */
\r
10 xbt_jcontext_ex_terminate(xbt_ex_t *e);
\r
12 static xbt_context_t
\r
13 xbt_ucontext_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv);
\r
16 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory);
\r
19 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro);
\r
22 xbt_ucontext_free(xbt_context_t context);
\r
25 xbt_ucontext_kill(xbt_context_t context);
\r
28 xbt_ucontext_schedule(xbt_context_t context);
\r
31 xbt_ucontext_yield(void);
\r
34 xbt_ucontext_start(xbt_context_t context);
\r
37 xbt_ucontext_stop(int exit_code);
\r
40 xbt_ucontext_swap(xbt_context_t context);
\r
43 xbt_ucontext_schedule(xbt_context_t context);
\r
46 xbt_ucontext_yield(void);
\r
49 xbt_ucontext_suspend(xbt_context_t context);
\r
52 xbt_ucontext_resume(xbt_context_t context);
\r
55 xbt_ucontext_wrapper(void* param);
\r
57 /* callback: context fetching */
\r
59 xbt_ucontext_ex_ctx(void)
\r
61 return current_context->exception;
\r
64 /* callback: termination */
\r
66 xbt_ucontext_ex_terminate(xbt_ex_t *e)
\r
74 xbt_ucontext_factory_init(xbt_context_factory_t* factory)
\r
76 /* context exception */
\r
77 *factory = xbt_new0(s_xbt_context_factory_t,1);
\r
79 (*factory)->create_context = xbt_ucontext_factory_create_context;
\r
80 (*factory)->finalize = xbt_ucontext_factory_finalize;
\r
81 (*factory)->create_maestro_context = xbt_ucontext_factory_create_maestro_context;
\r
82 (*factory)->name = "ucontext_context_factory";
\r
84 /* context exception handlers */
\r
85 __xbt_ex_ctx = xbt_ucontext_ex_ctx;
\r
86 __xbt_ex_terminate = xbt_ucontext_ex_terminate;
\r
92 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro)
\r
95 xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);
\r
97 context->exception = xbt_new(ex_ctx_t,1);
\r
98 XBT_CTX_INITIALIZE(context->exception);
\r
100 *maestro = (xbt_context_t)context;
\r
108 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory)
\r
110 free(maestro_context->exception);
\r
116 static xbt_context_t
\r
117 xbt_ucontext_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv)
\r
119 xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);
\r
121 context->code = code;
\r
122 context->name = xbt_strdup(name);
\r
124 xbt_assert2(getcontext(&(context->uc)) == 0,"Error in context saving: %d (%s)", errno, strerror(errno));
\r
125 context->uc.uc_link = NULL;
\r
126 context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, STACK_SIZE);
\r
127 context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, STACK_SIZE);
\r
129 context->exception = xbt_new(ex_ctx_t, 1);
\r
130 XBT_CTX_INITIALIZE(context->exception);
\r
131 context->iwannadie = 0; /* useless but makes valgrind happy */
\r
132 context->argc = argc;
\r
133 context->argv = argv;
\r
134 context->startup_func = startup_func;
\r
135 context->startup_arg = startup_arg;
\r
136 context->cleanup_func = cleanup_func;
\r
137 context->cleanup_arg = cleanup_arg;
\r
140 context->free = xbt_ucontext_free;
\r
141 context->kill = xbt_ucontext_kill;
\r
142 context->schedule = xbt_ucontext_schedule;
\r
143 context->yield = xbt_ucontext_yield;
\r
144 context->start = xbt_ucontext_start;
\r
145 context->stop = xbt_ucontext_stop;
\r
147 return (xbt_context_t)context;
\r
151 xbt_ucontext_free(xbt_context_t context)
\r
155 free(context->name);
\r
161 for(i = 0; i < context->argc; i++)
\r
162 if(context->argv[i])
\r
163 free(context->argv[i]);
\r
165 free(context->argv);
\r
168 if(context->exception)
\r
169 free(context->exception);
\r
171 /* finally destroy the context */
\r
177 xbt_ucontext_kill(xbt_context_t context)
\r
179 context->iwannadie = 1;
\r
180 xbt_ucontext_swap(context);
\r
184 * \param context the winner
\r
186 * Calling this function blocks the current context and schedule \a context.
\r
187 * When \a context will call xbt_context_yield, it will return
\r
188 * to this function as if nothing had happened.
\r
190 * Only the maestro can call this function to run a given process.
\r
193 xbt_ucontext_schedule(xbt_context_t context)
\r
195 xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");
\r
196 xbt_ucontext_swap(context);
\r
200 * Calling this function makes the current context yield. The context
\r
201 * that scheduled it returns from xbt_context_schedule as if nothing
\r
204 * Only the processes can call this function, giving back the control
\r
208 xbt_ucontext_yield(void)
\r
210 xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");
\r
211 xbt_ucontext_swap(current_context);
\r
215 xbt_ucontext_start(xbt_context_t context)
\r
217 makecontext(&(((xbt_ucontext_t)context)->uc), (void (*)(void)) xbt_ucontext_wrapper, 1, context);
\r
221 xbt_ucontext_stop(int exit_code)
\r
223 if(current_context->cleanup_func)
\r
224 ((*current_context->cleanup_func))(current_context->cleanup_arg);
\r
226 xbt_swag_remove(current_context, context_living);
\r
227 xbt_swag_insert(current_context, context_to_destroy);
\r
229 xbt_ucontext_swap(current_context);
\r
233 xbt_ucontext_swap(xbt_context_t context)
\r
235 xbt_assert0(current_context, "You have to call context_init() first.");
\r
236 xbt_assert0(context, "Invalid argument");
\r
238 if(((xbt_ucontext_t)context)->prev == NULL)
\r
239 xbt_ucontext_resume(context);
\r
241 xbt_ucontext_suspend(context);
\r
243 if(current_context->iwannadie)
\r
244 xbt_ucontext_stop(1);
\r
248 xbt_ucontext_wrapper(void* param)
\r
250 if (current_context->startup_func)
\r
251 (*current_context->startup_func)(current_context->startup_arg);
\r
253 xbt_ucontext_stop((*(current_context->code))(current_context->argc, current_context->argv));
\r
258 xbt_ucontext_suspend(xbt_context_t context)
\r
262 xbt_ucontext_t prev_context = ((xbt_ucontext_t)context)->prev;
\r
264 current_context = (xbt_context_t)(((xbt_ucontext_t)context)->prev);
\r
266 ((xbt_ucontext_t)context)->prev = NULL;
\r
268 rv = swapcontext(&(((xbt_ucontext_t)context)->uc), &(prev_context->uc));
\r
270 xbt_assert0((rv == 0), "Context swapping failure");
\r
274 xbt_ucontext_resume(xbt_context_t context)
\r
278 ((xbt_ucontext_t)context)->prev = (xbt_ucontext_t)current_context;
\r
280 current_context = context;
\r
282 rv = swapcontext(&(((xbt_ucontext_t)context)->prev->uc), &(((xbt_ucontext_t)context)->uc));
\r
284 xbt_assert0((rv == 0), "Context swapping failure");
\r