Logo AND Algorithmique Numérique Distribuée

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