Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
merge msg_vm.c - adrien (please note that there is one line (destruction of the tx_pr...
[simgrid.git] / src / bindings / java / smx_context_java.c
1 /* context_java - implementation of context switching for java threads */
2
3 /* Copyright (c) 2009-2010, 2012-2014. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include <xbt/function_types.h>
10 #include <simgrid/simix.h>
11 #include <xbt/ex.h>
12 #include "smx_context_java.h"
13 #include "jxbt_utilities.h"
14 #include "xbt/dynar.h"
15 #include "../../simix/smx_private.h"
16 extern JavaVM *__java_vm;
17
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(jmsg, bindings, "MSG for Java(TM)");
19
20 static smx_context_t
21 smx_ctx_java_factory_create_context(xbt_main_func_t code,
22                                     int argc, char **argv,
23                                     void_pfn_smxprocess_t cleanup_func,
24                                     smx_process_t process);
25
26 static void smx_ctx_java_free(smx_context_t context);
27 static void smx_ctx_java_suspend(smx_context_t context);
28 static void smx_ctx_java_resume(smx_context_t new_context);
29 static void smx_ctx_java_runall(void);
30 static void* smx_ctx_java_thread_run(void *data);
31 void SIMIX_ctx_java_factory_init(smx_context_factory_t * factory)
32 {
33   /* instantiate the context factory */
34   smx_ctx_base_factory_init(factory);
35
36   (*factory)->create_context = smx_ctx_java_factory_create_context;
37   /* Leave default behavior of (*factory)->finalize */
38   (*factory)->free = smx_ctx_java_free;
39   (*factory)->stop = smx_ctx_java_stop;
40   (*factory)->suspend = smx_ctx_java_suspend;
41   (*factory)->runall = smx_ctx_java_runall;
42   (*factory)->name = "ctx_java_factory";
43   //(*factory)->finalize = smx_ctx_base_factory_finalize;
44   (*factory)->self = smx_ctx_java_self;
45   (*factory)->get_process = smx_ctx_base_get_process;
46 }
47 smx_context_t smx_ctx_java_self(void)
48 {
49         return (smx_context_t)xbt_os_thread_get_extra_data();
50 }
51
52 static smx_context_t
53 smx_ctx_java_factory_create_context(xbt_main_func_t code,
54                                     int argc, char **argv,
55                                     void_pfn_smxprocess_t cleanup_func,
56                                     smx_process_t process)
57 {
58   static int thread_amount=0;
59   smx_ctx_java_t context = xbt_new0(s_smx_ctx_java_t, 1);
60   thread_amount++;
61   /* If the user provided a function for the process then use it
62      otherwise is the context for maestro */
63   if (code) {
64     if (argc == 0) {
65       context->jprocess = (jobject) code;
66     }
67     else {
68       context->jprocess = NULL;
69     }
70     context->super.cleanup_func = cleanup_func;
71     context->begin = xbt_os_sem_init(0);
72     context->end = xbt_os_sem_init(0);
73
74     context->super.argc = argc;
75     context->super.argv = argv;
76     context->super.code = code;
77
78     TRY {         
79        context->thread = xbt_os_thread_create(NULL,smx_ctx_java_thread_run,context,NULL);
80     }
81     CATCH_ANONYMOUS {
82       RETHROWF("Failed to create context #%d. You may want to switch to Java coroutines to increase your limits (error: %s)."
83                "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
84                thread_amount);
85     }
86   } else {
87         context->thread = NULL;
88     xbt_os_thread_set_extra_data(context);
89   }
90   context->super.process = process;
91   
92   return (smx_context_t) context;
93 }
94
95 static void* smx_ctx_java_thread_run(void *data) {
96   smx_ctx_java_t context = (smx_ctx_java_t)data;
97   xbt_os_thread_set_extra_data(context);
98   //Attach the thread to the JVM
99   JNIEnv *env;
100   _XBT_GNUC_UNUSED jint error = (*__java_vm)->AttachCurrentThread(__java_vm, (void **) &env, NULL);
101   xbt_assert((error == JNI_OK), "The thread could not be attached to the JVM");
102   context->jenv = get_current_thread_env();
103   //Wait for the first scheduling round to happen.
104   xbt_os_sem_acquire(context->begin);
105   //Create the "Process" object if needed.
106   if (context->super.argc > 0) {
107     context->super.code(context->super.argc, context->super.argv);
108   }
109   else {
110     smx_process_t process = SIMIX_process_self();
111     (*env)->SetLongField(env, context->jprocess, jprocess_field_Process_bind,
112                          (intptr_t)process);
113   }
114
115   // Adrien, ugly path, just to bypass creation of context at low levels
116   // (i.e such as for the VM migration for instance)
117   if(context->jprocess != NULL){
118         xbt_assert((context->jprocess != NULL), "Process not created...");
119         //wait for the process to be able to begin
120         //TODO: Cache it
121         jfieldID jprocess_field_Process_startTime = jxbt_get_sfield(env, "org/simgrid/msg/Process", "startTime", "D");
122         jdouble startTime =  (*env)->GetDoubleField(env, context->jprocess, jprocess_field_Process_startTime);
123         if (startTime > MSG_get_clock()) {
124                 MSG_process_sleep(startTime - MSG_get_clock());
125         }
126         //Execution of the "run" method.
127         jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
128         xbt_assert( (id != NULL), "Method not found...");
129         (*env)->CallVoidMethod(env, context->jprocess, id);
130   }
131   smx_ctx_java_stop((smx_context_t)context);
132
133   return NULL;
134 }
135
136 static void smx_ctx_java_free(smx_context_t context)
137 {
138   if (context) {
139     smx_ctx_java_t ctx_java = (smx_ctx_java_t) context;
140     if (ctx_java->thread) { /* We are not in maestro context */
141       xbt_os_thread_join(ctx_java->thread, NULL);
142       xbt_os_sem_destroy(ctx_java->begin);
143       xbt_os_sem_destroy(ctx_java->end);
144     }
145   }
146   smx_ctx_base_free(context);
147 }
148
149
150 void smx_ctx_java_stop(smx_context_t context)
151 {
152   smx_ctx_java_t ctx_java = (smx_ctx_java_t)context;
153   /* I am the current process and I am dying */
154   if (context->iwannadie) {
155     context->iwannadie = 0;
156     JNIEnv *env = get_current_thread_env();
157     XBT_DEBUG("Gonna launch Killed Error");
158     // TODO Adrien, if the process has not been created at the java layer, why should we raise the exception/error at the java level (this happens
159     // for instance during the migration process that creates at the C level two processes: one on the SRC node and one on the DST node, if the DST process is killed. 
160     // it is not required to raise an exception at the JAVA level, the low level should be able to manage such an issue correctly but this is not the case right now unfortunately ...
161     // TODO it will be nice to have the name of the process to help the end-user to know which Process has been killed
162    // jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", MSG_process_get_name( (msg_process_t)context) ));
163     jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", simcall_process_get_name((smx_process_t) SIMIX_context_get_process(context))) );
164     XBT_DEBUG("Trigger a cancel error at the C level");
165     THROWF(cancel_error, 0, "process cancelled");
166   } else {
167     smx_ctx_base_stop(context);
168     /* detach the thread and kills it */
169     JNIEnv *env = ctx_java->jenv;
170     (*env)->DeleteGlobalRef(env,ctx_java->jprocess);
171     _XBT_GNUC_UNUSED jint error = (*__java_vm)->DetachCurrentThread(__java_vm);
172     xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
173     xbt_os_sem_release(((smx_ctx_java_t)context)->end);
174     xbt_os_thread_exit(NULL);
175   }
176 }
177
178 static void smx_ctx_java_suspend(smx_context_t context)
179 {
180   smx_ctx_java_t ctx_java = (smx_ctx_java_t) context;
181   xbt_os_sem_release(ctx_java->end);
182   xbt_os_sem_acquire(ctx_java->begin);
183 }
184
185 // FIXME: inline those functions
186 static void smx_ctx_java_resume(smx_context_t new_context)
187 {
188   smx_ctx_java_t ctx_java = (smx_ctx_java_t) new_context;
189   xbt_os_sem_release(ctx_java->begin);
190   xbt_os_sem_acquire(ctx_java->end);
191 }
192
193 static void smx_ctx_java_runall(void)
194 {
195   xbt_dynar_t processes = SIMIX_process_get_runnable();
196   smx_process_t process;
197   unsigned int cursor;
198   xbt_dynar_foreach(processes, cursor, process) {
199     smx_ctx_java_resume(SIMIX_process_get_context(process));
200   }
201 }