2 #include "ucontext_stack.h"
\r
3 #include "xbt/ex_interface.h"
\r
4 #include "xbt/xbt_context_factory.h"
\r
5 #include "xbt/xbt_ucontext.h"
\r
7 /* callback: context fetching */
\r
9 xbt_jcontext_ex_ctx(void);
\r
11 /* callback: termination */
\r
13 xbt_jcontext_ex_terminate(xbt_ex_t *e);
\r
15 static xbt_context_t
\r
16 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
19 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory);
\r
22 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro);
\r
25 xbt_ucontext_free(xbt_context_t context);
\r
28 xbt_ucontext_kill(xbt_context_t context);
\r
31 xbt_ucontext_schedule(xbt_context_t context);
\r
34 xbt_ucontext_yield(void);
\r
37 xbt_ucontext_start(xbt_context_t context);
\r
40 xbt_ucontext_stop(int exit_code);
\r
43 xbt_ucontext_swap(xbt_context_t context);
\r
46 xbt_ucontext_schedule(xbt_context_t context);
\r
49 xbt_ucontext_yield(void);
\r
52 xbt_ucontext_suspend(xbt_context_t context);
\r
55 xbt_ucontext_resume(xbt_context_t context);
\r
58 xbt_ucontext_wrapper(void* param);
\r
60 /* callback: context fetching */
\r
62 xbt_ucontext_ex_ctx(void)
\r
64 return current_context->exception;
\r
67 /* callback: termination */
\r
69 xbt_ucontext_ex_terminate(xbt_ex_t *e)
\r
77 xbt_ucontext_factory_init(xbt_context_factory_t* factory)
\r
79 /* context exception */
\r
80 *factory = xbt_new0(s_xbt_context_factory_t,1);
\r
82 (*factory)->create_context = xbt_ucontext_factory_create_context;
\r
83 (*factory)->finalize = xbt_ucontext_factory_finalize;
\r
84 (*factory)->create_maestro_context = xbt_ucontext_factory_create_maestro_context;
\r
85 (*factory)->name = "ucontext_context_factory";
\r
87 /* context exception handlers */
\r
88 __xbt_ex_ctx = xbt_ucontext_ex_ctx;
\r
89 __xbt_ex_terminate = xbt_ucontext_ex_terminate;
\r
95 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro)
\r
98 xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);
\r
100 context->exception = xbt_new(ex_ctx_t,1);
\r
101 XBT_CTX_INITIALIZE(context->exception);
\r
103 *maestro = (xbt_context_t)context;
\r
111 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory)
\r
113 free(maestro_context->exception);
\r
119 static xbt_context_t
\r
120 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
122 xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);
\r
124 context->code = code;
\r
125 context->name = xbt_strdup(name);
\r
127 xbt_assert2(getcontext(&(context->uc)) == 0,"Error in context saving: %d (%s)", errno, strerror(errno));
\r
128 context->uc.uc_link = NULL;
\r
129 context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, STACK_SIZE);
\r
130 context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, STACK_SIZE);
\r
132 context->exception = xbt_new(ex_ctx_t, 1);
\r
133 XBT_CTX_INITIALIZE(context->exception);
\r
134 context->iwannadie = 0; /* useless but makes valgrind happy */
\r
135 context->argc = argc;
\r
136 context->argv = argv;
\r
137 context->startup_func = startup_func;
\r
138 context->startup_arg = startup_arg;
\r
139 context->cleanup_func = cleanup_func;
\r
140 context->cleanup_arg = cleanup_arg;
\r
143 context->free = xbt_ucontext_free;
\r
144 context->kill = xbt_ucontext_kill;
\r
145 context->schedule = xbt_ucontext_schedule;
\r
146 context->yield = xbt_ucontext_yield;
\r
147 context->start = xbt_ucontext_start;
\r
148 context->stop = xbt_ucontext_stop;
\r
150 return (xbt_context_t)context;
\r
154 xbt_ucontext_free(xbt_context_t context)
\r
158 free(context->name);
\r
164 for(i = 0; i < context->argc; i++)
\r
165 if(context->argv[i])
\r
166 free(context->argv[i]);
\r
168 free(context->argv);
\r
171 if(context->exception)
\r
172 free(context->exception);
\r
174 /* finally destroy the context */
\r
180 xbt_ucontext_kill(xbt_context_t context)
\r
182 context->iwannadie = 1;
\r
183 xbt_ucontext_swap(context);
\r
187 * \param context the winner
\r
189 * Calling this function blocks the current context and schedule \a context.
\r
190 * When \a context will call xbt_context_yield, it will return
\r
191 * to this function as if nothing had happened.
\r
193 * Only the maestro can call this function to run a given process.
\r
196 xbt_ucontext_schedule(xbt_context_t context)
\r
198 xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");
\r
199 xbt_ucontext_swap(context);
\r
203 * Calling this function makes the current context yield. The context
\r
204 * that scheduled it returns from xbt_context_schedule as if nothing
\r
207 * Only the processes can call this function, giving back the control
\r
211 xbt_ucontext_yield(void)
\r
213 xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");
\r
214 xbt_ucontext_swap(current_context);
\r
218 xbt_ucontext_start(xbt_context_t context)
\r
220 makecontext(&(((xbt_ucontext_t)context)->uc), (void (*)(void)) xbt_ucontext_wrapper, 1, context);
\r
224 xbt_ucontext_stop(int exit_code)
\r
226 if(current_context->cleanup_func)
\r
227 ((*current_context->cleanup_func))(current_context->cleanup_arg);
\r
229 xbt_swag_remove(current_context, context_living);
\r
230 xbt_swag_insert(current_context, context_to_destroy);
\r
232 xbt_ucontext_swap(current_context);
\r
236 xbt_ucontext_swap(xbt_context_t context)
\r
238 xbt_assert0(current_context, "You have to call context_init() first.");
\r
239 xbt_assert0(context, "Invalid argument");
\r
241 if(((xbt_ucontext_t)context)->prev == NULL)
\r
242 xbt_ucontext_resume(context);
\r
244 xbt_ucontext_suspend(context);
\r
246 if(current_context->iwannadie)
\r
247 xbt_ucontext_stop(1);
\r
251 xbt_ucontext_wrapper(void* param)
\r
253 if (current_context->startup_func)
\r
254 (*current_context->startup_func)(current_context->startup_arg);
\r
256 xbt_ucontext_stop((*(current_context->code))(current_context->argc, current_context->argv));
\r
261 xbt_ucontext_suspend(xbt_context_t context)
\r
265 xbt_ucontext_t prev_context = ((xbt_ucontext_t)context)->prev;
\r
267 current_context = (xbt_context_t)(((xbt_ucontext_t)context)->prev);
\r
269 ((xbt_ucontext_t)context)->prev = NULL;
\r
271 rv = swapcontext(&(((xbt_ucontext_t)context)->uc), &(prev_context->uc));
\r
273 xbt_assert0((rv == 0), "Context swapping failure");
\r
277 xbt_ucontext_resume(xbt_context_t context)
\r
281 ((xbt_ucontext_t)context)->prev = (xbt_ucontext_t)current_context;
\r
283 current_context = context;
\r
285 rv = swapcontext(&(((xbt_ucontext_t)context)->prev->uc), &(((xbt_ucontext_t)context)->uc));
\r
287 xbt_assert0((rv == 0), "Context swapping failure");
\r