Logo AND Algorithmique Numérique Distribuée

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