Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
c41798cc3e1510a87ecb3a1e749c7564b17bb709
[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    if (p_simdata->mutex) 
173       xbt_swag_remove(process,p_simdata->mutex->sleeping);
174    
175    if (p_simdata->cond) 
176       xbt_swag_remove(process,p_simdata->cond->sleeping);
177
178    xbt_swag_remove(process, simix_global->process_to_run);
179    xbt_swag_remove(process, simix_global->process_list);
180    xbt_context_kill(process->simdata->context);
181
182    if(process==SIMIX_process_self()) {
183       /* I just killed myself */
184       xbt_context_yield();
185    }
186 }
187
188 /**
189  * \brief Return the user data of a #smx_process_t.
190  *
191  * 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.
192  * \param process SIMIX process
193  * \return A void pointer to the user data
194  */
195 void *SIMIX_process_get_data(smx_process_t process)
196 {
197   xbt_assert0((process != NULL), "Invalid parameters");
198
199   return (process->data);
200 }
201
202 /**
203  * \brief Set the user data of a #m_process_t.
204  *
205  * 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.
206  * \param process SIMIX process
207  * \param data User data
208  */
209 void SIMIX_process_set_data(smx_process_t process,void *data)
210 {
211   xbt_assert0((process != NULL), "Invalid parameters");
212   //xbt_assert0((process->data == NULL), "Data already set");
213   
214   process->data = data;
215    
216   return ;
217 }
218
219 /**
220  * \brief Return the location on which an agent is running.
221  *
222  * 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.
223  * \param process SIMIX process
224  * \return SIMIX host
225  */
226 smx_host_t SIMIX_process_get_host(smx_process_t process)
227 {
228   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
229
230   return (process->simdata->s_host);
231 }
232
233 /**
234  * \brief Return the name of an agent.
235  *
236  * This functions checks whether \a process is a valid pointer or not and return its name.
237  * \param process SIMIX process
238  * \return The process name
239  */
240 const char *SIMIX_process_get_name(smx_process_t process)
241 {
242   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
243
244   return (process->name);
245 }
246
247 /**
248  * \brief Return the current agent.
249  *
250  * This functions returns the currently running #smx_process_t.
251  * \return The SIMIX process
252  */
253 smx_process_t SIMIX_process_self(void)
254 {
255   return simix_global ? simix_global->current_process : NULL;
256 }
257
258 /**
259  * \brief Suspend the process.
260  *
261  * This functions suspend the process by suspending the action on which it was waiting for the completion.
262  *      \param process SIMIX process
263  */
264 void SIMIX_process_suspend(smx_process_t process)
265 {
266   smx_simdata_process_t simdata = NULL;
267         
268   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
269
270   if(process!=SIMIX_process_self()) {
271     simdata = process->simdata;
272     
273                 if (simdata->mutex) {
274                         /* process blocked on a mutex, only set suspend=1 */
275                         simdata->suspended = 1;
276                 }
277                 else if (simdata->cond){
278                         /* process blocked cond, suspend all actions */
279
280                         /* temporaries variables */ 
281                         smx_cond_t c;
282                         xbt_fifo_item_t i;
283                         smx_action_t act;
284
285                         simdata->suspended = 1;
286                         c = simdata->cond;
287                         xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
288                                 surf_workstation_resource->common_public->suspend(act->simdata->surf_action);
289                         }
290                 }
291                 else {
292                         simdata->suspended = 1;
293                 }
294   }
295         else {
296                 /* process executing, I can create an action and suspend it */
297                 process->simdata->suspended = 1;
298                 smx_action_t dummy;
299                 smx_cond_t cond;
300                 char name[] = "dummy";
301
302                 cond = SIMIX_cond_init();
303                 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
304                 surf_workstation_resource->common_public->set_priority(dummy->simdata->surf_action,0.0);
305                 SIMIX_register_condition_to_action(dummy,cond);
306                 SIMIX_register_action_to_condition(dummy,cond);
307                 __SIMIX_cond_wait(cond);        
308                 //SIMIX_action_destroy(dummy);
309                 //SIMIX_cond_destroy(cond);
310         }
311   return ;
312 }
313
314 /**
315  * \brief Resume a suspended process.
316  *
317  * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
318  * \param process SIMIX process
319  */
320 void SIMIX_process_resume(smx_process_t process)
321 {
322   smx_simdata_process_t simdata = NULL;
323
324   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
325   SIMIX_CHECK_HOST();
326
327   if(process == SIMIX_process_self()) {
328                 return; 
329   }
330
331   simdata = process->simdata;
332   if(simdata->mutex) {
333                 DEBUG0("Resume process blocked on a mutex");
334     simdata->suspended = 0; /* He'll wake up by itself */
335                 return; 
336   }
337         else if (simdata->cond) {
338                 DEBUG0("Resume process blocked on a conditional");
339                 /* temporaries variables */ 
340                 smx_cond_t c;
341                 xbt_fifo_item_t i;
342                 smx_action_t act;
343                 simdata->suspended = 0;
344                 c = simdata->cond;
345                 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
346                         surf_workstation_resource->common_public->resume(act->simdata->surf_action);
347                 }
348                 return;
349         }
350         else {
351                 simdata->suspended = 0;
352                 xbt_swag_insert(process,simix_global->process_to_run);
353         }
354
355 }
356
357 /**
358  * \brief Returns true if the process is suspended .
359  *
360  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
361  * \param process SIMIX process
362  * \return 1, if the process is suspended, else 0.
363  */
364 int SIMIX_process_is_suspended(smx_process_t process)
365 {
366   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
367
368   return (process->simdata->suspended);
369 }
370
371
372 /* Helper functions for jMSG: manipulate the context data without breaking the module separation */
373 #include "xbt/context.h" /* to pass java objects from MSG to the context */
374
375 void SIMIX_process_set_jprocess(smx_process_t process, void *jp) {
376    xbt_context_set_jprocess(process->simdata->context,jp);
377 }
378 void* SIMIX_process_get_jprocess(smx_process_t process) {
379    return xbt_context_get_jprocess(process->simdata->context);
380 }
381
382 void SIMIX_process_set_jmutex(smx_process_t process, void *jm) {
383    xbt_context_set_jmutex(process->simdata->context,jm);
384 }
385 void* SIMIX_process_get_jmutex(smx_process_t process) {
386    return xbt_context_get_jmutex(process->simdata->context);
387 }
388
389 void SIMIX_process_set_jcond(smx_process_t process, void *jc) {
390    xbt_context_set_jcond(process->simdata->context,jc);
391 }
392 void* SIMIX_process_get_jcond(smx_process_t process) {
393    return xbt_context_get_jcond(process->simdata->context);
394 }
395
396 void SIMIX_process_set_jenv(smx_process_t process, void *je) {
397    xbt_context_set_jenv(process->simdata->context,je);
398 }
399 void* SIMIX_process_get_jenv(smx_process_t process) {
400    return xbt_context_get_jenv(process->simdata->context);
401 }
402