2 #include "xbt/ex_interface.h"
\r
3 #include "xbt/xbt_context_private.h"
\r
5 #include "context_sysv_config.h" /* loads context system definitions */
\r
6 #include "portable.h"
\r
7 #include <ucontext.h> /* context relative declarations */
\r
8 #define STACK_SIZE 128*1024 /* lower this if you want to reduce the memory consumption */
\r
10 typedef struct s_xbt_ctx_sysv {
\r
12 ucontext_t uc; /* the thread that execute the code */
\r
13 char stack[STACK_SIZE]; /* the thread stack size */
\r
14 struct s_xbt_ctx_sysv* prev;/* the previous thread */
\r
15 } s_xbt_ctx_sysv_t,* xbt_ctx_sysv_t;
\r
18 /* callback: context fetching */
\r
20 xbt_jcontext_ex_ctx(void);
\r
22 /* callback: termination */
\r
24 xbt_jcontext_ex_terminate(xbt_ex_t *e);
\r
26 static xbt_context_t
\r
27 xbt_ctx_sysv_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
30 xbt_ctx_sysv_factory_finalize(xbt_context_factory_t* factory);
\r
33 xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t* maestro);
\r
36 xbt_ctx_sysv_free(xbt_context_t context);
\r
39 xbt_ctx_sysv_kill(xbt_context_t context);
\r
42 xbt_ctx_sysv_schedule(xbt_context_t context);
\r
45 xbt_ctx_sysv_yield(void);
\r
48 xbt_ctx_sysv_start(xbt_context_t context);
\r
51 xbt_ctx_sysv_stop(int exit_code);
\r
54 xbt_ctx_sysv_swap(xbt_context_t context);
\r
57 xbt_ctx_sysv_schedule(xbt_context_t context);
\r
60 xbt_ctx_sysv_yield(void);
\r
63 xbt_ctx_sysv_suspend(xbt_context_t context);
\r
66 xbt_ctx_sysv_resume(xbt_context_t context);
\r
68 static void xbt_ctx_sysv_wrapper(void);
\r
70 /* callback: context fetching */
\r
72 xbt_ctx_sysv_ex_ctx(void)
\r
74 return current_context->exception;
\r
77 /* callback: termination */
\r
79 xbt_ctx_sysv_ex_terminate(xbt_ex_t *e)
\r
87 xbt_ctx_sysv_factory_init(xbt_context_factory_t* factory)
\r
89 /* context exception */
\r
90 *factory = xbt_new0(s_xbt_context_factory_t,1);
\r
92 (*factory)->create_context = xbt_ctx_sysv_factory_create_context;
\r
93 (*factory)->finalize = xbt_ctx_sysv_factory_finalize;
\r
94 (*factory)->create_maestro_context = xbt_ctx_sysv_factory_create_maestro_context;
\r
95 (*factory)->name = "ctx_sysv_context_factory";
\r
97 /* context exception handlers */
\r
98 __xbt_ex_ctx = xbt_ctx_sysv_ex_ctx;
\r
99 __xbt_ex_terminate = xbt_ctx_sysv_ex_terminate;
\r
103 xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t* maestro)
\r
106 xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1);
\r
108 context->exception = xbt_new(ex_ctx_t,1);
\r
109 XBT_CTX_INITIALIZE(context->exception);
\r
111 *maestro = (xbt_context_t)context;
\r
119 xbt_ctx_sysv_factory_finalize(xbt_context_factory_t* factory)
\r
121 free(maestro_context->exception);
\r
127 static xbt_context_t
\r
128 xbt_ctx_sysv_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
130 xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1);
\r
132 context->code = code;
\r
133 context->name = xbt_strdup(name);
\r
135 xbt_assert2(getcontext(&(context->uc)) == 0,"Error in context saving: %d (%s)", errno, strerror(errno));
\r
136 context->uc.uc_link = NULL;
\r
137 context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, STACK_SIZE);
\r
138 context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, STACK_SIZE);
\r
140 context->exception = xbt_new(ex_ctx_t, 1);
\r
141 XBT_CTX_INITIALIZE(context->exception);
\r
142 context->iwannadie = 0; /* useless but makes valgrind happy */
\r
143 context->argc = argc;
\r
144 context->argv = argv;
\r
145 context->startup_func = startup_func;
\r
146 context->startup_arg = startup_arg;
\r
147 context->cleanup_func = cleanup_func;
\r
148 context->cleanup_arg = cleanup_arg;
\r
151 context->free = xbt_ctx_sysv_free;
\r
152 context->kill = xbt_ctx_sysv_kill;
\r
153 context->schedule = xbt_ctx_sysv_schedule;
\r
154 context->yield = xbt_ctx_sysv_yield;
\r
155 context->start = xbt_ctx_sysv_start;
\r
156 context->stop = xbt_ctx_sysv_stop;
\r
158 return (xbt_context_t)context;
\r
162 xbt_ctx_sysv_free(xbt_context_t context)
\r
166 free(context->name);
\r
172 for(i = 0; i < context->argc; i++)
\r
173 if(context->argv[i])
\r
174 free(context->argv[i]);
\r
176 free(context->argv);
\r
179 if(context->exception)
\r
180 free(context->exception);
\r
182 /* finally destroy the context */
\r
188 xbt_ctx_sysv_kill(xbt_context_t context)
\r
190 context->iwannadie = 1;
\r
191 xbt_ctx_sysv_swap(context);
\r
195 * \param context the winner
\r
197 * Calling this function blocks the current context and schedule \a context.
\r
198 * When \a context will call xbt_context_yield, it will return
\r
199 * to this function as if nothing had happened.
\r
201 * Only the maestro can call this function to run a given process.
\r
204 xbt_ctx_sysv_schedule(xbt_context_t context)
\r
206 xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");
\r
207 xbt_ctx_sysv_swap(context);
\r
211 * Calling this function makes the current context yield. The context
\r
212 * that scheduled it returns from xbt_context_schedule as if nothing
\r
215 * Only the processes can call this function, giving back the control
\r
219 xbt_ctx_sysv_yield(void)
\r
221 xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");
\r
222 xbt_ctx_sysv_swap(current_context);
\r
226 xbt_ctx_sysv_start(xbt_context_t context)
\r
228 makecontext(&(((xbt_ctx_sysv_t)context)->uc), xbt_ctx_sysv_wrapper, 0);
\r
232 xbt_ctx_sysv_stop(int exit_code)
\r
234 if(current_context->cleanup_func)
\r
235 ((*current_context->cleanup_func))(current_context->cleanup_arg);
\r
237 xbt_swag_remove(current_context, context_living);
\r
238 xbt_swag_insert(current_context, context_to_destroy);
\r
240 xbt_ctx_sysv_swap(current_context);
\r
244 xbt_ctx_sysv_swap(xbt_context_t context)
\r
246 xbt_assert0(current_context, "You have to call context_init() first.");
\r
247 xbt_assert0(context, "Invalid argument");
\r
249 if(((xbt_ctx_sysv_t)context)->prev == NULL)
\r
250 xbt_ctx_sysv_resume(context);
\r
252 xbt_ctx_sysv_suspend(context);
\r
254 if(current_context->iwannadie)
\r
255 xbt_ctx_sysv_stop(1);
\r
259 xbt_ctx_sysv_wrapper(void)
\r
261 if (current_context->startup_func)
\r
262 (*current_context->startup_func)(current_context->startup_arg);
\r
264 xbt_ctx_sysv_stop((*(current_context->code))(current_context->argc, current_context->argv));
\r
268 xbt_ctx_sysv_suspend(xbt_context_t context)
\r
272 xbt_ctx_sysv_t prev_context = ((xbt_ctx_sysv_t)context)->prev;
\r
274 current_context = (xbt_context_t)(((xbt_ctx_sysv_t)context)->prev);
\r
276 ((xbt_ctx_sysv_t)context)->prev = NULL;
\r
278 rv = swapcontext(&(((xbt_ctx_sysv_t)context)->uc), &(prev_context->uc));
\r
280 xbt_assert0((rv == 0), "Context swapping failure");
\r
284 xbt_ctx_sysv_resume(xbt_context_t context)
\r
288 ((xbt_ctx_sysv_t)context)->prev = (xbt_ctx_sysv_t)current_context;
\r
290 current_context = context;
\r
292 rv = swapcontext(&(((xbt_ctx_sysv_t)context)->prev->uc), &(((xbt_ctx_sysv_t)context)->uc));
\r
294 xbt_assert0((rv == 0), "Context swapping failure");
\r