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 /* get the right definition of the xbt_ctx with all we need here */
25 #include "xbt/context_private.h"
27 pfn_schedule_t __process_schedule= NULL;
28 pfn_schedule_t __process_unschedule= NULL;
31 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ctx, xbt, "Context");
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*/
45 __xbt_process_schedule(xbt_context_t context);
48 __xbt_process_unschedule(xbt_context_t context);
51 __xbt_context_yield(xbt_context_t context);
54 __xbt_process_schedule(xbt_context_t context) {
55 (*(__process_schedule))(context);
59 __xbt_process_unschedule(xbt_context_t context) {
60 (*(__process_unschedule))(context);
64 __xbt_context_yield(xbt_context_t context) {
68 /* save the current context */
69 xbt_context_t self = current_context;
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
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;
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
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;
107 if(current_context->iwannadie)
108 __context_exit(current_context, 1);
115 xbt_context_free(xbt_context_t context) {
119 if(context->jprocess)
121 jobject jprocess = context->jprocess;
122 context->jprocess = NULL;
124 /* if the java process is alive join it */
125 if(jprocess_is_alive(jprocess,get_current_thread_env()))
127 jprocess_join(jprocess,get_current_thread_env());
131 /* destroy the mutex of the process */
132 xbt_os_mutex_destroy(context->mutex);
134 /* destroy the condition of the process */
135 xbt_os_cond_destroy(context->cond);
137 context->mutex = NULL;
138 context->cond = NULL;
140 if(context->exception)
141 free(context->exception);
149 * This function is only called by the main thread.
152 __context_exit(xbt_context_t context ,int value) {
153 /* call the cleanup function of the context */
155 if(context->cleanup_func)
156 context->cleanup_func(context->cleanup_arg);
158 /* remove the context from the list of the contexts in use. */
159 xbt_swag_remove(context, context_living);
161 /* insert the context in the list of contexts to destroy. */
162 xbt_swag_insert(context, context_to_destroy);
165 * signal the condition of the java process
168 xbt_os_mutex_lock(master_mutex);
170 if (context->jprocess)
172 if (jprocess_is_alive(context->jprocess,get_current_thread_env()))
175 __xbt_process_schedule(context);
176 jprocess = context->jprocess;
177 context->jprocess = NULL;
178 jprocess_exit(jprocess,get_current_thread_env());
186 * This function is called by a java process (only).
189 jcontext_exit(xbt_context_t context ,int value,JNIEnv* env) {
190 jobject __jprocess = context->jprocess;
191 context->jprocess = NULL;
193 if(context->cleanup_func)
194 context->cleanup_func(context->cleanup_arg);
196 /* remove the context of the list of living contexts */
197 xbt_swag_remove(context, context_living);
199 /* insert the context in the list of the contexts to destroy */
200 xbt_swag_insert(context, context_to_destroy);
203 * signal the condition of the main thread.
205 xbt_os_mutex_lock(master_mutex);
206 xbt_os_cond_signal(master_cond);
207 xbt_os_mutex_unlock(master_mutex);
210 /* the global reference to the java process instance is deleted */
211 jprocess_delete_global_ref(__jprocess,get_current_thread_env());
214 /* callback: context fetching */
216 __context_ex_ctx(void) {
217 return current_context->exception;
220 /* callback: termination */
222 __context_ex_terminate(xbt_ex_t *e) {
229 * This function initialize the xbt module context which contains
230 * all functions of the context API .
232 * @remark This function must be called before use all other function
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);
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;
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));
252 /* append the current context in the list of context in use */
253 xbt_swag_insert(init_context, context_living);
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();
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();
265 __process_schedule = jprocess_schedule;
266 __process_unschedule = jprocess_unschedule;
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.
275 void xbt_context_empty_trash(void) {
276 xbt_context_t context=NULL;
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);
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());
288 /* the main thread locks the mutex used to create all the process */
289 xbt_os_mutex_lock(creation_mutex);
291 /* the main thread starts the java process */
292 jprocess_start(context->jprocess,get_current_thread_env());
294 /* the main thread waits the startup of the java process */
295 xbt_os_cond_wait(creation_cond, creation_mutex);
297 /* the java process is started, the main thread unlocks the mutex
298 * used during the creation of the java process
300 xbt_os_mutex_unlock(creation_mutex);
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);
311 context->code = code;
312 context->name = xbt_strdup(name);
314 context->mutex = xbt_os_mutex_init();
315 context->cond = xbt_os_cond_init();
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);
327 xbt_swag_insert(context, context_living);
333 void xbt_context_yield(void) {
334 __xbt_context_yield(current_context);
338 * \param context the winner
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.
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);
350 * This function kill all existing context and free all the memory
351 * that has been allocated in this module.
353 void xbt_context_exit(void) {
355 xbt_context_t context=NULL;
357 xbt_context_empty_trash();
359 while((context=xbt_swag_extract(context_living))) {
360 if(context!=init_context)
361 xbt_context_kill(context);
364 free(init_context->exception);
367 init_context = current_context = NULL ;
369 xbt_context_empty_trash();
371 xbt_swag_free(context_to_destroy);
372 xbt_swag_free(context_living);
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);
381 * \param context poor victim
383 * This function simply kills \a context... scarry isn't it ?
385 void xbt_context_kill(xbt_context_t context) {
387 context->iwannadie=1;
388 __xbt_context_yield(context);
392 xbt_creation_cond_get(void) {
393 return creation_cond;
397 xbt_creation_mutex_get(void) {
398 return creation_mutex;
401 void xbt_context_set_jprocess(xbt_context_t context, void *jp) {
402 context->jprocess = jp;
404 void* xbt_context_get_jprocess(xbt_context_t context) {
405 return context->jprocess;
408 void xbt_context_set_jmutex(xbt_context_t context,void *jm) {
411 void* xbt_context_get_jmutex(xbt_context_t context) {
412 return context->mutex;
415 void xbt_context_set_jcond(xbt_context_t context,void *jc) {
418 void* xbt_context_get_jcond(xbt_context_t context) {
419 return context->cond;
422 void xbt_context_set_jenv(xbt_context_t context,void* je) {
425 void* xbt_context_get_jenv(xbt_context_t context) {
426 return get_current_thread_env();