Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Many changes done.
[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 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
12                                 "Logging specific to SIMIX (process)");
13 /** \defgroup m_process_management Management Functions of Agents
14  *  \brief This section describes the agent structure of MSG
15  *  (#m_process_t) and the functions for managing it.
16  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Agents" --> \endhtmlonly
17  * 
18  *  We need to simulate many independent scheduling decisions, so
19  *  the concept of <em>process</em> is at the heart of the
20  *  simulator. A process may be defined as a <em>code</em>, with
21  *  some <em>private data</em>, executing in a <em>location</em>.
22  *  \see m_process_t
23  */
24
25 /******************************** Process ************************************/
26 /** \ingroup m_process_management
27  * \brief Creates and runs a new #m_process_t.
28  *
29  * Does exactly the same as #MSG_process_create_with_arguments but without 
30    providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time).
31  * \sa MSG_process_create_with_arguments
32  */
33 smx_process_t SIMIX_process_create(const char *name,
34                                smx_process_code_t code, void *data,
35                                const char * hostname, void * clean_process_function)
36 {
37   return SIMIX_process_create_with_arguments(name, code, data, hostname, -1, NULL, clean_process_function);
38 }
39
40 void SIMIX_process_cleanup(void *arg)
41 {
42   xbt_swag_remove(arg, simix_global->process_list);
43   xbt_swag_remove(arg, simix_global->process_to_run);
44   xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->host->simdata->process_list);
45   free(((smx_process_t) arg)->name);
46   ((smx_process_t) arg)->name = NULL;
47   free(((smx_process_t) arg)->simdata);
48   ((smx_process_t) arg)->simdata = NULL;
49   free(arg);
50 }
51
52 /** \ingroup m_process_management
53  * \brief Creates and runs a new #m_process_t.
54
55  * A constructor for #m_process_t taking four arguments and returning the 
56  * corresponding object. The structure (and the corresponding thread) is
57  * created, and put in the list of ready process.
58  * \param name a name for the object. It is for user-level information
59    and can be NULL.
60  * \param code is a function describing the behavior of the agent. It
61    should then only use functions described in \ref
62    m_process_management (to create a new #m_process_t for example),
63    in \ref m_host_management (only the read-only functions i.e. whose
64    name contains the word get), in \ref m_task_management (to create
65    or destroy some #m_task_t for example) and in \ref
66    msg_gos_functions (to handle file transfers and task processing).
67  * \param data a pointer to any data one may want to attach to the new
68    object.  It is for user-level information and can be NULL. It can
69    be retrieved with the function \ref MSG_process_get_data.
70  * \param host the location where the new agent is executed.
71  * \param argc first argument passed to \a code
72  * \param argv second argument passed to \a code
73  * \see m_process_t
74  * \return The new corresponding object.
75  */
76 smx_process_t SIMIX_process_create_with_arguments(const char *name,
77                                               smx_process_code_t code, void *data,
78                                               const char * hostname, int argc, char **argv, void * clean_process_function)
79 {
80   smx_simdata_process_t simdata = xbt_new0(s_smx_simdata_process_t,1);
81   smx_process_t process = xbt_new0(s_smx_process_t,1);
82   smx_process_t self = NULL;
83         smx_host_t host = SIMIX_host_get_by_name(hostname);
84
85   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
86   /* Simulator Data */
87
88   simdata->host = host;
89   simdata->argc = argc;
90   simdata->argv = argv;
91         if (clean_process_function) {
92         simdata->context = xbt_context_new(code, NULL, NULL, 
93                                              clean_process_function, process, 
94                                              simdata->argc, simdata->argv);
95         }
96         else {
97         simdata->context = xbt_context_new(code, NULL, NULL, 
98                                              SIMIX_process_cleanup, process, 
99                                              simdata->argc, simdata->argv);
100         }
101   //simdata->last_errno=SIMIX_OK;
102
103
104   /* Process structure */
105   process->name = xbt_strdup(name);
106   process->simdata = simdata;
107   process->data = data;
108
109   xbt_swag_insert(process, host->simdata->process_list);
110
111   /* *************** FIX du current_process !!! *************** */
112   self = simix_global->current_process;
113   xbt_context_start(process->simdata->context);
114   simix_global->current_process = self;
115
116   xbt_swag_insert(process,simix_global->process_list);
117   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
118          host->name);
119   xbt_swag_insert(process,simix_global->process_to_run);
120
121   return process;
122 }
123
124
125
126
127 /** \ingroup m_process_management
128  * \param process poor victim
129  *
130  * This function simply kills a \a process... scarry isn't it ? :)
131  */
132 void SIMIX_process_kill(smx_process_t process)
133 {
134   //int i;
135   smx_simdata_process_t p_simdata = process->simdata;
136   //simdata_host_t h_simdata= p_simdata->host->simdata;
137   //int _cursor;
138   //smx_process_t proc = NULL;
139
140   DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
141   
142         if (p_simdata->mutex) {
143                 xbt_swag_remove(process,p_simdata->mutex->sleeping);
144         }
145         if (p_simdata->cond) {
146                 xbt_swag_remove(process,p_simdata->cond->sleeping);
147         }
148   /*
149   
150   if(p_simdata->waiting_task) {
151     xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) {
152       if(proc==process) 
153         xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc);
154     }
155     if(p_simdata->waiting_task->simdata->compute)
156       surf_workstation_resource->common_public->
157         action_free(p_simdata->waiting_task->simdata->compute);
158     else if (p_simdata->waiting_task->simdata->comm) {
159       surf_workstation_resource->common_public->
160         action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
161       surf_workstation_resource->common_public->
162         action_free(p_simdata->waiting_task->simdata->comm);
163     } else {
164       xbt_die("UNKNOWN STATUS. Please report this bug.");
165     }
166   }
167
168   if ((i==msg_global->max_channel) && (process!=MSG_process_self()) && 
169       (!p_simdata->waiting_task)) {
170     xbt_die("UNKNOWN STATUS. Please report this bug.");
171   }
172 */
173   xbt_swag_remove(process,simix_global->process_to_run);
174   xbt_swag_remove(process,simix_global->process_list);
175   xbt_context_kill(process->simdata->context);
176
177   if(process==SIMIX_process_self()) {
178     /* I just killed myself */
179     xbt_context_yield();
180   }
181 }
182
183 /** \ingroup m_process_management
184  * \brief Return the user data of a #m_process_t.
185  *
186  * This functions checks whether \a process is a valid pointer or not 
187    and return the user data associated to \a process if it is possible.
188  */
189 void *SIMIX_process_get_data(smx_process_t process)
190 {
191   xbt_assert0((process != NULL), "Invalid parameters");
192
193   return (process->data);
194 }
195
196 /** \ingroup m_process_management
197  * \brief Set the user data of a #m_process_t.
198  *
199  * This functions checks whether \a process is a valid pointer or not 
200    and set the user data associated to \a process if it is possible.
201  */
202 void SIMIX_process_set_data(smx_process_t process,void *data)
203 {
204   xbt_assert0((process != NULL), "Invalid parameters");
205   xbt_assert0((process->data == NULL), "Data already set");
206   
207   process->data = data;
208    
209   return ;
210 }
211
212 /** \ingroup m_process_management
213  * \brief Return the location on which an agent is running.
214  *
215  * This functions checks whether \a process is a valid pointer or not 
216    and return the m_host_t corresponding to the location on which \a 
217    process is running.
218  */
219 smx_host_t SIMIX_process_get_host(smx_process_t process)
220 {
221   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
222
223   return (process->simdata->host);
224 }
225
226 /** \ingroup m_process_management
227  * \brief Return the name of an agent.
228  *
229  * This functions checks whether \a process is a valid pointer or not 
230    and return its name.
231  */
232 const char *SIMIX_process_get_name(smx_process_t process)
233 {
234   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
235
236   return (process->name);
237 }
238
239 /** \ingroup m_process_management
240  * \brief Return the current agent.
241  *
242  * This functions returns the currently running #m_process_t.
243  */
244 smx_process_t SIMIX_process_self(void)
245 {
246   return simix_global ? simix_global->current_process : NULL;
247 }
248
249 /** \ingroup m_process_management
250  * \brief Suspend the process.
251  *
252  * This functions suspend the process by suspending the task on which
253  * it was waiting for the completion.
254  */
255 void SIMIX_process_suspend(smx_process_t process)
256 {
257   smx_simdata_process_t simdata = NULL;
258         
259   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
260
261   if(process!=SIMIX_process_self()) {
262     simdata = process->simdata;
263     
264                 if (simdata->mutex) {
265                         /* process blocked on a mutex, only set suspend=1 */
266                         simdata->suspended = 1;
267                 }
268                 else if (simdata->cond){
269                         /* process blocked cond, suspend all actions */
270
271                         /* temporaries variables */ 
272                         smx_cond_t c;
273                         xbt_fifo_item_t i;
274                         smx_action_t act;
275
276                         simdata->suspended = 1;
277                         c = simdata->cond;
278                         xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
279                                 surf_workstation_resource->common_public->suspend(act->simdata->surf_action);
280                         }
281                 }
282                 else {
283                         simdata->suspended = 1;
284                 }
285   }
286         else {
287                 /* process executing, I can create an action and suspend it */
288                 process->simdata->suspended = 1;
289                 smx_action_t dummy;
290                 smx_cond_t cond;
291                 char name[] = "dummy";
292
293                 cond = SIMIX_cond_init();
294                 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
295                 surf_workstation_resource->common_public->set_priority(dummy->simdata->surf_action,0.0);
296                 SIMIX_register_condition_to_action(dummy,cond);
297                 SIMIX_register_action_to_condition(dummy,cond);
298                 __SIMIX_cond_wait(cond);        
299                 //SIMIX_action_destroy(dummy);
300                 //SIMIX_cond_destroy(cond);
301         }
302   return ;
303 }
304
305 /** \ingroup m_process_management
306  * \brief Resume a suspended process.
307  *
308  * This functions resume a suspended process by resuming the task on
309  * which it was waiting for the completion.
310  */
311 void SIMIX_process_resume(smx_process_t process)
312 {
313   smx_simdata_process_t simdata = NULL;
314
315   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
316   CHECK_HOST();
317
318   if(process == SIMIX_process_self()) {
319                 return; 
320   }
321
322   simdata = process->simdata;
323   if(simdata->mutex) {
324                 DEBUG0("Resume process blocked on a mutex");
325     simdata->suspended = 0; /* He'll wake up by itself */
326                 return; 
327   }
328         else if (simdata->cond) {
329                 DEBUG0("Resume process blocked on a conditional");
330                 /* temporaries variables */ 
331                 smx_cond_t c;
332                 xbt_fifo_item_t i;
333                 smx_action_t act;
334                 simdata->suspended = 0;
335                 c = simdata->cond;
336                 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
337                         surf_workstation_resource->common_public->resume(act->simdata->surf_action);
338                 }
339                 return;
340         }
341         else {
342                 simdata->suspended = 0;
343                 xbt_swag_insert(process,simix_global->process_to_run);
344         }
345
346 }
347
348 /** \ingroup m_process_management
349  * \brief Returns true if the process is suspended .
350  *
351  * This checks whether a process is suspended or not by inspecting the
352  * task on which it was waiting for the completion.
353  */
354 int SIMIX_process_is_suspended(smx_process_t process)
355 {
356   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
357
358   return (process->simdata->suspended);
359 }
360
361
362