Logo AND Algorithmique Numérique Distribuée

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