Logo AND Algorithmique Numérique Distribuée

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