4 * Copyright 2006,2007 Arnaud Legrand,Martin Quinson,Malek Cherier
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.
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"
20 #define JAVA_SIMGRID /* get the right definition of the xbt_ctx with all we need here */
21 #include "xbt/context_private.h"
24 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ctx, xbt, "Context");
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*/
37 __xbt_context_yield(xbt_context_t context);
41 __xbt_context_yield(xbt_context_t context) {
43 /* save the current context */
44 xbt_context_t self = current_context;
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
54 xbt_os_mutex_lock(master_mutex);
55 xbt_os_mutex_lock(context->mutex);
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;
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
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;
87 if(current_context->iwannadie) {
88 __context_exit(current_context, 1);
95 xbt_context_free(xbt_context_t context) {
97 if(context->jprocess) {
98 jobject jprocess = context->jprocess;
99 context->jprocess = NULL;
101 /* if the java process is alive join it */
102 if(jprocess_is_alive(jprocess,context->jenv)) {
103 jprocess_join(jprocess,context->jenv);
107 /* destroy the mutex of the process */
108 xbt_os_mutex_destroy(context->mutex);
110 /* destroy the condition of the process */
111 xbt_os_cond_destroy(context->cond);
113 context->mutex = NULL;
114 context->cond = NULL;
116 if(context->exception)
117 free(context->exception);
125 * This function is only called by the main thread.
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);
133 /* remove the context from the list of the contexts in use. */
134 xbt_swag_remove(context, context_living);
136 /* insert the context in the list of contexts to destroy. */
137 xbt_swag_insert(context, context_to_destroy);
140 * signal the condition of the java process
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);
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);
158 * This function is called by a java process (only).
161 jcontext_exit(xbt_context_t context ,int value,JNIEnv* env) {
162 jobject __jprocess = context->jprocess;
163 context->jprocess = NULL;
165 if(context->cleanup_func)
166 context->cleanup_func(context->cleanup_arg);
168 /* remove the context of the list of living contexts */
169 xbt_swag_remove(context, context_living);
171 /* insert the context in the list of the contexts to destroy */
172 xbt_swag_insert(context, context_to_destroy);
175 * signal the condition of the main thread.
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);
183 /* the global reference to the java process instance is deleted */
184 jprocess_delete_global_ref(__jprocess,env);
187 /* callback: context fetching */
189 __context_ex_ctx(void) {
190 return current_context->exception;
193 /* callback: termination */
195 __context_ex_terminate(xbt_ex_t *e) {
202 * This function initialize the xbt module context which contains
203 * all functions of the context API .
205 * @remark This function must be called before use all other function
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);
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;
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));
225 /* append the current context in the list of context in use */
226 xbt_swag_insert(init_context, context_living);
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();
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();
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.
245 void xbt_context_empty_trash(void) {
246 xbt_context_t context=NULL;
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);
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);
258 /* the main thread locks the mutex used to create all the process */
259 xbt_os_mutex_lock(creation_mutex);
261 /* the main thread starts the java process */
262 jprocess_start(context->jprocess,context->jenv);
264 /* the main thread waits the startup of the java process */
265 xbt_os_cond_wait(creation_cond, creation_mutex);
267 /* the java process is started, the main thread unlocks the mutex
268 * used during the creation of the java process
270 xbt_os_mutex_unlock(creation_mutex);
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);
281 context->code = code;
282 context->name = xbt_strdup(name);
284 context->mutex = xbt_os_mutex_init();
285 context->cond = xbt_os_cond_init();
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);
297 xbt_swag_insert(context, context_living);
303 void xbt_context_yield(void) {
304 __xbt_context_yield(current_context);
308 * \param context the winner
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.
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);
320 * This function kill all existing context and free all the memory
321 * that has been allocated in this module.
323 void xbt_context_exit(void) {
325 xbt_context_t context=NULL;
327 xbt_context_empty_trash();
329 while((context=xbt_swag_extract(context_living))) {
330 if(context!=init_context)
331 xbt_context_kill(context);
334 free(init_context->exception);
337 init_context = current_context = NULL ;
339 xbt_context_empty_trash();
341 xbt_swag_free(context_to_destroy);
342 xbt_swag_free(context_living);
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);
351 * \param context poor victim
353 * This function simply kills \a context... scarry isn't it ?
355 void xbt_context_kill(xbt_context_t context) {
356 context->iwannadie=1;
357 __xbt_context_yield(context);
361 xbt_creation_cond_get(void) {
362 return creation_cond;
366 xbt_creation_mutex_get(void) {
367 return creation_mutex;
370 void xbt_context_set_jprocess(xbt_context_t context, void *jp) {
371 context->jprocess = jp;
373 void* xbt_context_get_jprocess(xbt_context_t context) {
374 return context->jprocess;
377 void xbt_context_set_jmutex(xbt_context_t context,void *jm) {
380 void* xbt_context_get_jmutex(xbt_context_t context) {
381 return context->mutex;
384 void xbt_context_set_jcond(xbt_context_t context,void *jc) {
387 void* xbt_context_get_jcond(xbt_context_t context) {
388 return context->cond;
391 void xbt_context_set_jenv(xbt_context_t context,void* je) {
394 void* xbt_context_get_jenv(xbt_context_t context) {
395 return context->jenv;