Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
The file containing the new implementation of the switch context mechanism.
[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
39 static void
40 __xbt_process_schedule(xbt_context_t context);
41
42 static void
43 __xbt_process_unschedule(xbt_context_t context);
44
45 static void 
46 __xbt_context_yield(xbt_context_t context);
47
48 static void
49 __xbt_process_schedule(xbt_context_t context) {
50         (*(__process_schedule))(context);
51 }
52
53 static void
54 __xbt_process_unschedule(xbt_context_t context) {
55         (*(__process_unschedule))(context);
56 }
57
58 static void 
59 __xbt_context_yield(xbt_context_t context) {
60
61   if(context) {
62     xbt_context_t self = current_context;
63         current_context = context;
64         __xbt_process_schedule(context);
65
66         current_context = self;
67   }
68   
69   if(current_context->iwannadie)
70     __context_exit(current_context, 1);
71   
72 }
73 static void 
74 xbt_context_free(xbt_context_t context) {
75
76         if(context) 
77         {
78                 if(context->jprocess) 
79                 {
80                         jobject jprocess = context->jprocess;
81                         context->jprocess = NULL;
82
83                         /* if the java process is alive join it */
84                         if(jprocess_is_alive(jprocess,get_current_thread_env())) 
85                         {
86                                 jprocess_join(jprocess,get_current_thread_env());
87                         }
88                 }
89
90                 if(context->exception) 
91                         free(context->exception);
92
93                 free(context->name);
94                 free(context);
95                 context = NULL;
96   }
97 }
98 /*
99  * This function is only called by the main thread.
100  */
101 void 
102 __context_exit(xbt_context_t context ,int value) {
103   /* call the cleanup function of the context */
104         
105         if(context->cleanup_func)
106                 context->cleanup_func(context->cleanup_arg);
107         
108         /* remove the context from the list of the contexts in use. */
109         xbt_swag_remove(context, context_living);
110         
111         /* insert the context in the list of contexts to destroy. */ 
112         xbt_swag_insert(context, context_to_destroy);
113         
114         /*
115         * signal the condition of the java process 
116         */
117         if (context->jprocess) 
118         {
119                 if (jprocess_is_alive(context->jprocess,get_current_thread_env())) 
120                 {
121                         jobject jprocess;
122                         __xbt_process_schedule(context);
123                         jprocess = context->jprocess;
124                         context->jprocess = NULL;
125                         jprocess_exit(jprocess,get_current_thread_env());
126                 }
127         }
128 }
129
130 /*
131  * This function is called by a java process (only).
132  */
133 void 
134 jcontext_exit(xbt_context_t context ,int value,JNIEnv* env) {
135
136   jobject __jprocess = context->jprocess;
137   context->jprocess = NULL;
138         
139   if(context->cleanup_func)
140     context->cleanup_func(context->cleanup_arg);
141
142   /* remove the context of the list of living contexts */
143   xbt_swag_remove(context, context_living);
144
145   /* insert the context in the list of the contexts to destroy */
146   xbt_swag_insert(context, context_to_destroy);
147         
148   /* the global reference to the java process instance is deleted */
149   jprocess_delete_global_ref(__jprocess,get_current_thread_env());
150 }
151
152 /* callback: context fetching */
153 static ex_ctx_t *
154 __context_ex_ctx(void) {
155   return current_context->exception;
156 }
157
158 /* callback: termination */
159 static void 
160 __context_ex_terminate(xbt_ex_t *e) {
161   xbt_ex_display(e);
162
163   abort();
164 }
165
166 /**
167  * This function initialize the xbt module context which contains 
168  * all functions of the context API .
169  *
170  * @remark This function must be called before use all other function 
171  * of this API.
172  */
173 void 
174 xbt_context_init(void) {
175   if(!current_context) {
176     /* allocate the current context. */
177     current_context = init_context = xbt_new0(s_xbt_context_t,1);
178                 
179     /* context exception */
180     init_context->exception = xbt_new(ex_ctx_t,1);
181     XBT_CTX_INITIALIZE(init_context->exception);
182     __xbt_ex_ctx       = __context_ex_ctx;
183     __xbt_ex_terminate = __context_ex_terminate;
184     
185     /* this list contains the context to destroy */
186     context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
187     /* this list contains the context in use */
188     context_living = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
189     
190     /* append the current context in the list of context in use */
191     xbt_swag_insert(init_context, context_living);
192     
193     __process_schedule = jprocess_schedule;
194         __process_unschedule = jprocess_unschedule;
195   }
196 }
197
198 /** 
199  * This function is used as a garbage collection
200  * Should be called some time to time to free the memory allocated for contexts
201  * that have finished executing their main functions.
202  */
203 void xbt_context_empty_trash(void) {
204   xbt_context_t context=NULL;
205         
206   /* destroy all the context contained in the list of context to destroy */
207   while((context=xbt_swag_extract(context_to_destroy)))
208     xbt_context_free(context);
209 }
210
211 void 
212 xbt_context_start(xbt_context_t context)  {
213   DEBUG3("xbt_context_start of %p (jproc=%p, jenv=%p)",
214          context, context->jprocess, get_current_thread_env());
215
216   /* the main thread starts the java process                            */
217   jprocess_start(context->jprocess,get_current_thread_env());
218 }
219
220
221 xbt_context_t 
222 xbt_context_new(const char *name, xbt_main_func_t code, 
223                 void_f_pvoid_t startup_func, void *startup_arg,
224                 void_f_pvoid_t cleanup_func, void *cleanup_arg,
225                 int argc, char *argv[]) {
226   xbt_context_t context = xbt_new0(s_xbt_context_t,1);
227
228   context->code = code;
229   context->name = xbt_strdup(name);
230         
231   context->argc = argc;
232   context->argv = argv;
233   context->startup_func = startup_func;
234   context->startup_arg = startup_arg;
235   context->cleanup_func = cleanup_func;
236   context->cleanup_arg = cleanup_arg;
237   context->exception = xbt_new(ex_ctx_t,1);
238   XBT_CTX_INITIALIZE(context->exception);
239         
240   xbt_swag_insert(context, context_living);
241         
242   return context;
243 }
244
245
246 void xbt_context_yield(void) {
247   __xbt_process_unschedule(current_context);
248
249
250 }
251
252 /** 
253  * \param context the winner
254  *
255  * Calling this function blocks the current context and schedule \a context.  
256  * When \a context will call xbt_context_yield, it will return
257  * to this function as if nothing had happened.
258  */
259 void xbt_context_schedule(xbt_context_t context) {
260   xbt_assert0((current_context==init_context),"You are not supposed to run this function here!");
261   __xbt_context_yield(context);
262 }
263
264 /** 
265  * This function kill all existing context and free all the memory
266  * that has been allocated in this module.
267  */
268 void xbt_context_exit(void)  {
269
270   xbt_context_t context=NULL;
271         
272   xbt_context_empty_trash();
273         
274   while((context=xbt_swag_extract(context_living))) {
275     if(context!=init_context) 
276       xbt_context_kill(context);
277   }
278
279   free(init_context->exception); 
280   free(init_context);   
281
282   init_context = current_context = NULL ;
283
284   xbt_context_empty_trash();
285
286   xbt_swag_free(context_to_destroy);
287   xbt_swag_free(context_living);
288 }
289
290 /** 
291  * \param context poor victim
292  *
293  * This function simply kills \a context... scarry isn't it ?
294  */
295 void xbt_context_kill(xbt_context_t context) {
296
297   context->iwannadie=1;
298   __xbt_context_yield(context);
299 }
300
301 void  xbt_context_set_jprocess(xbt_context_t context, void *jp) {
302   context->jprocess = jp;
303 }
304 void* xbt_context_get_jprocess(xbt_context_t context)           { 
305    return context->jprocess;
306 }
307
308 void  xbt_context_set_jenv(xbt_context_t context,void* je)      {
309    context->jenv = je;
310 }
311 void* xbt_context_get_jenv(xbt_context_t context)               { 
312    return get_current_thread_env();
313 }
314
315
316
317 /* @} */