Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ooops, forgot to change this one
[simgrid.git] / src / xbt / xbt_ucontext.c
1 \r
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
6 \r
7 /* callback: context fetching */\r
8 static ex_ctx_t*\r
9 xbt_jcontext_ex_ctx(void);\r
10 \r
11 /* callback: termination */\r
12 static void \r
13 xbt_jcontext_ex_terminate(xbt_ex_t *e);\r
14 \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
17 \r
18 static int\r
19 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory);\r
20 \r
21 static int \r
22 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro);\r
23 \r
24 static void \r
25 xbt_ucontext_free(xbt_context_t context);\r
26 \r
27 static void \r
28 xbt_ucontext_kill(xbt_context_t context);\r
29 \r
30 static void \r
31 xbt_ucontext_schedule(xbt_context_t context);\r
32 \r
33 static void \r
34 xbt_ucontext_yield(void);\r
35 \r
36 static void \r
37 xbt_ucontext_start(xbt_context_t context);\r
38 \r
39 static void \r
40 xbt_ucontext_stop(int exit_code);\r
41 \r
42 static void \r
43 xbt_ucontext_swap(xbt_context_t context);\r
44 \r
45 static void\r
46 xbt_ucontext_schedule(xbt_context_t context);\r
47 \r
48 static void\r
49 xbt_ucontext_yield(void);\r
50 \r
51 static void\r
52 xbt_ucontext_suspend(xbt_context_t context);\r
53 \r
54 static void\r
55 xbt_ucontext_resume(xbt_context_t context);\r
56 \r
57 static void* \r
58 xbt_ucontext_wrapper(void* param);\r
59 \r
60 /* callback: context fetching */\r
61 static ex_ctx_t*\r
62 xbt_ucontext_ex_ctx(void) \r
63 {\r
64         return current_context->exception;\r
65 }\r
66 \r
67 /* callback: termination */\r
68 static void \r
69 xbt_ucontext_ex_terminate(xbt_ex_t *e) \r
70 {\r
71         xbt_ex_display(e);\r
72         abort();\r
73 }\r
74 \r
75 \r
76 int\r
77 xbt_ucontext_factory_init(xbt_context_factory_t* factory)\r
78 {\r
79         /* context exception */\r
80         *factory = xbt_new0(s_xbt_context_factory_t,1);\r
81         \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
86         \r
87         /* context exception handlers */\r
88         __xbt_ex_ctx       = xbt_ucontext_ex_ctx;\r
89     __xbt_ex_terminate = xbt_ucontext_ex_terminate;     \r
90     \r
91         return 0;\r
92 }\r
93 \r
94 static int \r
95 xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro)\r
96 {\r
97                 \r
98         xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);\r
99         \r
100         context->exception = xbt_new(ex_ctx_t,1);\r
101     XBT_CTX_INITIALIZE(context->exception);\r
102     \r
103     *maestro = (xbt_context_t)context;\r
104     \r
105     return 0;\r
106     \r
107 }\r
108 \r
109 \r
110 static int\r
111 xbt_ucontext_factory_finalize(xbt_context_factory_t* factory)\r
112 {\r
113         free(maestro_context->exception);\r
114         free(*factory);\r
115         *factory = NULL;\r
116         return 0;\r
117 }\r
118 \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
121 {\r
122         xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);\r
123         \r
124         context->code = code;\r
125         context->name = xbt_strdup(name);\r
126         \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
131         \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
141         \r
142         \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
149         \r
150         return (xbt_context_t)context;\r
151 }\r
152 \r
153 static void \r
154 xbt_ucontext_free(xbt_context_t context)\r
155 {\r
156         if(context)\r
157         {\r
158                 free(context->name);\r
159                 \r
160                 if(context->argv)\r
161                 {\r
162                         int i;\r
163                         \r
164                         for(i = 0; i < context->argc; i++)\r
165                                 if(context->argv[i])\r
166                                         free(context->argv[i]);\r
167                                         \r
168                         free(context->argv);\r
169                 }\r
170                 \r
171                 if(context->exception) \r
172                         free(context->exception);\r
173                 \r
174                 /* finally destroy the context */\r
175                 free(context);\r
176         }\r
177 }\r
178 \r
179 static void \r
180 xbt_ucontext_kill(xbt_context_t context)\r
181 {\r
182         context->iwannadie = 1;\r
183         xbt_ucontext_swap(context);\r
184 }\r
185 \r
186 /** \r
187  * \param context the winner\r
188  *\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
192  * \r
193  * Only the maestro can call this function to run a given process.\r
194  */\r
195 static void \r
196 xbt_ucontext_schedule(xbt_context_t context)\r
197 {\r
198         xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");\r
199         xbt_ucontext_swap(context);\r
200 }\r
201 \r
202 /** \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
205  * had happened.\r
206  * \r
207  * Only the processes can call this function, giving back the control\r
208  * to the maestro\r
209  */\r
210 static void \r
211 xbt_ucontext_yield(void)\r
212 {\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
215 }\r
216 \r
217 static void \r
218 xbt_ucontext_start(xbt_context_t context)\r
219 {\r
220         makecontext(&(((xbt_ucontext_t)context)->uc), (void (*)(void)) xbt_ucontext_wrapper, 1, context);\r
221 }\r
222 \r
223 static void \r
224 xbt_ucontext_stop(int exit_code)\r
225 {\r
226         if(current_context->cleanup_func) \r
227                 ((*current_context->cleanup_func))(current_context->cleanup_arg);\r
228         \r
229         xbt_swag_remove(current_context, context_living);\r
230         xbt_swag_insert(current_context, context_to_destroy);   \r
231         \r
232         xbt_ucontext_swap(current_context);\r
233 }\r
234 \r
235 static void \r
236 xbt_ucontext_swap(xbt_context_t context)\r
237 {\r
238         xbt_assert0(current_context, "You have to call context_init() first.");\r
239         xbt_assert0(context, "Invalid argument");\r
240         \r
241         if(((xbt_ucontext_t)context)->prev == NULL) \r
242                 xbt_ucontext_resume(context);\r
243         else \r
244                 xbt_ucontext_suspend(context);\r
245         \r
246         if(current_context->iwannadie)\r
247                 xbt_ucontext_stop(1);\r
248 }\r
249 \r
250 static void* \r
251 xbt_ucontext_wrapper(void* param)\r
252 {\r
253         if (current_context->startup_func)\r
254                 (*current_context->startup_func)(current_context->startup_arg);\r
255         \r
256         xbt_ucontext_stop((*(current_context->code))(current_context->argc, current_context->argv));\r
257         return NULL;\r
258 }\r
259 \r
260 static void\r
261 xbt_ucontext_suspend(xbt_context_t context)\r
262 {\r
263         int rv;\r
264         \r
265         xbt_ucontext_t prev_context = ((xbt_ucontext_t)context)->prev;\r
266         \r
267         current_context = (xbt_context_t)(((xbt_ucontext_t)context)->prev);\r
268         \r
269         ((xbt_ucontext_t)context)->prev = NULL;\r
270         \r
271         rv = swapcontext(&(((xbt_ucontext_t)context)->uc), &(prev_context->uc));\r
272                 \r
273         xbt_assert0((rv == 0), "Context swapping failure");\r
274 }\r
275 \r
276 static void\r
277 xbt_ucontext_resume(xbt_context_t context)\r
278 {\r
279         int rv;\r
280         \r
281         ((xbt_ucontext_t)context)->prev = (xbt_ucontext_t)current_context;\r
282         \r
283         current_context = context;\r
284         \r
285         rv = swapcontext(&(((xbt_ucontext_t)context)->prev->uc), &(((xbt_ucontext_t)context)->uc));\r
286                 \r
287         xbt_assert0((rv == 0), "Context swapping failure");\r
288 }\r
289 \r
290 \r
291 \r