Logo AND Algorithmique Numérique Distribuée

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