Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Functions added and changed. Keeps the cvs updated.
[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 smx_process_t SIMIX_process_create(const char *name,
24                                smx_process_code_t code, void *data,
25                                const char * hostname, void * clean_process_function)
26 {
27   return SIMIX_process_create_with_arguments(name, code, data, hostname, -1, NULL, clean_process_function);
28 }
29
30 void SIMIX_process_cleanup(void *arg)
31 {
32   xbt_swag_remove(arg, simix_global->process_list);
33   xbt_swag_remove(arg, simix_global->process_to_run);
34   xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->host->simdata->process_list);
35   free(((smx_process_t) arg)->name);
36   ((smx_process_t) arg)->name = NULL;
37
38   free(((smx_process_t) arg)->simdata);
39   ((smx_process_t) arg)->simdata = NULL;
40   free(arg);
41 }
42
43 /** 
44  * \brief Creates and runs a new #smx_process_t.
45  *
46  * 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.
47  *
48  * \param name a name for the object. It is for user-level information and can be NULL.
49 * \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.
50  * \param host the location where the new agent is executed.
51  * \param argc first argument passed to \a code
52  * \param argv second argument passed to \a code
53  * \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. 
54  * \see smx_process_t
55  * \return The new corresponding object.
56  */
57 smx_process_t SIMIX_process_create_with_arguments(const char *name,
58                                               smx_process_code_t code, void *data,
59                                               const char * hostname, int argc, char **argv, void * clean_process_function)
60 {
61   smx_simdata_process_t simdata = xbt_new0(s_smx_simdata_process_t,1);
62   smx_process_t process = xbt_new0(s_smx_process_t,1);
63   smx_process_t self = NULL;
64         smx_host_t host = SIMIX_host_get_by_name(hostname);
65
66   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
67   /* Simulator Data */
68
69   simdata->host = host;
70         simdata->mutex = NULL;
71         simdata->cond = NULL;
72   simdata->argc = argc;
73   simdata->argv = argv;
74         if (clean_process_function) {
75         simdata->context = xbt_context_new(code, NULL, NULL, 
76                                              clean_process_function, process, 
77                                              simdata->argc, simdata->argv);
78         }
79         else {
80         simdata->context = xbt_context_new(code, NULL, NULL, 
81                                              SIMIX_process_cleanup, process, 
82                                              simdata->argc, simdata->argv);
83         }
84
85   /* Process structure */
86   process->name = xbt_strdup(name);
87   process->simdata = simdata;
88   process->data = data;
89
90   xbt_swag_insert(process, host->simdata->process_list);
91
92   /* *************** FIX du current_process !!! *************** */
93   self = simix_global->current_process;
94   xbt_context_start(process->simdata->context);
95   simix_global->current_process = self;
96
97   xbt_swag_insert(process,simix_global->process_list);
98   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
99          host->name);
100   xbt_swag_insert(process,simix_global->process_to_run);
101
102   return process;
103 }
104
105
106 /** \brief Kill a SIMIX process
107  *
108  * This function simply kills a \a process... scarry isn't it ? :). Removes it from the mutex or condition that it can be blocked.
109  * \param process poor victim
110  *
111  */
112 void SIMIX_process_kill(smx_process_t process)
113 {       
114   smx_simdata_process_t p_simdata = process->simdata;
115
116   DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
117   
118         if (p_simdata->mutex) {
119                 xbt_swag_remove(process,p_simdata->mutex->sleeping);
120         }
121         if (p_simdata->cond) {
122                 xbt_swag_remove(process,p_simdata->cond->sleeping);
123         }
124   xbt_swag_remove(process,simix_global->process_to_run);
125   xbt_swag_remove(process,simix_global->process_list);
126   xbt_context_kill(process->simdata->context);
127
128   if(process==SIMIX_process_self()) {
129     /* I just killed myself */
130     xbt_context_yield();
131   }
132 }
133
134 /**
135  * \brief Return the user data of a #smx_process_t.
136  *
137  * 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.
138  * \param process SIMIX process
139  * \return A void pointer to the user data
140  */
141 void *SIMIX_process_get_data(smx_process_t process)
142 {
143   xbt_assert0((process != NULL), "Invalid parameters");
144
145   return (process->data);
146 }
147
148 /**
149  * \brief Set the user data of a #m_process_t.
150  *
151  * 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.
152  * \param process SIMIX process
153  * \param data User data
154  */
155 void SIMIX_process_set_data(smx_process_t process,void *data)
156 {
157   xbt_assert0((process != NULL), "Invalid parameters");
158   xbt_assert0((process->data == NULL), "Data already set");
159   
160   process->data = data;
161    
162   return ;
163 }
164
165 /**
166  * \brief Return the location on which an agent is running.
167  *
168  * 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.
169  * \param process SIMIX process
170  * \return SIMIX host
171  */
172 smx_host_t SIMIX_process_get_host(smx_process_t process)
173 {
174   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
175
176   return (process->simdata->host);
177 }
178
179 /**
180  * \brief Return the name of an agent.
181  *
182  * This functions checks whether \a process is a valid pointer or not and return its name.
183  * \param process SIMIX process
184  * \return The process name
185  */
186 const char *SIMIX_process_get_name(smx_process_t process)
187 {
188   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
189
190   return (process->name);
191 }
192
193 /**
194  * \brief Return the current agent.
195  *
196  * This functions returns the currently running #smx_process_t.
197  * \return The SIMIX process
198  */
199 smx_process_t SIMIX_process_self(void)
200 {
201   return simix_global ? simix_global->current_process : NULL;
202 }
203
204 /**
205  * \brief Suspend the process.
206  *
207  * This functions suspend the process by suspending the action on which it was waiting for the completion.
208  *      \param process SIMIX process
209  */
210 void SIMIX_process_suspend(smx_process_t process)
211 {
212   smx_simdata_process_t simdata = NULL;
213         
214   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
215
216   if(process!=SIMIX_process_self()) {
217     simdata = process->simdata;
218     
219                 if (simdata->mutex) {
220                         /* process blocked on a mutex, only set suspend=1 */
221                         simdata->suspended = 1;
222                 }
223                 else if (simdata->cond){
224                         /* process blocked cond, suspend all actions */
225
226                         /* temporaries variables */ 
227                         smx_cond_t c;
228                         xbt_fifo_item_t i;
229                         smx_action_t act;
230
231                         simdata->suspended = 1;
232                         c = simdata->cond;
233                         xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
234                                 surf_workstation_resource->common_public->suspend(act->simdata->surf_action);
235                         }
236                 }
237                 else {
238                         simdata->suspended = 1;
239                 }
240   }
241         else {
242                 /* process executing, I can create an action and suspend it */
243                 process->simdata->suspended = 1;
244                 smx_action_t dummy;
245                 smx_cond_t cond;
246                 char name[] = "dummy";
247
248                 cond = SIMIX_cond_init();
249                 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
250                 surf_workstation_resource->common_public->set_priority(dummy->simdata->surf_action,0.0);
251                 SIMIX_register_condition_to_action(dummy,cond);
252                 SIMIX_register_action_to_condition(dummy,cond);
253                 __SIMIX_cond_wait(cond);        
254                 //SIMIX_action_destroy(dummy);
255                 //SIMIX_cond_destroy(cond);
256         }
257   return ;
258 }
259
260 /**
261  * \brief Resume a suspended process.
262  *
263  * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
264  * \param process SIMIX process
265  */
266 void SIMIX_process_resume(smx_process_t process)
267 {
268   smx_simdata_process_t simdata = NULL;
269
270   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
271   CHECK_HOST();
272
273   if(process == SIMIX_process_self()) {
274                 return; 
275   }
276
277   simdata = process->simdata;
278   if(simdata->mutex) {
279                 DEBUG0("Resume process blocked on a mutex");
280     simdata->suspended = 0; /* He'll wake up by itself */
281                 return; 
282   }
283         else if (simdata->cond) {
284                 DEBUG0("Resume process blocked on a conditional");
285                 /* temporaries variables */ 
286                 smx_cond_t c;
287                 xbt_fifo_item_t i;
288                 smx_action_t act;
289                 simdata->suspended = 0;
290                 c = simdata->cond;
291                 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
292                         surf_workstation_resource->common_public->resume(act->simdata->surf_action);
293                 }
294                 return;
295         }
296         else {
297                 simdata->suspended = 0;
298                 xbt_swag_insert(process,simix_global->process_to_run);
299         }
300
301 }
302
303 /**
304  * \brief Returns true if the process is suspended .
305  *
306  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
307  * \param process SIMIX process
308  * \return 1, if the process is suspended, else 0.
309  */
310 int SIMIX_process_is_suspended(smx_process_t process)
311 {
312   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
313
314   return (process->simdata->suspended);
315 }
316
317
318