Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9ca20d816e5003116a2b40d55ba48552c37598ab
[simgrid.git] / src / java / jxbt_context.c
1 /*
2  * $Id$
3  *
4  * Copyright 2006,2007 Arnaud Legrand,Martin Quinson,Malek Cherier         
5  * All right reserved. 
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. 
9  */
10
11 #include "portable.h"
12 #include "xbt/log.h"
13 #include "xbt/dynar.h"
14 #include "xbt/xbt_os_thread.h"
15 #include "java/jxbt_context.h"
16 #include "java/jmsg.h"
17 #include "java/jmsg_process.h"
18
19 #define JAVA_SIMGRID /* get the right definition of the xbt_ctx with all we need here */
20 #include "xbt/context_private.h"
21
22
23 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ctx, xbt, "Context");
24
25
26 static xbt_context_t current_context = NULL;    /* the current context                  */
27 static xbt_context_t init_context = NULL;       /* the initial context                  */
28 static xbt_swag_t context_to_destroy = NULL;    /* the list of the contexs to destroy   */
29 static xbt_swag_t context_living = NULL;        /* the list of the contexts in use      */
30 static xbt_os_mutex_t creation_mutex;              /* For syncronization during process creation */
31 static xbt_os_cond_t creation_cond;              /* For syncronization during process creation */
32 static xbt_os_mutex_t master_mutex;             /* For syncronization during process scheduling*/
33 static xbt_os_cond_t master_cond;               /* For syncronization during process scheduling*/
34
35 static void 
36 __xbt_context_yield(xbt_context_t context);
37
38
39 static void 
40 __xbt_context_yield(xbt_context_t context) {
41   if(context) {
42     /* save the current context */
43     xbt_context_t self = current_context;
44     
45     if(is_main_thread()) {
46       /* the main thread has called this function
47        * - update the current context
48        * - signal the condition of the process to run
49        * - wait on its condition
50        * - restore thr current contex
51        */
52       
53       xbt_os_mutex_lock(master_mutex);
54       xbt_os_mutex_lock(context->mutex);
55                         
56       /* update the current context */
57       current_context = context;
58       xbt_os_cond_signal(context->cond);
59       xbt_os_mutex_unlock(context->mutex);
60       xbt_os_cond_wait(master_cond, master_mutex);
61       xbt_os_mutex_unlock(master_mutex);
62       /* retore the current context */
63       current_context = self;
64                         
65     } else {
66         /* a java thread has called this function
67          * - update the current context
68          * - signal the condition of the main thread
69          * - wait on its condition
70          * - restore thr current contex
71          */
72
73         xbt_os_mutex_lock(master_mutex);
74         xbt_os_mutex_lock(context->mutex);
75         /* update the current context */
76         current_context = context;
77         xbt_os_cond_signal(master_cond);
78         xbt_os_mutex_unlock(master_mutex);
79         xbt_os_cond_wait(context->cond, context->mutex);
80         xbt_os_mutex_unlock(context->mutex);
81         /* retore the current context */
82         current_context = self;
83       }
84   }
85         
86   if(current_context->iwannadie) {
87     __context_exit(current_context, 1);
88   }
89 }
90
91
92
93 static void 
94 xbt_context_free(xbt_context_t context) {
95   if(context) {
96     if(context->jprocess) {
97       jobject jprocess = context->jprocess;
98       context->jprocess = NULL;
99                         
100       /* if the java process is alive join it */
101       if(jprocess_is_alive(jprocess,context->jenv)) {
102         jprocess_join(jprocess,context->jenv);
103       }
104     }
105         
106     /* destroy the mutex of the process */
107     xbt_os_mutex_destroy(context->mutex);
108
109     /* destroy the condition of the process */
110     xbt_os_cond_destroy(context->cond);
111
112     context->mutex = NULL;
113     context->cond = NULL;
114     
115     if(context->exception) 
116       free(context->exception);
117     
118     free(context);
119     context = NULL;
120   }
121 }
122 /*
123  * This function is only called by the main thread.
124  */
125 void 
126 __context_exit(xbt_context_t context ,int value) {
127   /* call the cleanup function of the context */
128   if(context->cleanup_func)
129     context->cleanup_func(context->cleanup_arg);
130         
131   /* remove the context from the list of the contexts in use. */
132   xbt_swag_remove(context, context_living);
133         
134   /* insert the context in the list of contexts to destroy. */ 
135   xbt_swag_insert(context, context_to_destroy);
136         
137   /*
138    * signal the condition of the java process 
139    */
140   xbt_os_mutex_lock(master_mutex);
141   xbt_os_mutex_lock(context->mutex);
142   xbt_os_cond_signal(context->cond);
143   xbt_os_mutex_unlock(context->mutex);
144         
145   if (context->jprocess) {
146     /* if the java process is alive, stop it */
147     if (jprocess_is_alive(context->jprocess,context->jenv)) {
148       jobject jprocess = context->jprocess;
149       context->jprocess = NULL;
150       jprocess_exit(jprocess,context->jenv);
151     }
152   }
153 }
154
155 /*
156  * This function is called by a java process (only).
157  */
158 void 
159 jcontext_exit(xbt_context_t context ,int value,JNIEnv* env) {
160   jobject __jprocess = context->jprocess;
161   context->jprocess = NULL;
162         
163   if(context->cleanup_func)
164     context->cleanup_func(context->cleanup_arg);
165
166   /* remove the context of the list of living contexts */
167   xbt_swag_remove(context, context_living);
168
169   /* insert the context in the list of the contexts to destroy */
170   xbt_swag_insert(context, context_to_destroy);
171         
172   /*
173    * signal the condition of the main thread.
174    */
175   xbt_os_mutex_lock(master_mutex);
176   xbt_os_mutex_lock(context->mutex);
177   xbt_os_cond_signal(master_cond);
178   xbt_os_mutex_unlock(master_mutex);
179         
180         
181   /* the global reference to the java process instance is deleted */
182   jprocess_delete_global_ref(__jprocess,env);
183 }
184
185 /* callback: context fetching */
186 static ex_ctx_t *
187 __context_ex_ctx(void) {
188   return current_context->exception;
189 }
190
191 /* callback: termination */
192 static void 
193 __context_ex_terminate(xbt_ex_t *e) {
194   xbt_ex_display(e);
195
196   abort();
197 }
198
199 /**
200  * This function initialize the xbt module context which contains 
201  * all functions of the context API .
202  *
203  * @remark This function must be called before use all other function 
204  * of this API.
205  */
206 void 
207 xbt_context_init(void) {
208   if(!current_context) {
209     /* allocate the current context. */
210     current_context = init_context = xbt_new0(s_xbt_context_t,1);
211                 
212     /* context exception */
213     init_context->exception = xbt_new(ex_ctx_t,1);
214     XBT_CTX_INITIALIZE(init_context->exception);
215     __xbt_ex_ctx       = __context_ex_ctx;
216     __xbt_ex_terminate = __context_ex_terminate;
217     
218     /* this list contains the context to destroy */
219     context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
220     /* this list contains the context in use */
221     context_living = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
222     
223     /* append the current context in the list of context in use */
224     xbt_swag_insert(init_context, context_living);
225            
226     /* this mutex is used to synchronize the creation of the java process */
227     creation_mutex = xbt_os_mutex_init();
228     /* this mutex is used to synchronize the creation of the java process */
229     creation_cond = xbt_os_cond_init();
230
231     /* this mutex is used to synchronize the scheduling of the java process */
232     master_mutex = xbt_os_mutex_init();
233     /* this mutex is used to synchronize the scheduling of the java process */
234     master_cond = xbt_os_cond_init();
235   }
236 }
237
238 /** 
239  * This function is used as a garbage collection
240  * Should be called some time to time to free the memory allocated for contexts
241  * that have finished executing their main functions.
242  */
243 void xbt_context_empty_trash(void) {
244   xbt_context_t context=NULL;
245         
246   /* destroy all the context contained in the list of context to destroy */
247   while((context=xbt_swag_extract(context_to_destroy)))
248     xbt_context_free(context);
249 }
250
251 void 
252 xbt_context_start(xbt_context_t context)  {
253   DEBUG3("xbt_context_start of %p (jproc=%p, jenv=%p)",
254          context, context->jprocess, context->jenv);
255
256   /* the main thread locks the mutex used to create all the process     */
257   xbt_os_mutex_lock(creation_mutex);
258
259   /* the main thread starts the java process                            */
260   jprocess_start(context->jprocess,context->jenv);
261
262   /* the main thread waits the startup of the java process              */
263   xbt_os_cond_wait(creation_cond, creation_mutex);
264         
265   /* the java process is started, the main thread unlocks the mutex
266    * used during the creation of the java process
267    */
268   xbt_os_mutex_unlock(creation_mutex);
269 }
270
271
272 xbt_context_t 
273 xbt_context_new(xbt_main_func_t code, 
274                 void_f_pvoid_t startup_func, void *startup_arg,
275                 void_f_pvoid_t cleanup_func, void *cleanup_arg,
276                 int argc, char *argv[]) {
277   xbt_context_t context = xbt_new0(s_xbt_context_t,1);
278
279   context->code = code;
280         
281   context->mutex = xbt_os_mutex_init();
282   context->cond = xbt_os_cond_init();
283         
284         
285   context->argc = argc;
286   context->argv = argv;
287   context->startup_func = startup_func;
288   context->startup_arg = startup_arg;
289   context->cleanup_func = cleanup_func;
290   context->cleanup_arg = cleanup_arg;
291   context->exception = xbt_new(ex_ctx_t,1);
292   XBT_CTX_INITIALIZE(context->exception);
293         
294   xbt_swag_insert(context, context_living);
295         
296   return context;
297 }
298
299
300 void xbt_context_yield(void) {
301   __xbt_context_yield(current_context);
302 }
303
304 /** 
305  * \param context the winner
306  *
307  * Calling this function blocks the current context and schedule \a context.  
308  * When \a context will call xbt_context_yield, it will return
309  * to this function as if nothing had happened.
310  */
311 void xbt_context_schedule(xbt_context_t context) {
312   xbt_assert0((current_context==init_context),"You are not supposed to run this function here!");
313   __xbt_context_yield(context);
314 }
315
316 /** 
317  * This function kill all existing context and free all the memory
318  * that has been allocated in this module.
319  */
320 void xbt_context_exit(void)  {
321
322   xbt_context_t context=NULL;
323         
324   xbt_context_empty_trash();
325         
326   while((context=xbt_swag_extract(context_living))) {
327     if(context!=init_context) 
328       xbt_context_kill(context);
329   }
330
331   free(init_context->exception); 
332   free(init_context);   
333
334   init_context = current_context = NULL ;
335
336   xbt_context_empty_trash();
337
338   xbt_swag_free(context_to_destroy);
339   xbt_swag_free(context_living);
340         
341   xbt_os_mutex_destroy(creation_mutex);
342   xbt_os_cond_destroy(creation_cond);
343   xbt_os_mutex_destroy(master_mutex);
344   xbt_os_cond_destroy(master_cond);
345 }
346
347 /** 
348  * \param context poor victim
349  *
350  * This function simply kills \a context... scarry isn't it ?
351  */
352 void xbt_context_kill(xbt_context_t context) {
353   context->iwannadie=1;
354   __xbt_context_yield(context);
355 }
356
357 xbt_os_cond_t
358 xbt_creation_cond_get(void) {
359   return creation_cond;
360 }
361
362 xbt_os_mutex_t
363 xbt_creation_mutex_get(void) {
364   return creation_mutex;
365 }
366
367 void  xbt_context_set_jprocess(xbt_context_t context, void *jp) {
368   context->jprocess = jp;
369 }
370 void* xbt_context_get_jprocess(xbt_context_t context)           { 
371    return context->jprocess;
372 }
373
374 void  xbt_context_set_jmutex(xbt_context_t context,void *jm)    {
375    context->mutex = jm;
376 }
377 void* xbt_context_get_jmutex(xbt_context_t context)             { 
378    return context->mutex; 
379 }
380
381 void  xbt_context_set_jcond(xbt_context_t context,void *jc)     {
382    context->cond = jc;
383 }
384 void* xbt_context_get_jcond(xbt_context_t context)              { 
385    return context->cond;
386 }
387
388 void  xbt_context_set_jenv(xbt_context_t context,void* je)      {
389    context->jenv = je;
390 }
391 void* xbt_context_get_jenv(xbt_context_t context)               { 
392    return context->jenv;
393 }
394
395
396 /* @} */