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 */
40 __xbt_process_schedule(xbt_context_t context);
43 __xbt_process_unschedule(xbt_context_t context);
46 __xbt_context_yield(xbt_context_t context);
49 __xbt_process_schedule(xbt_context_t context) {
50 (*(__process_schedule))(context);
54 __xbt_process_unschedule(xbt_context_t context) {
55 (*(__process_unschedule))(context);
59 __xbt_context_yield(xbt_context_t context) {
62 xbt_context_t self = current_context;
63 current_context = context;
64 __xbt_process_schedule(context);
66 current_context = self;
69 if(current_context->iwannadie)
70 __context_exit(current_context, 1);
74 xbt_context_free(xbt_context_t context) {
80 jobject jprocess = context->jprocess;
81 context->jprocess = NULL;
83 /* if the java process is alive join it */
84 if(jprocess_is_alive(jprocess,get_current_thread_env()))
86 jprocess_join(jprocess,get_current_thread_env());
90 if(context->exception)
91 free(context->exception);
99 * This function is only called by the main thread.
102 __context_exit(xbt_context_t context ,int value) {
103 /* call the cleanup function of the context */
105 if(context->cleanup_func)
106 context->cleanup_func(context->cleanup_arg);
108 /* remove the context from the list of the contexts in use. */
109 xbt_swag_remove(context, context_living);
111 /* insert the context in the list of contexts to destroy. */
112 xbt_swag_insert(context, context_to_destroy);
115 * signal the condition of the java process
117 if (context->jprocess)
119 if (jprocess_is_alive(context->jprocess,get_current_thread_env()))
122 __xbt_process_schedule(context);
123 jprocess = context->jprocess;
124 context->jprocess = NULL;
125 jprocess_exit(jprocess,get_current_thread_env());
131 * This function is called by a java process (only).
134 jcontext_exit(xbt_context_t context ,int value,JNIEnv* env) {
136 jobject __jprocess = context->jprocess;
137 context->jprocess = NULL;
139 if(context->cleanup_func)
140 context->cleanup_func(context->cleanup_arg);
142 /* remove the context of the list of living contexts */
143 xbt_swag_remove(context, context_living);
145 /* insert the context in the list of the contexts to destroy */
146 xbt_swag_insert(context, context_to_destroy);
148 /* the global reference to the java process instance is deleted */
149 jprocess_delete_global_ref(__jprocess,get_current_thread_env());
152 /* callback: context fetching */
154 __context_ex_ctx(void) {
155 return current_context->exception;
158 /* callback: termination */
160 __context_ex_terminate(xbt_ex_t *e) {
167 * This function initialize the xbt module context which contains
168 * all functions of the context API .
170 * @remark This function must be called before use all other function
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);
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;
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));
190 /* append the current context in the list of context in use */
191 xbt_swag_insert(init_context, context_living);
193 __process_schedule = jprocess_schedule;
194 __process_unschedule = jprocess_unschedule;
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.
203 void xbt_context_empty_trash(void) {
204 xbt_context_t context=NULL;
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);
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());
216 /* the main thread starts the java process */
217 jprocess_start(context->jprocess,get_current_thread_env());
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);
228 context->code = code;
229 context->name = xbt_strdup(name);
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);
240 xbt_swag_insert(context, context_living);
246 void xbt_context_yield(void) {
247 __xbt_process_unschedule(current_context);
253 * \param context the winner
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.
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);
265 * This function kill all existing context and free all the memory
266 * that has been allocated in this module.
268 void xbt_context_exit(void) {
270 xbt_context_t context=NULL;
272 xbt_context_empty_trash();
274 while((context=xbt_swag_extract(context_living))) {
275 if(context!=init_context)
276 xbt_context_kill(context);
279 free(init_context->exception);
282 init_context = current_context = NULL ;
284 xbt_context_empty_trash();
286 xbt_swag_free(context_to_destroy);
287 xbt_swag_free(context_living);
291 * \param context poor victim
293 * This function simply kills \a context... scarry isn't it ?
295 void xbt_context_kill(xbt_context_t context) {
297 context->iwannadie=1;
298 __xbt_context_yield(context);
301 void xbt_context_set_jprocess(xbt_context_t context, void *jp) {
302 context->jprocess = jp;
304 void* xbt_context_get_jprocess(xbt_context_t context) {
305 return context->jprocess;
308 void xbt_context_set_jenv(xbt_context_t context,void* je) {
311 void* xbt_context_get_jenv(xbt_context_t context) {
312 return get_current_thread_env();