Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
hack around the place to get the initialization phase of java working + cosmetics
[simgrid.git] / src / simix / smx_process.c
1 //*     $Id$     */
2
3 /* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved.        */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "private.h"
9 #include "xbt/sysdep.h"
10 #include "xbt/log.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
13                                 "Logging specific to SIMIX (process)");
14
15 /******************************** Process ************************************/
16 /**
17  * \brief Creates and runs a new #smx_process_t.
18  *
19  * Does exactly the same as #SIMIX_process_create_with_arguments but without 
20    providing standard arguments (\a argc, \a argv).
21  * \see SIMIX_process_create_with_arguments
22  */
23
24
25 void SIMIX_process_cleanup(void *arg)
26 {
27   xbt_swag_remove(arg, simix_global->process_list);
28   xbt_swag_remove(arg, simix_global->process_to_run);
29   xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->s_host->simdata->process_list);
30   free(((smx_process_t) arg)->name);
31   ((smx_process_t) arg)->name = NULL;
32
33   free(((smx_process_t) arg)->simdata);
34   ((smx_process_t) arg)->simdata = NULL;
35   free(arg);
36 }
37
38 /** 
39  * \brief Creates and runs a new #smx_process_t.
40  *
41  * A constructor for #m_process_t taking four arguments and returning the corresponding object. The structure (and the corresponding thread) is created, and put in the list of ready process.
42  *
43  * \param name a name for the object. It is for user-level information and can be NULL.
44 * \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data.
45  * \param host the location where the new agent is executed.
46  * \param argc first argument passed to \a code
47  * \param argv second argument passed to \a code
48  * \param clean_process_function The cleanup function of user process. It will be called when the process finish. This function have to call the SIMIX_process_cleanup. 
49  * \see smx_process_t
50  * \return The new corresponding object.
51  */
52 smx_process_t SIMIX_process_create(const char *name,
53                                    smx_process_code_t code, void *data,
54                                    const char * hostname, int argc, char **argv, 
55                                    void * clean_process_function)
56 {
57   smx_simdata_process_t simdata = xbt_new0(s_smx_simdata_process_t,1);
58   smx_process_t process = xbt_new0(s_smx_process_t,1);
59   smx_process_t self = NULL;
60   smx_host_t host = SIMIX_host_get_by_name(hostname);
61
62   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
63   /* Simulator Data */
64
65   simdata->s_host = host;
66         simdata->mutex = NULL;
67         simdata->cond = NULL;
68   simdata->argc = argc;
69   simdata->argv = argv;
70         if (clean_process_function) {
71         simdata->context = xbt_context_new(code, NULL, NULL, 
72                                              clean_process_function, process, 
73                                              simdata->argc, simdata->argv);
74         }
75         else {
76         simdata->context = xbt_context_new(code, NULL, NULL, 
77                                              SIMIX_process_cleanup, process, 
78                                              simdata->argc, simdata->argv);
79         }
80
81   /* Process structure */
82   process->name = xbt_strdup(name);
83   process->simdata = simdata;
84   process->data = data;
85
86   xbt_swag_insert(process, host->simdata->process_list);
87
88   /* fix current_process, about which xbt_context_start mocks around */
89   self = simix_global->current_process;
90   xbt_context_start(process->simdata->context);
91   simix_global->current_process = self;
92
93   xbt_swag_insert(process,simix_global->process_list);
94   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
95          host->name);
96   xbt_swag_insert(process,simix_global->process_to_run);
97
98   return process;
99 }
100
101 /** 
102  * \brief Creates and runs a new #smx_process_t hosting a JAVA thread
103  *
104  * Warning: this should only be used in libsimgrid4java, since it create
105  * a context with no code, which leads to segfaults in plain libsimgrid 
106  */
107 void SIMIX_jprocess_create(const char *name, smx_host_t host,
108                            void *data,
109                            void *jprocess, void *jenv,
110                            void *clean_process_function,
111                            smx_process_t *res)
112 {
113   smx_simdata_process_t simdata = xbt_new0(s_smx_simdata_process_t,1);
114   smx_process_t process = xbt_new0(s_smx_process_t,1);
115   smx_process_t self = NULL;
116
117   /* HACK: We need this trick because when we xbt_context_new() do
118      syncronization stuff, the s_process field in the m_process needs 
119      to have a valid value, and we call xbt_context_new() before 
120      returning, of course, ie, before providing a right value to the 
121      caller (Java_simgrid_msg_Msg_processCreate) have time to store it  
122      in place. This way, we initialize the m_process->simdata->s_process 
123      field ourself ASAP.
124
125      All this would be much simpler if the synchronization stuff would be done
126      in the JAVA world, I think.
127   */
128   *res= process; 
129
130
131
132   DEBUG5("jprocess_create(name=%s,host=%p,data=%p,jproc=%p,jenv=%p)",
133          name,host,data,jprocess,jenv);
134   xbt_assert0(host, "Invalid parameters");
135   /* Simulator Data */
136   simdata->s_host = host;
137   simdata->mutex = NULL;
138   simdata->cond = NULL;
139   simdata->argc = 0;
140   simdata->argv = NULL;
141   
142    if (clean_process_function) {
143       simdata->context = xbt_context_new(NULL, NULL, NULL, 
144                                          clean_process_function, process, 
145                                          /* argc/argv*/0,NULL);
146    } else {
147       simdata->context = xbt_context_new(NULL, NULL, NULL, 
148                                          SIMIX_process_cleanup, process, 
149                                          /* argc/argv*/0,NULL);
150    }
151
152   /* Process structure */
153   process->name = xbt_strdup(name);
154   process->simdata = simdata; 
155   process->data = data;
156   SIMIX_process_set_jprocess(process,jprocess);
157   SIMIX_process_set_jenv(process,jenv);
158
159   xbt_swag_insert(process, host->simdata->process_list);
160
161   /* fix current_process, about which xbt_context_start mocks around */
162   self = simix_global->current_process;
163   xbt_context_start(process->simdata->context);
164   simix_global->current_process = self;
165
166   xbt_swag_insert(process,simix_global->process_list);
167   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
168          host->name);
169   xbt_swag_insert(process,simix_global->process_to_run);
170
171 }
172
173
174 /** \brief Kill a SIMIX process
175  *
176  * This function simply kills a \a process... scarry isn't it ? :).
177  * \param process poor victim
178  *
179  */
180 void SIMIX_process_kill(smx_process_t process)
181 {       
182    smx_simdata_process_t p_simdata = process->simdata;
183
184    DEBUG2("Killing process %s on %s",process->name, p_simdata->s_host->name);
185   
186    /* Cleanup if we were waiting for something */
187    if (p_simdata->mutex) 
188       xbt_swag_remove(process,p_simdata->mutex->sleeping);
189    
190    if (p_simdata->cond) 
191       xbt_swag_remove(process,p_simdata->cond->sleeping);
192
193    xbt_swag_remove(process, simix_global->process_to_run);
194    xbt_swag_remove(process, simix_global->process_list);
195    xbt_context_kill(process->simdata->context);
196
197    if(process==SIMIX_process_self()) {
198       /* I just killed myself */
199       xbt_context_yield();
200    }
201 }
202
203 /**
204  * \brief Return the user data of a #smx_process_t.
205  *
206  * This functions checks whether \a process is a valid pointer or not and return the user data associated to \a process if it is possible.
207  * \param process SIMIX process
208  * \return A void pointer to the user data
209  */
210 void *SIMIX_process_get_data(smx_process_t process)
211 {
212   xbt_assert0((process != NULL), "Invalid parameters");
213
214   return (process->data);
215 }
216
217 /**
218  * \brief Set the user data of a #m_process_t.
219  *
220  * This functions checks whether \a process is a valid pointer or not and set the user data associated to \a process if it is possible.
221  * \param process SIMIX process
222  * \param data User data
223  */
224 void SIMIX_process_set_data(smx_process_t process,void *data)
225 {
226   xbt_assert0((process != NULL), "Invalid parameters");
227   xbt_assert0((process->data == NULL), "Data already set");
228   
229   process->data = data;
230    
231   return ;
232 }
233
234 /**
235  * \brief Return the location on which an agent is running.
236  *
237  * This functions checks whether \a process is a valid pointer or not and return the m_host_t corresponding to the location on which \a process is running.
238  * \param process SIMIX process
239  * \return SIMIX host
240  */
241 smx_host_t SIMIX_process_get_host(smx_process_t process)
242 {
243   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
244
245   return (process->simdata->s_host);
246 }
247
248 /**
249  * \brief Return the name of an agent.
250  *
251  * This functions checks whether \a process is a valid pointer or not and return its name.
252  * \param process SIMIX process
253  * \return The process name
254  */
255 const char *SIMIX_process_get_name(smx_process_t process)
256 {
257   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
258
259   return (process->name);
260 }
261
262 /**
263  * \brief Return the current agent.
264  *
265  * This functions returns the currently running #smx_process_t.
266  * \return The SIMIX process
267  */
268 smx_process_t SIMIX_process_self(void)
269 {
270   return simix_global ? simix_global->current_process : NULL;
271 }
272
273 /**
274  * \brief Suspend the process.
275  *
276  * This functions suspend the process by suspending the action on which it was waiting for the completion.
277  *      \param process SIMIX process
278  */
279 void SIMIX_process_suspend(smx_process_t process)
280 {
281   smx_simdata_process_t simdata = NULL;
282         
283   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
284
285   if(process!=SIMIX_process_self()) {
286     simdata = process->simdata;
287     
288                 if (simdata->mutex) {
289                         /* process blocked on a mutex, only set suspend=1 */
290                         simdata->suspended = 1;
291                 }
292                 else if (simdata->cond){
293                         /* process blocked cond, suspend all actions */
294
295                         /* temporaries variables */ 
296                         smx_cond_t c;
297                         xbt_fifo_item_t i;
298                         smx_action_t act;
299
300                         simdata->suspended = 1;
301                         c = simdata->cond;
302                         xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
303                                 surf_workstation_resource->common_public->suspend(act->simdata->surf_action);
304                         }
305                 }
306                 else {
307                         simdata->suspended = 1;
308                 }
309   }
310         else {
311                 /* process executing, I can create an action and suspend it */
312                 process->simdata->suspended = 1;
313                 smx_action_t dummy;
314                 smx_cond_t cond;
315                 char name[] = "dummy";
316
317                 cond = SIMIX_cond_init();
318                 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
319                 surf_workstation_resource->common_public->set_priority(dummy->simdata->surf_action,0.0);
320                 SIMIX_register_condition_to_action(dummy,cond);
321                 SIMIX_register_action_to_condition(dummy,cond);
322                 __SIMIX_cond_wait(cond);        
323                 //SIMIX_action_destroy(dummy);
324                 //SIMIX_cond_destroy(cond);
325         }
326   return ;
327 }
328
329 /**
330  * \brief Resume a suspended process.
331  *
332  * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
333  * \param process SIMIX process
334  */
335 void SIMIX_process_resume(smx_process_t process)
336 {
337   smx_simdata_process_t simdata = NULL;
338
339   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
340   SIMIX_CHECK_HOST();
341
342   if(process == SIMIX_process_self()) {
343                 return; 
344   }
345
346   simdata = process->simdata;
347   if(simdata->mutex) {
348                 DEBUG0("Resume process blocked on a mutex");
349     simdata->suspended = 0; /* He'll wake up by itself */
350                 return; 
351   }
352         else if (simdata->cond) {
353                 DEBUG0("Resume process blocked on a conditional");
354                 /* temporaries variables */ 
355                 smx_cond_t c;
356                 xbt_fifo_item_t i;
357                 smx_action_t act;
358                 simdata->suspended = 0;
359                 c = simdata->cond;
360                 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
361                         surf_workstation_resource->common_public->resume(act->simdata->surf_action);
362                 }
363                 return;
364         }
365         else {
366                 simdata->suspended = 0;
367                 xbt_swag_insert(process,simix_global->process_to_run);
368         }
369
370 }
371
372 /**
373  * \brief Returns true if the process is suspended .
374  *
375  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
376  * \param process SIMIX process
377  * \return 1, if the process is suspended, else 0.
378  */
379 int SIMIX_process_is_suspended(smx_process_t process)
380 {
381   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
382
383   return (process->simdata->suspended);
384 }
385
386
387 /* Helper functions for jMSG: manipulate the context data without breaking the module separation */
388 #include "xbt/context.h" /* to pass java objects from MSG to the context */
389
390 void SIMIX_process_set_jprocess(smx_process_t process, void *jp) {
391    xbt_context_set_jprocess(process->simdata->context,jp);
392 }
393 void* SIMIX_process_get_jprocess(smx_process_t process) {
394    return xbt_context_get_jprocess(process->simdata->context);
395 }
396
397 void SIMIX_process_set_jmutex(smx_process_t process, void *jm) {
398    xbt_context_set_jmutex(process->simdata->context,jm);
399 }
400 void* SIMIX_process_get_jmutex(smx_process_t process) {
401    return xbt_context_get_jmutex(process->simdata->context);
402 }
403
404 void SIMIX_process_set_jcond(smx_process_t process, void *jc) {
405    xbt_context_set_jcond(process->simdata->context,jc);
406 }
407 void* SIMIX_process_get_jcond(smx_process_t process) {
408    return xbt_context_get_jcond(process->simdata->context);
409 }
410
411 void SIMIX_process_set_jenv(smx_process_t process, void *je) {
412    xbt_context_set_jenv(process->simdata->context,je);
413 }
414 void* SIMIX_process_get_jenv(smx_process_t process) {
415    return xbt_context_get_jenv(process->simdata->context);
416 }
417