Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Copyright corrected.
[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                                smx_host_t host)
36 {
37   return SIMIX_process_create_with_arguments(name, code, data, host, -1, NULL);
38 }
39
40 static 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                                               smx_host_t host, int argc, char **argv)
79 {
80   simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
81   smx_process_t process = xbt_new0(s_smx_process_t,1);
82   smx_process_t self = NULL;
83
84   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
85   /* Simulator Data */
86
87   simdata->host = host;
88   simdata->argc = argc;
89   simdata->argv = argv;
90   simdata->context = xbt_context_new(code, NULL, NULL, 
91                                      SIMIX_process_cleanup, process, 
92                                      simdata->argc, simdata->argv);
93
94   simdata->last_errno=SIMIX_OK;
95
96
97   /* Process structure */
98   process->name = xbt_strdup(name);
99   process->simdata = simdata;
100   process->data = data;
101
102   xbt_swag_insert_at_head(process, host->simdata->process_list);
103
104   /* *************** FIX du current_process !!! *************** */
105   self = simix_global->current_process;
106   xbt_context_start(process->simdata->context);
107   simix_global->current_process = self;
108
109   xbt_swag_insert_at_head(process,simix_global->process_list);
110   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
111          host->name);
112   xbt_swag_insert_at_head(process,simix_global->process_to_run);
113
114   return process;
115 }
116
117 /** \ingroup m_process_management
118  * \param process poor victim
119  *
120  * This function simply kills a \a process... scarry isn't it ? :)
121  */
122 void SIMIX_process_kill(smx_process_t process)
123 {
124   //int i;
125   simdata_process_t p_simdata = process->simdata;
126   //simdata_host_t h_simdata= p_simdata->host->simdata;
127   //int _cursor;
128   //smx_process_t proc = NULL;
129
130   DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
131   
132   /*
133   
134   if(p_simdata->waiting_task) {
135     xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) {
136       if(proc==process) 
137         xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc);
138     }
139     if(p_simdata->waiting_task->simdata->compute)
140       surf_workstation_resource->common_public->
141         action_free(p_simdata->waiting_task->simdata->compute);
142     else if (p_simdata->waiting_task->simdata->comm) {
143       surf_workstation_resource->common_public->
144         action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
145       surf_workstation_resource->common_public->
146         action_free(p_simdata->waiting_task->simdata->comm);
147     } else {
148       xbt_die("UNKNOWN STATUS. Please report this bug.");
149     }
150   }
151
152   if ((i==msg_global->max_channel) && (process!=MSG_process_self()) && 
153       (!p_simdata->waiting_task)) {
154     xbt_die("UNKNOWN STATUS. Please report this bug.");
155   }
156 */
157   xbt_swag_remove(process,simix_global->process_to_run);
158   xbt_swag_remove(process,simix_global->process_list);
159   xbt_context_free(process->simdata->context);
160
161   if(process==SIMIX_process_self()) {
162     /* I just killed myself */
163     xbt_context_yield();
164   }
165 }
166
167 /** \ingroup m_process_management
168  * \brief Migrates an agent to another location.
169  *
170  * This functions checks whether \a process and \a host are valid pointers
171    and change the value of the #m_host_t on which \a process is running.
172  */
173 SIMIX_error_t SIMIX_process_change_host(smx_process_t process, smx_host_t host)
174 {
175   simdata_process_t simdata = NULL;
176
177   /* Sanity check */
178
179   xbt_assert0(((process) && (process->simdata)
180           && (host)), "Invalid parameters");
181   simdata = process->simdata;
182
183   xbt_swag_remove(process,simdata->host->simdata->process_list);
184   simdata->host = host;
185   xbt_swag_insert_at_head(process,host->simdata->process_list);
186
187   return SIMIX_OK;
188 }
189
190 /** \ingroup m_process_management
191  * \brief Return the user data of a #m_process_t.
192  *
193  * This functions checks whether \a process is a valid pointer or not 
194    and return the user data associated to \a process if it is possible.
195  */
196 void *SIMIX_process_get_data(smx_process_t process)
197 {
198   xbt_assert0((process != NULL), "Invalid parameters");
199
200   return (process->data);
201 }
202
203 /** \ingroup m_process_management
204  * \brief Set the user data of a #m_process_t.
205  *
206  * This functions checks whether \a process is a valid pointer or not 
207    and set the user data associated to \a process if it is possible.
208  */
209 SIMIX_error_t 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 SIMIX_OK;
217 }
218
219 /** \ingroup m_process_management
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 
223    and return the m_host_t corresponding to the location on which \a 
224    process is running.
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 (((simdata_process_t) process->simdata)->host);
231 }
232
233 /** \ingroup m_process_management
234  * \brief Return the name of an agent.
235  *
236  * This functions checks whether \a process is a valid pointer or not 
237    and return its name.
238  */
239 const char *SIMIX_process_get_name(smx_process_t process)
240 {
241   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
242
243   return (process->name);
244 }
245
246 /** \ingroup m_process_management
247  * \brief Return the current agent.
248  *
249  * This functions returns the currently running #m_process_t.
250  */
251 smx_process_t SIMIX_process_self(void)
252 {
253   return simix_global ? simix_global->current_process : NULL;
254 }
255
256 /** \ingroup m_process_management
257  * \brief Suspend the process.
258  *
259  * This functions suspend the process by suspending the task on which
260  * it was waiting for the completion.
261  */
262 SIMIX_error_t SIMIX_process_suspend(smx_process_t process)
263 {
264 /*
265   simdata_process_t simdata = NULL;
266   simdata_task_t simdata_task = NULL;
267
268   XBT_IN2("(%p(%s))", process, process->name);
269
270   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
271
272   PAJE_PROCESS_PUSH_STATE(process,"S",NULL);
273
274   if(process!=SIMIX_process_self()) {
275     simdata = process->simdata;
276     
277     xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
278
279     simdata_task = simdata->waiting_task->simdata;
280
281     simdata->suspended = 1;
282     if(simdata->blocked) {
283       XBT_OUT;
284       return SIMIX_OK;
285     }
286
287     xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
288                 !((simdata_task->compute)&&(simdata_task->comm)),
289                 "Got a problem in deciding which action to choose !");
290     simdata->suspended = 1;
291     if(simdata_task->compute) 
292       surf_workstation_resource->common_public->suspend(simdata_task->compute);
293     else
294       surf_workstation_resource->common_public->suspend(simdata_task->comm);
295   } else {
296     m_task_t dummy = MSG_TASK_UNINITIALIZED;
297     dummy = MSG_task_create("suspended", 0.0, 0, NULL);
298
299     simdata = process->simdata;
300     simdata->suspended = 1;
301     __MSG_task_execute(process,dummy);
302     surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
303     __MSG_wait_for_computation(process,dummy);
304     simdata->suspended = 0;
305
306     MSG_task_destroy(dummy);
307   }
308   XBT_OUT;
309   */
310   return SIMIX_OK;
311 }
312
313 /** \ingroup m_process_management
314  * \brief Resume a suspended process.
315  *
316  * This functions resume a suspended process by resuming the task on
317  * which it was waiting for the completion.
318  */
319 SIMIX_error_t SIMIX_process_resume(smx_process_t process)
320 {
321 /*
322   simdata_process_t simdata = NULL;
323   simdata_task_t simdata_task = NULL;
324
325   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
326   CHECK_HOST();
327
328   XBT_IN2("(%p(%s))", process, process->name);
329
330   if(process == SIMIX_process_self()) {
331     XBT_OUT;
332     SIMIX_RETURN(SIMIX_OK);
333   }
334
335   simdata = process->simdata;
336
337   if(simdata->blocked) {
338     PAJE_PROCESS_POP_STATE(process);
339
340     simdata->suspended = 0; *//* He'll wake up by itself */
341     /*XBT_OUT;
342     SIMIX_RETURN(SIMIX_OK);
343   }
344
345   if(!(simdata->waiting_task)) {
346     xbt_assert0(0,"Process not waiting for anything else. Weird !");
347     XBT_OUT;
348     return SIMIX_WARNING;
349   }
350   simdata_task = simdata->waiting_task->simdata;
351
352
353   if(simdata_task->compute) {
354     surf_workstation_resource->common_public->resume(simdata_task->compute);
355     PAJE_PROCESS_POP_STATE(process);
356   }
357   else {
358     PAJE_PROCESS_POP_STATE(process);
359     surf_workstation_resource->common_public->resume(simdata_task->comm);
360   }
361
362   XBT_OUT;
363   */
364   SIMIX_RETURN(SIMIX_OK);
365 }
366
367 /** \ingroup m_process_management
368  * \brief Returns true if the process is suspended .
369  *
370  * This checks whether a process is suspended or not by inspecting the
371  * task on which it was waiting for the completion.
372  */
373 int SIMIX_process_is_suspended(smx_process_t process)
374 {
375   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
376
377   return (process->simdata->suspended);
378 }
379
380 int __SIMIX_process_block(double max_duration, const char *info)
381 {
382 /*
383   smx_process_t process = SIMIX_process_self();
384   m_task_t dummy = SIMIX_TASK_UNINITIALIZED;
385   char blocked_name[512];
386   snprintf(blocked_name,512,"blocked [%s] (%s:%s)",
387           info, process->name, process->simdata->host->name);
388
389   XBT_IN1(": max_duration=%g",max_duration);
390
391   dummy = MSG_task_create(blocked_name, 0.0, 0, NULL);
392   
393   PAJE_PROCESS_PUSH_STATE(process,"B",NULL);
394
395   process->simdata->blocked=1;
396   __MSG_task_execute(process,dummy);
397   surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
398   if(max_duration>=0)
399     surf_workstation_resource->common_public->set_max_duration(dummy->simdata->compute, 
400                                                                max_duration);
401   __MSG_wait_for_computation(process,dummy);
402   MSG_task_destroy(dummy);
403   process->simdata->blocked=0;
404
405   if(process->simdata->suspended) {
406     DEBUG0("I've been suspended in the meantime");    
407     SIMIX_process_suspend(process);
408     DEBUG0("I've been resumed, let's keep going");    
409   }
410
411   PAJE_PROCESS_POP_STATE(process);
412
413   XBT_OUT;
414   */
415   return 1;
416 }
417
418 SIMIX_error_t __SIMIX_process_unblock(smx_process_t process)
419 {
420 /*
421   simdata_process_t simdata = NULL;
422   simdata_task_t simdata_task = NULL;
423
424   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
425   CHECK_HOST();
426
427   XBT_IN2(": %s unblocking %s", SIMIX_process_self()->name,process->name);
428
429   simdata = process->simdata;
430   if(!(simdata->waiting_task)) {
431     xbt_assert0(0,"Process not waiting for anything else. Weird !");
432     XBT_OUT;
433     return SIMIX_WARNING;
434   }
435   simdata_task = simdata->waiting_task->simdata;
436
437   xbt_assert0(simdata->blocked,"Process not blocked");
438
439   surf_workstation_resource->common_public->resume(simdata_task->compute);
440
441   XBT_OUT;
442 */
443   SIMIX_RETURN(SIMIX_OK);
444 }
445
446 int __SIMIX_process_isBlocked(smx_process_t process)
447 {
448   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
449
450   return (process->simdata->blocked);
451 }