2 #include "xbt/ex_interface.h"
3 #include "xbt/xbt_context_private.h"
5 #include "context_sysv_config.h" /* loads context system definitions */
7 #include <ucontext.h> /* context relative declarations */
8 #define STACK_SIZE 128*1024 /* lower this if you want to reduce the memory consumption */
10 typedef struct s_xbt_ctx_sysv {
12 ucontext_t uc; /* the thread that execute the code */
13 char stack[STACK_SIZE]; /* the thread stack size */
14 struct s_xbt_ctx_sysv *prev; /* the previous thread */
15 } s_xbt_ctx_sysv_t, *xbt_ctx_sysv_t;
18 /* callback: context fetching */
19 static ex_ctx_t *xbt_jcontext_ex_ctx(void);
21 /* callback: termination */
22 static void xbt_jcontext_ex_terminate(xbt_ex_t * e);
25 xbt_ctx_sysv_factory_create_context(const char *name, xbt_main_func_t code,
26 void_f_pvoid_t startup_func,
28 void_f_pvoid_t cleanup_func,
29 void *cleanup_arg, int argc, char **argv);
31 static int xbt_ctx_sysv_factory_finalize(xbt_context_factory_t * factory);
34 xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t * maestro);
36 static void xbt_ctx_sysv_free(xbt_context_t context);
38 static void xbt_ctx_sysv_kill(xbt_context_t context);
40 static void xbt_ctx_sysv_schedule(xbt_context_t context);
42 static void xbt_ctx_sysv_yield(void);
44 static void xbt_ctx_sysv_start(xbt_context_t context);
46 static void xbt_ctx_sysv_stop(int exit_code);
48 static void xbt_ctx_sysv_swap(xbt_context_t context);
50 static void xbt_ctx_sysv_schedule(xbt_context_t context);
52 static void xbt_ctx_sysv_yield(void);
54 static void xbt_ctx_sysv_suspend(xbt_context_t context);
56 static void xbt_ctx_sysv_resume(xbt_context_t context);
58 static void xbt_ctx_sysv_wrapper(void);
60 /* callback: context fetching */
61 static ex_ctx_t *xbt_ctx_sysv_ex_ctx(void)
63 return current_context->exception;
66 /* callback: termination */
67 static void xbt_ctx_sysv_ex_terminate(xbt_ex_t * e)
74 void xbt_ctx_sysv_factory_init(xbt_context_factory_t * factory)
76 /* context exception */
77 *factory = xbt_new0(s_xbt_context_factory_t, 1);
79 (*factory)->create_context = xbt_ctx_sysv_factory_create_context;
80 (*factory)->finalize = xbt_ctx_sysv_factory_finalize;
81 (*factory)->create_maestro_context =
82 xbt_ctx_sysv_factory_create_maestro_context;
83 (*factory)->name = "ctx_sysv_context_factory";
85 /* context exception handlers */
86 __xbt_ex_ctx = xbt_ctx_sysv_ex_ctx;
87 __xbt_ex_terminate = xbt_ctx_sysv_ex_terminate;
91 xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t * maestro)
94 xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1);
96 context->exception = xbt_new(ex_ctx_t, 1);
97 XBT_CTX_INITIALIZE(context->exception);
99 *maestro = (xbt_context_t) context;
106 static int xbt_ctx_sysv_factory_finalize(xbt_context_factory_t * factory)
108 free(maestro_context->exception);
115 xbt_ctx_sysv_factory_create_context(const char *name, xbt_main_func_t code,
116 void_f_pvoid_t startup_func,
118 void_f_pvoid_t cleanup_func,
119 void *cleanup_arg, int argc, char **argv)
121 xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1);
123 context->code = code;
124 context->name = xbt_strdup(name);
126 xbt_assert2(getcontext(&(context->uc)) == 0,
127 "Error in context saving: %d (%s)", errno, strerror(errno));
128 context->uc.uc_link = NULL;
129 context->uc.uc_stack.ss_sp =
130 pth_skaddr_makecontext(context->stack, STACK_SIZE);
131 context->uc.uc_stack.ss_size =
132 pth_sksize_makecontext(context->stack, STACK_SIZE);
134 context->exception = xbt_new(ex_ctx_t, 1);
135 XBT_CTX_INITIALIZE(context->exception);
136 context->iwannadie = 0; /* useless but makes valgrind happy */
137 context->argc = argc;
138 context->argv = argv;
139 context->startup_func = startup_func;
140 context->startup_arg = startup_arg;
141 context->cleanup_func = cleanup_func;
142 context->cleanup_arg = cleanup_arg;
145 context->free = xbt_ctx_sysv_free;
146 context->kill = xbt_ctx_sysv_kill;
147 context->schedule = xbt_ctx_sysv_schedule;
148 context->yield = xbt_ctx_sysv_yield;
149 context->start = xbt_ctx_sysv_start;
150 context->stop = xbt_ctx_sysv_stop;
152 return (xbt_context_t) context;
155 static void xbt_ctx_sysv_free(xbt_context_t context)
163 for (i = 0; i < context->argc; i++)
164 if (context->argv[i])
165 free(context->argv[i]);
170 if (context->exception)
171 free(context->exception);
173 /* finally destroy the context */
178 static void xbt_ctx_sysv_kill(xbt_context_t context)
180 context->iwannadie = 1;
181 xbt_ctx_sysv_swap(context);
185 * \param context the winner
187 * Calling this function blocks the current context and schedule \a context.
188 * When \a context will call xbt_context_yield, it will return
189 * to this function as if nothing had happened.
191 * Only the maestro can call this function to run a given process.
193 static void xbt_ctx_sysv_schedule(xbt_context_t context)
195 xbt_assert0((current_context == maestro_context),
196 "You are not supposed to run this function here!");
197 xbt_ctx_sysv_swap(context);
201 * Calling this function makes the current context yield. The context
202 * that scheduled it returns from xbt_context_schedule as if nothing
205 * Only the processes can call this function, giving back the control
208 static void xbt_ctx_sysv_yield(void)
210 xbt_assert0((current_context != maestro_context),
211 "You are not supposed to run this function here!");
212 xbt_ctx_sysv_swap(current_context);
215 static void xbt_ctx_sysv_start(xbt_context_t context)
217 makecontext(&(((xbt_ctx_sysv_t) context)->uc), xbt_ctx_sysv_wrapper, 0);
220 static void xbt_ctx_sysv_stop(int exit_code)
222 if (current_context->cleanup_func)
223 ((*current_context->cleanup_func)) (current_context->cleanup_arg);
225 xbt_swag_remove(current_context, context_living);
226 xbt_swag_insert(current_context, context_to_destroy);
228 xbt_ctx_sysv_swap(current_context);
231 static void xbt_ctx_sysv_swap(xbt_context_t context)
233 xbt_assert0(current_context, "You have to call context_init() first.");
234 xbt_assert0(context, "Invalid argument");
236 if (((xbt_ctx_sysv_t) context)->prev == NULL)
237 xbt_ctx_sysv_resume(context);
239 xbt_ctx_sysv_suspend(context);
241 if (current_context->iwannadie)
242 xbt_ctx_sysv_stop(1);
245 static void xbt_ctx_sysv_wrapper(void)
247 if (current_context->startup_func)
248 (*current_context->startup_func) (current_context->startup_arg);
250 xbt_ctx_sysv_stop((*(current_context->code))
251 (current_context->argc, current_context->argv));
254 static void xbt_ctx_sysv_suspend(xbt_context_t context)
258 xbt_ctx_sysv_t prev_context = ((xbt_ctx_sysv_t) context)->prev;
260 current_context = (xbt_context_t) (((xbt_ctx_sysv_t) context)->prev);
262 ((xbt_ctx_sysv_t) context)->prev = NULL;
264 rv = swapcontext(&(((xbt_ctx_sysv_t) context)->uc), &(prev_context->uc));
266 xbt_assert0((rv == 0), "Context swapping failure");
269 static void xbt_ctx_sysv_resume(xbt_context_t context)
273 ((xbt_ctx_sysv_t) context)->prev = (xbt_ctx_sysv_t) current_context;
275 current_context = context;
278 swapcontext(&(((xbt_ctx_sysv_t) context)->prev->uc),
279 &(((xbt_ctx_sysv_t) context)->uc));
281 xbt_assert0((rv == 0), "Context swapping failure");