Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix issues in documentation
[simgrid.git] / src / simix / smx_user.c
1 /* smx_user.c - public interface to simix                                   */
2
3 /* Copyright (c) 2010, 2011. Da SimGrid team. 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 #ifndef _SVID_SOURCE
8 #  define _SVID_SOURCE    /* strdup() */
9 #endif
10 #ifndef _ISOC99_SOURCE
11 #  define _ISOC99_SOURCE  /* isfinite() */
12 #endif
13 #ifndef _ISO_C99_SOURCE
14 #  define _ISO_C99_SOURCE /* isfinite() */
15 #endif
16 #include <math.h>         /* isfinite() */
17
18 #include "smx_private.h"
19 #include "mc/mc.h"
20 #include "xbt/ex.h"
21
22 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
23
24 static const char* simcall_names[] = {
25 #undef SIMCALL_ENUM_ELEMENT
26 #define SIMCALL_ENUM_ELEMENT(x) #x /* generate strings from the enumeration values */
27 SIMCALL_LIST
28 #undef SIMCALL_ENUM_ELEMENT
29 };
30
31 /**
32  * \brief Returns a host given its name.
33  *
34  * \param name The name of the host to get
35  * \return The corresponding host
36  */
37 smx_host_t simcall_host_get_by_name(const char *name)
38 {
39   smx_simcall_t simcall = SIMIX_simcall_mine();
40
41   simcall->call = SIMCALL_HOST_GET_BY_NAME;
42   simcall->host_get_by_name.name = name;
43   SIMIX_simcall_push(simcall->issuer);
44   return simcall->host_get_by_name.result;
45 }
46
47 /**
48  * \brief Returns the name of a host.
49  *
50  * \param host A SIMIX host
51  * \return The name of this host
52  */
53 const char* simcall_host_get_name(smx_host_t host)
54 {
55   smx_simcall_t simcall = SIMIX_simcall_mine();
56
57   simcall->call = SIMCALL_HOST_GET_NAME;
58   simcall->host_get_name.host = host;
59   SIMIX_simcall_push(simcall->issuer);
60   return simcall->host_get_name.result;
61 }
62
63 /**
64  * \brief Returns a dict of the properties assigned to a host.
65  *
66  * \param host A host
67  * \return The properties of this host
68  */
69 xbt_dict_t simcall_host_get_properties(smx_host_t host)
70 {
71   smx_simcall_t simcall = SIMIX_simcall_mine();
72
73   simcall->call = SIMCALL_HOST_GET_PROPERTIES;
74   simcall->host_get_properties.host = host;
75   SIMIX_simcall_push(simcall->issuer);
76   return simcall->host_get_properties.result;
77 }
78
79 /**
80  * \brief Returns the speed of the processor.
81  *
82  * The speed returned does not take into account the current load on the machine.
83  * \param host A SIMIX host
84  * \return The speed of this host (in Mflop/s)
85  */
86 double simcall_host_get_speed(smx_host_t host)
87 {
88   smx_simcall_t simcall = SIMIX_simcall_mine();
89
90   simcall->call = SIMCALL_HOST_GET_SPEED;
91   simcall->host_get_speed.host = host;
92   SIMIX_simcall_push(simcall->issuer);
93   return simcall->host_get_speed.result;
94 }
95
96 /**
97  * \brief Returns the available speed of the processor.
98  *
99  * \return Speed currently available (in Mflop/s)
100  */
101 double simcall_host_get_available_speed(smx_host_t host)
102 {
103   smx_simcall_t simcall = SIMIX_simcall_mine();
104
105   simcall->call = SIMCALL_HOST_GET_AVAILABLE_SPEED;
106   simcall->host_get_available_speed.host = host;
107   SIMIX_simcall_push(simcall->issuer);
108   return simcall->host_get_available_speed.result;
109 }
110
111 /**
112  * \brief Returns the state of a host.
113  *
114  * Two states are possible: 1 if the host is active or 0 if it has crashed.
115  * \param host A SIMIX host
116  * \return 1 if the host is available, 0 otherwise
117  */
118 int simcall_host_get_state(smx_host_t host)
119 {
120   smx_simcall_t simcall = SIMIX_simcall_mine();
121
122   simcall->call = SIMCALL_HOST_GET_STATE;
123   simcall->host_get_state.host = host;
124   SIMIX_simcall_push(simcall->issuer);
125   return simcall->host_get_state.result;
126 }
127
128 /**
129  * \brief Returns the user data associated to a host.
130  *
131  * \param host SIMIX host
132  * \return the user data of this host
133  */
134 void* simcall_host_get_data(smx_host_t host)
135 {
136   smx_simcall_t simcall = SIMIX_simcall_mine();
137
138   simcall->call = SIMCALL_HOST_GET_DATA;
139   simcall->host_get_data.host = host;
140   SIMIX_simcall_push(simcall->issuer);
141   return simcall->host_get_data.result;
142 }
143
144 /**
145  * \brief Sets the user data associated to a host.
146  *
147  * The host must not have previous user data associated to it.
148  * \param A host SIMIX host
149  * \param data The user data to set
150  */
151 void simcall_host_set_data(smx_host_t host, void *data)
152 {
153   smx_simcall_t simcall = SIMIX_simcall_mine();
154
155   simcall->call = SIMCALL_HOST_SET_DATA;
156   simcall->host_set_data.host = host;
157   simcall->host_set_data.data = data;
158   SIMIX_simcall_push(simcall->issuer);
159 }
160
161 /** \brief Creates an action that executes some computation of an host.
162  *
163  * This function creates a SURF action and allocates the data necessary
164  * to create the SIMIX action. It can raise a host_error exception if the host crashed.
165  *
166  * \param name Name of the execution action to create
167  * \param host SIMIX host where the action will be executed
168  * \param amount Computation amount (in bytes)
169  * \return A new SIMIX execution action
170  */
171 smx_action_t simcall_host_execute(const char *name, smx_host_t host,
172                                     double computation_amount,
173                                     double priority)
174 {
175   /* checking for infinite values */
176   xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
177   xbt_assert(isfinite(priority), "priority is not finite!");
178   
179   smx_simcall_t simcall = SIMIX_simcall_mine();
180
181   simcall->call = SIMCALL_HOST_EXECUTE;
182   simcall->host_execute.name = name;
183   simcall->host_execute.host = host;
184   simcall->host_execute.computation_amount = computation_amount;
185   simcall->host_execute.priority = priority;
186   SIMIX_simcall_push(simcall->issuer);
187   return simcall->host_execute.result;
188 }
189
190 /** \brief Creates an action that may involve parallel computation on
191  * several hosts and communication between them.
192  *
193  * \param name Name of the execution action to create
194  * \param host_nb Number of hosts where the action will be executed
195  * \param host_list Array (of size host_nb) of hosts where the action will be executed
196  * \param computation_amount Array (of size host_nb) of computation amount of hosts (in bytes)
197  * \param communication_amount Array (of size host_nb * host_nb) representing the communication
198  * amount between each pair of hosts
199  * \param amount the SURF action amount
200  * \param rate the SURF action rate
201  * \return A new SIMIX execution action
202  */
203 smx_action_t simcall_host_parallel_execute(const char *name,
204                                          int host_nb,
205                                          smx_host_t *host_list,
206                                          double *computation_amount,
207                                          double *communication_amount,
208                                          double amount,
209                                          double rate)
210 {
211   int i,j;
212   /* checking for infinite values */
213   for (i = 0 ; i < host_nb ; ++i) {
214      xbt_assert(isfinite(computation_amount[i]), "computation_amount[%d] is not finite!", i);
215      for (j = 0 ; j < host_nb ; ++j) {
216         xbt_assert(isfinite(communication_amount[i + host_nb * j]), 
217              "communication_amount[%d+%d*%d] is not finite!", i, host_nb, j);
218      }   
219   }   
220  
221   xbt_assert(isfinite(amount), "amount is not finite!");
222   xbt_assert(isfinite(rate), "rate is not finite!");
223   
224   smx_simcall_t simcall = SIMIX_simcall_mine();
225
226   simcall->call = SIMCALL_HOST_PARALLEL_EXECUTE;
227   simcall->host_parallel_execute.name = name;
228   simcall->host_parallel_execute.host_nb = host_nb;
229   simcall->host_parallel_execute.host_list = host_list;
230   simcall->host_parallel_execute.computation_amount = computation_amount;
231   simcall->host_parallel_execute.communication_amount = communication_amount;
232   simcall->host_parallel_execute.amount = amount;
233   simcall->host_parallel_execute.rate = rate;
234   SIMIX_simcall_push(simcall->issuer);
235   return simcall->host_parallel_execute.result;
236 }
237
238 /**
239  * \brief Destroys an execution action.
240  *
241  * Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
242  * \param action The execution action to destroy
243  */
244 void simcall_host_execution_destroy(smx_action_t execution)
245 {
246   smx_simcall_t simcall = SIMIX_simcall_mine();
247
248   simcall->call = SIMCALL_HOST_EXECUTION_DESTROY;
249   simcall->host_execution_destroy.execution = execution;
250   SIMIX_simcall_push(simcall->issuer);
251 }
252
253 /**
254  * \brief Cancels an execution action.
255  *
256  * This functions stops the execution. It calls a surf function.
257  * \param action The execution action to cancel
258  */
259 void simcall_host_execution_cancel(smx_action_t execution)
260 {
261   smx_simcall_t simcall = SIMIX_simcall_mine();
262
263   simcall->call = SIMCALL_HOST_EXECUTION_CANCEL;
264   simcall->host_execution_cancel.execution = execution;
265   SIMIX_simcall_push(simcall->issuer);
266 }
267
268 /**
269  * \brief Returns how much of an execution action remains to be done.
270  *
271  * \param Action The execution action
272  * \return The remaining amount
273  */
274 double simcall_host_execution_get_remains(smx_action_t execution)
275 {
276   smx_simcall_t simcall = SIMIX_simcall_mine();
277
278   simcall->call = SIMCALL_HOST_EXECUTION_GET_REMAINS;
279   simcall->host_execution_get_remains.execution = execution;
280   SIMIX_simcall_push(simcall->issuer);
281   return simcall->host_execution_get_remains.result;
282 }
283
284 /**
285  * \brief Returns the state of an execution action.
286  *
287  * \param execution The execution action
288  * \return The state
289  */
290 e_smx_state_t simcall_host_execution_get_state(smx_action_t execution)
291 {
292   smx_simcall_t simcall = SIMIX_simcall_mine();
293
294   simcall->call = SIMCALL_HOST_EXECUTION_GET_STATE;
295   simcall->host_execution_get_state.execution = execution;
296   SIMIX_simcall_push(simcall->issuer);
297   return simcall->host_execution_get_state.result;
298 }
299
300 /**
301  * \brief Changes the priority of an execution action.
302  *
303  * This functions changes the priority only. It calls a surf function.
304  * \param execution The execution action
305  * \param priority The new priority
306  */
307 void simcall_host_execution_set_priority(smx_action_t execution, double priority)
308 {
309   /* checking for infinite values */
310   xbt_assert(isfinite(priority), "priority is not finite!");
311   
312   smx_simcall_t simcall = SIMIX_simcall_mine();
313
314   simcall->call = SIMCALL_HOST_EXECUTION_SET_PRIORITY;
315   simcall->host_execution_set_priority.execution = execution;
316   simcall->host_execution_set_priority.priority = priority;
317   SIMIX_simcall_push(simcall->issuer);
318 }
319
320 /**
321  * \brief Waits for the completion of an execution action and destroy it.
322  *
323  * \param execution The execution action
324  */
325 e_smx_state_t simcall_host_execution_wait(smx_action_t execution)
326 {
327   smx_simcall_t simcall = SIMIX_simcall_mine();
328
329   simcall->call = SIMCALL_HOST_EXECUTION_WAIT;
330   simcall->host_execution_wait.execution = execution;
331   SIMIX_simcall_push(simcall->issuer);
332   return simcall->host_execution_wait.result;
333 }
334
335 /**
336  * \brief Creates and runs a new SIMIX process.
337  *
338  * The structure and the corresponding thread are created and put in the list of ready processes.
339  *
340  * \param process the process created will be stored in this pointer
341  * \param name a name for the process. It is for user-level information and can be NULL.
342  * \param code the main function of the process
343  * \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.
344  * It can be retrieved with the function \ref simcall_process_get_data.
345  * \param hostname name of the host where the new agent is executed.
346  * \param kill_time time when the process is killed
347  * \param argc first argument passed to \a code
348  * \param argv second argument passed to \a code
349  * \param properties the properties of the process
350  */
351 void simcall_process_create(smx_process_t *process, const char *name,
352                               xbt_main_func_t code,
353                               void *data,
354                               const char *hostname,
355                               double kill_time,
356                               int argc, char **argv,
357                               xbt_dict_t properties,
358                               int auto_restart)
359 {
360   smx_simcall_t simcall = SIMIX_simcall_mine();
361
362   simcall->call = SIMCALL_PROCESS_CREATE;
363   simcall->process_create.process = process;
364   simcall->process_create.name = name;
365   simcall->process_create.code = code;
366   simcall->process_create.data = data;
367   simcall->process_create.hostname = hostname;
368   simcall->process_create.kill_time = kill_time;
369   simcall->process_create.argc = argc;
370   simcall->process_create.argv = argv;
371   simcall->process_create.properties = properties;
372   simcall->process_create.auto_restart = auto_restart;
373   SIMIX_simcall_push(simcall->issuer);
374 }
375
376 /** \brief Kills a SIMIX process.
377  *
378  * This function simply kills a  process.
379  *
380  * \param process poor victim
381  */
382 void simcall_process_kill(smx_process_t process)
383 {
384   smx_simcall_t simcall = SIMIX_simcall_mine();
385
386   simcall->call = SIMCALL_PROCESS_KILL;
387   simcall->process_kill.process = process;
388   SIMIX_simcall_push(simcall->issuer);
389 }
390
391 /** \brief Kills all SIMIX processes.
392  */
393 void simcall_process_killall(void)
394 {
395   smx_simcall_t simcall = SIMIX_simcall_mine();
396
397   simcall->call = SIMCALL_PROCESS_KILLALL;
398   SIMIX_simcall_push(simcall->issuer);
399 }
400
401 /** \brief Cleans up a SIMIX process.
402  * \param process poor victim (must have already been killed)
403  */
404 void simcall_process_cleanup(smx_process_t process)
405 {
406   smx_simcall_t simcall = SIMIX_simcall_mine();
407
408   simcall->call = SIMCALL_PROCESS_CLEANUP;
409   simcall->process_cleanup.process = process;
410   SIMIX_simcall_push(simcall->issuer);
411 }
412
413 /**
414  * \brief Migrates an agent to another location.
415  *
416  * This function changes the value of the host on which \a process is running.
417  *
418  * \param process the process to migrate
419  * \param source name of the previous host
420  * \param dest name of the new host
421  */
422 void simcall_process_change_host(smx_process_t process, smx_host_t dest)
423 {
424   smx_simcall_t simcall = SIMIX_simcall_mine();
425
426   simcall->call = SIMCALL_PROCESS_CHANGE_HOST;
427   simcall->process_change_host.process = process;
428   simcall->process_change_host.dest = dest;
429   SIMIX_simcall_push(simcall->issuer);
430 }
431
432 /**
433  * \brief Suspends a process.
434  *
435  * This function suspends the process by suspending the action
436  * it was waiting for completion.
437  *
438  * \param process a SIMIX process
439  */
440 void simcall_process_suspend(smx_process_t process)
441 {
442   xbt_assert(process, "Invalid parameters");
443
444   smx_simcall_t simcall = SIMIX_simcall_mine();
445
446   simcall->call = SIMCALL_PROCESS_SUSPEND;
447   simcall->process_suspend.process = process;
448   SIMIX_simcall_push(simcall->issuer);
449 }
450
451 /**
452  * \brief Resumes a suspended process.
453  *
454  * This function resumes a suspended process by resuming the action
455  * it was waiting for completion.
456  *
457  * \param process a SIMIX process
458  */
459 void simcall_process_resume(smx_process_t process)
460 {
461   smx_simcall_t simcall = SIMIX_simcall_mine();
462
463   simcall->call = SIMCALL_PROCESS_RESUME;
464   simcall->process_resume.process = process;
465   SIMIX_simcall_push(simcall->issuer);
466 }
467
468 /**
469  * \brief Returns the amount of SIMIX processes in the system
470  *
471  * Maestro internal process is not counted, only user code processes are
472  */
473 int simcall_process_count(void)
474 {
475   smx_simcall_t simcall = SIMIX_simcall_mine();
476
477   simcall->call = SIMCALL_PROCESS_COUNT;
478   SIMIX_simcall_push(simcall->issuer);
479   return simcall->process_count.result;
480 }
481
482 /**
483  * \brief Return the user data of a #smx_process_t.
484  * \param process a SIMIX process
485  * \return the user data of this process
486  */
487 void* simcall_process_get_data(smx_process_t process)
488 {
489   if (process == SIMIX_process_self()) {
490     /* avoid a simcall if this function is called by the process itself */
491     return SIMIX_process_get_data(process);
492   }
493
494   smx_simcall_t simcall = SIMIX_simcall_mine();
495
496   simcall->call = SIMCALL_PROCESS_GET_DATA;
497   simcall->process_get_data.process = process;
498   SIMIX_simcall_push(simcall->issuer);
499   return simcall->process_get_data.result;
500 }
501
502 /**
503  * \brief Set the user data of a #smx_process_t.
504  *
505  * 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.
506  * \param process SIMIX process
507  * \param data User data
508  */
509 void simcall_process_set_data(smx_process_t process, void *data)
510 {
511   if (process == SIMIX_process_self()) {
512     /* avoid a simcall if this function is called by the process itself */
513     SIMIX_process_self_set_data(process, data);
514   }
515   else {
516
517     smx_simcall_t simcall = SIMIX_simcall_mine();
518
519     simcall->call = SIMCALL_PROCESS_SET_DATA;
520     simcall->process_set_data.process = process;
521     simcall->process_set_data.data = data;
522     SIMIX_simcall_push(simcall->issuer);
523   }
524 }
525
526 /**
527  * \brief Set the kill time of a process.
528  * \param process a process
529  * \param kill_time a double
530  */
531 void simcall_process_set_kill_time(smx_process_t process, double kill_time)
532 {
533
534   if (kill_time > SIMIX_get_clock()) {
535     if (simix_global->kill_process_function) {
536       XBT_DEBUG("Set kill time %f for process %s(%s)",kill_time, process->name,
537           process->smx_host->name);
538       SIMIX_timer_set(kill_time, simix_global->kill_process_function, process);
539     }
540   }
541 }
542
543 /**
544  * \brief Return the location on which an agent is running.
545  *
546  * 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.
547  * \param process SIMIX process
548  * \return SIMIX host
549  */
550 smx_host_t simcall_process_get_host(smx_process_t process)
551 {
552   smx_simcall_t simcall = SIMIX_simcall_mine();
553
554   simcall->call = SIMCALL_PROCESS_GET_HOST;
555   simcall->process_get_host.process = process;
556   SIMIX_simcall_push(simcall->issuer);
557   return simcall->process_get_host.result;
558 }
559
560 /**
561  * \brief Return the name of an agent.
562  *
563  * This functions checks whether \a process is a valid pointer or not and return its name.
564  * \param process SIMIX process
565  * \return The process name
566  */
567 const char* simcall_process_get_name(smx_process_t process)
568 {
569   if (process == SIMIX_process_self()) {
570     /* avoid a simcall if this function is called by the process itself */
571     return process->name;
572   }
573
574   smx_simcall_t simcall = SIMIX_simcall_mine();
575
576   simcall->call = SIMCALL_PROCESS_GET_NAME;
577   simcall->process_get_name.process = process;
578   SIMIX_simcall_push(simcall->issuer);
579   return simcall->process_get_name.result;
580 }
581
582 /**
583  * \brief Returns true if the process is suspended .
584  *
585  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
586  * \param process SIMIX process
587  * \return 1, if the process is suspended, else 0.
588  */
589 int simcall_process_is_suspended(smx_process_t process)
590 {
591   smx_simcall_t simcall = SIMIX_simcall_mine();
592
593   simcall->call = SIMCALL_PROCESS_IS_SUSPENDED;
594   simcall->process_is_suspended.process = process;
595   SIMIX_simcall_push(simcall->issuer);
596   return simcall->process_is_suspended.result;
597 }
598
599 /** \ingroup m_process_management
600  * \brief Return the properties
601  *
602  * This functions returns the properties associated with this process
603  */
604 xbt_dict_t simcall_process_get_properties(smx_process_t process)
605 {
606   smx_simcall_t simcall = SIMIX_simcall_mine();
607
608   simcall->call = SIMCALL_PROCESS_GET_PROPERTIES;
609   simcall->process_get_properties.process = process;
610   SIMIX_simcall_push(simcall->issuer);
611   return simcall->process_get_properties.result;
612 }
613 /**
614  * \brief Add an on_exit function
615  * Add an on_exit function which will be executed when the process exits/is killed.
616  */
617 XBT_PUBLIC(void) simcall_process_on_exit(smx_process_t process, int_f_pvoid_t fun, void *data) {
618   smx_simcall_t simcall = SIMIX_simcall_mine();
619
620   simcall->call = SIMCALL_PROCESS_ON_EXIT;
621   simcall->process_on_exit.process = process;
622   simcall->process_on_exit.fun = fun;
623   simcall->process_on_exit.data = data;
624
625   SIMIX_simcall_push(simcall->issuer);
626 }
627 /**
628  * \brief Sets the process to be auto-restarted or not by SIMIX when its host comes back up.
629  * Will restart the process when the host comes back up if auto_restart is set to 1.
630  */
631
632 XBT_PUBLIC(void) simcall_process_auto_restart_set(smx_process_t process, int auto_restart) {
633   smx_simcall_t simcall = SIMIX_simcall_mine();
634
635   simcall->call = SIMCALL_PROCESS_AUTO_RESTART_SET;
636   simcall->process_auto_restart.process = process;
637   simcall->process_auto_restart.auto_restart = auto_restart;
638
639   SIMIX_simcall_push(simcall->issuer);
640 }
641 /** \brief Creates a new sleep SIMIX action.
642  *
643  * This function creates a SURF action and allocates the data necessary
644  * to create the SIMIX action. It can raise a host_error exception if the
645  * host crashed. The default SIMIX name of the action is "sleep".
646  *
647  *   \param duration Time duration of the sleep.
648  *   \return A result telling whether the sleep was successful
649  */
650 e_smx_state_t simcall_process_sleep(double duration)
651 {
652   /* checking for infinite values */
653   xbt_assert(isfinite(duration), "duration is not finite!");
654   
655   smx_simcall_t simcall = SIMIX_simcall_mine();
656
657   simcall->call = SIMCALL_PROCESS_SLEEP;
658   simcall->process_sleep.duration = duration;
659   SIMIX_simcall_push(simcall->issuer);
660   return simcall->process_sleep.result;
661 }
662
663 /**
664  *  \brief Creates a new rendez-vous point
665  *  \param name The name of the rendez-vous point
666  *  \return The created rendez-vous point
667  */
668 smx_rdv_t simcall_rdv_create(const char *name)
669 {
670   smx_simcall_t simcall = SIMIX_simcall_mine();
671
672   simcall->call = SIMCALL_RDV_CREATE;
673   simcall->rdv_create.name = name;
674
675   SIMIX_simcall_push(simcall->issuer);
676   return simcall->rdv_create.result;
677 }
678
679
680 /**
681  *  \brief Destroy a rendez-vous point
682  *  \param name The rendez-vous point to destroy
683  */
684 void simcall_rdv_destroy(smx_rdv_t rdv)
685 {
686   smx_simcall_t simcall = SIMIX_simcall_mine();
687
688   simcall->call = SIMCALL_RDV_DESTROY;
689   simcall->rdv_destroy.rdv = rdv;
690
691   SIMIX_simcall_push(simcall->issuer);
692 }
693
694 smx_rdv_t simcall_rdv_get_by_name(const char *name)
695 {
696   xbt_assert(name != NULL, "Invalid parameter for simcall_rdv_get_by_name (name is NULL)");
697
698   /* FIXME: this is a horrible lost of performance, so we hack it out by
699    * skipping the simcall (for now). It works in parallel, it won't work on
700    * distributed but probably we will change MSG for that. */
701
702   /*
703   smx_simcall_t simcall = simcall_mine();
704   simcall->call = SIMCALL_RDV_GEY_BY_NAME;
705   simcall->rdv_get_by_name.name = name;
706   SIMIX_simcall_push(simcall->issuer);
707   return simcall->rdv_get_by_name.result;*/
708
709   return SIMIX_rdv_get_by_name(name);
710 }
711
712 /**
713  *  \brief Counts the number of communication actions of a given host pending
714  *         on a rendez-vous point.
715  *  \param rdv The rendez-vous point
716  *  \param host The host to be counted
717  *  \return The number of comm actions pending in the rdv
718  */
719 int simcall_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
720 {
721   smx_simcall_t simcall = SIMIX_simcall_mine();
722
723   simcall->call = SIMCALL_RDV_COMM_COUNT_BY_HOST;
724   simcall->rdv_comm_count_by_host.rdv = rdv;
725   simcall->rdv_comm_count_by_host.host = host;
726
727   SIMIX_simcall_push(simcall->issuer);
728   return simcall->rdv_comm_count_by_host.result;
729 }
730
731 /**
732  *  \brief returns the communication at the head of the rendez-vous
733  *  \param rdv The rendez-vous point
734  *  \return The communication or NULL if empty
735  */
736 smx_action_t simcall_rdv_get_head(smx_rdv_t rdv)
737 {
738   smx_simcall_t simcall = SIMIX_simcall_mine();
739
740   simcall->call = SIMCALL_RDV_GET_HEAD;
741   simcall->rdv_get_head.rdv = rdv;
742
743   SIMIX_simcall_push(simcall->issuer);
744   return simcall->rdv_get_head.result;
745 }
746
747 void simcall_comm_send(smx_rdv_t rdv, double task_size, double rate,
748                          void *src_buff, size_t src_buff_size,
749                          int (*match_fun)(void *, void *, smx_action_t), void *data,
750                          double timeout)
751 {
752   /* checking for infinite values */
753   xbt_assert(isfinite(task_size), "task_size is not finite!");
754   xbt_assert(isfinite(rate), "rate is not finite!");
755   xbt_assert(isfinite(timeout), "timeout is not finite!");
756   
757   xbt_assert(rdv, "No rendez-vous point defined for send");
758
759   if (MC_IS_ENABLED) {
760     /* the model-checker wants two separate simcalls */
761     smx_action_t comm = simcall_comm_isend(rdv, task_size, rate,
762         src_buff, src_buff_size, match_fun, NULL, data, 0);
763     simcall_comm_wait(comm, timeout);
764   }
765   else {
766     smx_simcall_t simcall = SIMIX_simcall_mine();
767
768     simcall->call = SIMCALL_COMM_SEND;
769     simcall->comm_send.rdv = rdv;
770     simcall->comm_send.task_size = task_size;
771     simcall->comm_send.rate = rate;
772     simcall->comm_send.src_buff = src_buff;
773     simcall->comm_send.src_buff_size = src_buff_size;
774     simcall->comm_send.match_fun = match_fun;
775     simcall->comm_send.data = data;
776     simcall->comm_send.timeout = timeout;
777
778     SIMIX_simcall_push(simcall->issuer);
779   }
780 }
781
782 smx_action_t simcall_comm_isend(smx_rdv_t rdv, double task_size, double rate,
783                               void *src_buff, size_t src_buff_size,
784                               int (*match_fun)(void *, void *, smx_action_t),
785                               void (*clean_fun)(void *),
786                               void *data,
787                               int detached)
788 {
789   /* checking for infinite values */
790   xbt_assert(isfinite(task_size), "task_size is not finite!");
791   xbt_assert(isfinite(rate), "rate is not finite!");
792   
793   xbt_assert(rdv, "No rendez-vous point defined for isend");
794
795   smx_simcall_t simcall = SIMIX_simcall_mine();
796
797   simcall->call = SIMCALL_COMM_ISEND;
798   simcall->comm_isend.rdv = rdv;
799   simcall->comm_isend.task_size = task_size;
800   simcall->comm_isend.rate = rate;
801   simcall->comm_isend.src_buff = src_buff;
802   simcall->comm_isend.src_buff_size = src_buff_size;
803   simcall->comm_isend.match_fun = match_fun;
804   simcall->comm_isend.clean_fun = clean_fun;
805   simcall->comm_isend.data = data;
806   simcall->comm_isend.detached = detached;
807
808   SIMIX_simcall_push(simcall->issuer);
809   return simcall->comm_isend.result;
810 }
811
812 void simcall_comm_recv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
813                          int (*match_fun)(void *, void *, smx_action_t), void *data, double timeout)
814 {
815   xbt_assert(isfinite(timeout), "timeout is not finite!");
816   xbt_assert(rdv, "No rendez-vous point defined for recv");
817
818   if (MC_IS_ENABLED) {
819     /* the model-checker wants two separate simcalls */
820     smx_action_t comm = simcall_comm_irecv(rdv, dst_buff, dst_buff_size,
821         match_fun, data);
822     simcall_comm_wait(comm, timeout);
823   }
824   else {
825     smx_simcall_t simcall = SIMIX_simcall_mine();
826
827     simcall->call = SIMCALL_COMM_RECV;
828     simcall->comm_recv.rdv = rdv;
829     simcall->comm_recv.dst_buff = dst_buff;
830     simcall->comm_recv.dst_buff_size = dst_buff_size;
831     simcall->comm_recv.match_fun = match_fun;
832     simcall->comm_recv.data = data;
833     simcall->comm_recv.timeout = timeout;
834
835     SIMIX_simcall_push(simcall->issuer);
836   }
837 }
838
839 smx_action_t simcall_comm_irecv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
840                                   int (*match_fun)(void *, void *, smx_action_t), void *data)
841 {
842   xbt_assert(rdv, "No rendez-vous point defined for irecv");
843
844   smx_simcall_t simcall = SIMIX_simcall_mine();
845
846   simcall->call = SIMCALL_COMM_IRECV;
847   simcall->comm_irecv.rdv = rdv;
848   simcall->comm_irecv.dst_buff = dst_buff;
849   simcall->comm_irecv.dst_buff_size = dst_buff_size;
850   simcall->comm_irecv.match_fun = match_fun;
851   simcall->comm_irecv.data = data;
852
853   SIMIX_simcall_push(simcall->issuer);
854   return simcall->comm_irecv.result;
855 }
856
857 void simcall_comm_destroy(smx_action_t comm)
858 {
859   xbt_assert(comm, "Invalid parameter");
860
861   /* FIXME remove this simcall type: comms are auto-destroyed now */
862
863   /*
864   smx_simcall_t simcall = simcall_mine();
865
866   simcall->call = SIMCALL_COMM_DESTROY;
867   simcall->comm_destroy.comm = comm;
868
869   SIMIX_simcall_push(simcall->issuer);
870   */
871 }
872
873 void simcall_comm_cancel(smx_action_t comm)
874 {
875   smx_simcall_t simcall = SIMIX_simcall_mine();
876
877   simcall->call = SIMCALL_COMM_CANCEL;
878   simcall->comm_cancel.comm = comm;
879
880   SIMIX_simcall_push(simcall->issuer);
881 }
882
883 unsigned int simcall_comm_waitany(xbt_dynar_t comms)
884 {
885   smx_simcall_t simcall = SIMIX_simcall_mine();
886
887   simcall->call = SIMCALL_COMM_WAITANY;
888   simcall->comm_waitany.comms = comms;
889
890   SIMIX_simcall_push(simcall->issuer);
891   return simcall->comm_waitany.result;
892 }
893
894 int simcall_comm_testany(xbt_dynar_t comms)
895 {
896   smx_simcall_t simcall = SIMIX_simcall_mine();
897   if (xbt_dynar_is_empty(comms))
898     return -1;
899
900   simcall->call = SIMCALL_COMM_TESTANY;
901   simcall->comm_testany.comms = comms;
902
903   SIMIX_simcall_push(simcall->issuer);
904   return simcall->comm_testany.result;
905 }
906
907 void simcall_comm_wait(smx_action_t comm, double timeout)
908 {
909   xbt_assert(isfinite(timeout), "timeout is not finite!");
910   
911   smx_simcall_t simcall = SIMIX_simcall_mine();
912
913   simcall->call = SIMCALL_COMM_WAIT;
914   simcall->comm_wait.comm = comm;
915   simcall->comm_wait.timeout = timeout;
916
917   SIMIX_simcall_push(simcall->issuer);
918 }
919
920 #ifdef HAVE_TRACING
921 /**
922  * \brief Set the category of an action.
923  *
924  * This functions changes the category only. It calls a surf function.
925  * \param execution The execution action
926  * \param category The tracing category
927  */
928 void simcall_set_category(smx_action_t action, const char *category)
929 {
930   if (category == NULL) {
931     return;
932   }
933
934   smx_simcall_t simcall = SIMIX_simcall_mine();
935
936   simcall->call = SIMCALL_SET_CATEGORY;
937   simcall->set_category.action = action;
938   simcall->set_category.category = category;
939
940   SIMIX_simcall_push(simcall->issuer);
941 }
942 #endif
943
944 int simcall_comm_test(smx_action_t comm)
945 {
946   smx_simcall_t simcall = SIMIX_simcall_mine();
947
948   simcall->call = SIMCALL_COMM_TEST;
949   simcall->comm_test.comm = comm;
950
951   SIMIX_simcall_push(simcall->issuer);
952   return simcall->comm_test.result;
953 }
954
955 double simcall_comm_get_remains(smx_action_t comm)
956 {
957   smx_simcall_t simcall = SIMIX_simcall_mine();
958
959   simcall->call = SIMCALL_COMM_GET_REMAINS;
960   simcall->comm_get_remains.comm = comm;
961
962   SIMIX_simcall_push(simcall->issuer);
963   return simcall->comm_get_remains.result;
964 }
965
966 e_smx_state_t simcall_comm_get_state(smx_action_t comm)
967 {
968   smx_simcall_t simcall = SIMIX_simcall_mine();
969
970   simcall->call = SIMCALL_COMM_GET_STATE;
971   simcall->comm_get_state.comm = comm;
972
973   SIMIX_simcall_push(simcall->issuer);
974   return simcall->comm_get_state.result;
975 }
976
977 void *simcall_comm_get_src_data(smx_action_t comm)
978 {
979   smx_simcall_t simcall = SIMIX_simcall_mine();
980
981   simcall->call = SIMCALL_COMM_GET_SRC_DATA;
982   simcall->comm_get_src_data.comm = comm;
983
984   SIMIX_simcall_push(simcall->issuer);
985   return simcall->comm_get_src_data.result;
986 }
987
988 void *simcall_comm_get_dst_data(smx_action_t comm)
989 {
990   smx_simcall_t simcall = SIMIX_simcall_mine();
991
992   simcall->call = SIMCALL_COMM_GET_DST_DATA;
993   simcall->comm_get_dst_data.comm = comm;
994
995   SIMIX_simcall_push(simcall->issuer);
996   return simcall->comm_get_dst_data.result;
997 }
998
999 smx_process_t simcall_comm_get_src_proc(smx_action_t comm)
1000 {
1001   smx_simcall_t simcall = SIMIX_simcall_mine();
1002
1003   simcall->call = SIMCALL_COMM_GET_SRC_PROC;
1004   simcall->comm_get_src_proc.comm = comm;
1005
1006   SIMIX_simcall_push(simcall->issuer);
1007   return simcall->comm_get_src_proc.result;
1008 }
1009
1010 smx_process_t simcall_comm_get_dst_proc(smx_action_t comm)
1011 {
1012   smx_simcall_t simcall = SIMIX_simcall_mine();
1013
1014   simcall->call = SIMCALL_COMM_GET_DST_PROC;
1015   simcall->comm_get_dst_proc.comm = comm;
1016
1017   SIMIX_simcall_push(simcall->issuer);
1018   return simcall->comm_get_dst_proc.result;
1019 }
1020
1021 #ifdef HAVE_LATENCY_BOUND_TRACKING
1022 int simcall_comm_is_latency_bounded(smx_action_t comm)
1023 {
1024   smx_simcall_t simcall = SIMIX_simcall_mine();
1025
1026   simcall->call = SIMCALL_COMM_IS_LATENCY_BOUNDED;
1027   simcall->comm_is_latency_bounded.comm = comm;
1028
1029   SIMIX_simcall_push(simcall->issuer);
1030   return simcall->comm_is_latency_bounded.result;
1031 }
1032 #endif
1033
1034 smx_mutex_t simcall_mutex_init(void)
1035 {
1036   if(!simix_global) {
1037     fprintf(stderr,"You must run MSG_init or gras_init before using MSG or GRAS\n"); // I would have loved using xbt_die but I can't since it is not initialized yet... :)
1038     abort();
1039   }
1040   smx_simcall_t simcall = SIMIX_simcall_mine();
1041
1042   simcall->call = SIMCALL_MUTEX_INIT;
1043
1044   SIMIX_simcall_push(simcall->issuer);
1045   return simcall->mutex_init.result;
1046 }
1047
1048 void simcall_mutex_destroy(smx_mutex_t mutex)
1049 {
1050   smx_simcall_t simcall = SIMIX_simcall_mine();
1051
1052   simcall->call = SIMCALL_MUTEX_DESTROY;
1053   simcall->mutex_destroy.mutex = mutex;
1054
1055   SIMIX_simcall_push(simcall->issuer);
1056 }
1057
1058 void simcall_mutex_lock(smx_mutex_t mutex)
1059 {
1060   smx_simcall_t simcall = SIMIX_simcall_mine();
1061
1062   simcall->call = SIMCALL_MUTEX_LOCK;
1063   simcall->mutex_lock.mutex = mutex;
1064
1065   SIMIX_simcall_push(simcall->issuer);
1066 }
1067
1068 int simcall_mutex_trylock(smx_mutex_t mutex)
1069 {
1070   smx_simcall_t simcall = SIMIX_simcall_mine();
1071
1072   simcall->call = SIMCALL_MUTEX_TRYLOCK;
1073   simcall->mutex_trylock.mutex = mutex;
1074
1075   SIMIX_simcall_push(simcall->issuer);
1076   return simcall->mutex_trylock.result;
1077 }
1078
1079 void simcall_mutex_unlock(smx_mutex_t mutex)
1080 {
1081   smx_simcall_t simcall = SIMIX_simcall_mine();
1082
1083   simcall->call = SIMCALL_MUTEX_UNLOCK;
1084   simcall->mutex_unlock.mutex = mutex;
1085
1086   SIMIX_simcall_push(simcall->issuer);
1087 }
1088
1089
1090 smx_cond_t simcall_cond_init(void)
1091 {
1092   smx_simcall_t simcall = SIMIX_simcall_mine();
1093
1094   simcall->call = SIMCALL_COND_INIT;
1095
1096   SIMIX_simcall_push(simcall->issuer);
1097   return simcall->cond_init.result;
1098 }
1099
1100 void simcall_cond_destroy(smx_cond_t cond)
1101 {
1102   smx_simcall_t simcall = SIMIX_simcall_mine();
1103
1104   simcall->call = SIMCALL_COND_DESTROY;
1105   simcall->cond_destroy.cond = cond;
1106
1107   SIMIX_simcall_push(simcall->issuer);
1108 }
1109
1110 void simcall_cond_signal(smx_cond_t cond)
1111 {
1112   smx_simcall_t simcall = SIMIX_simcall_mine();
1113
1114   simcall->call = SIMCALL_COND_SIGNAL;
1115   simcall->cond_signal.cond = cond;
1116
1117   SIMIX_simcall_push(simcall->issuer);
1118 }
1119
1120 void simcall_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
1121 {
1122   smx_simcall_t simcall = SIMIX_simcall_mine();
1123
1124   simcall->call = SIMCALL_COND_WAIT;
1125   simcall->cond_wait.cond = cond;
1126   simcall->cond_wait.mutex = mutex;
1127
1128   SIMIX_simcall_push(simcall->issuer);
1129 }
1130
1131 void simcall_cond_wait_timeout(smx_cond_t cond,
1132                                  smx_mutex_t mutex,
1133                                  double timeout)
1134 {
1135   xbt_assert(isfinite(timeout), "timeout is not finite!");
1136   
1137   smx_simcall_t simcall = SIMIX_simcall_mine();
1138
1139   simcall->call = SIMCALL_COND_WAIT_TIMEOUT;
1140   simcall->cond_wait_timeout.cond = cond;
1141   simcall->cond_wait_timeout.mutex = mutex;
1142   simcall->cond_wait_timeout.timeout = timeout;
1143
1144   SIMIX_simcall_push(simcall->issuer);
1145 }
1146
1147 void simcall_cond_broadcast(smx_cond_t cond)
1148 {
1149   smx_simcall_t simcall = SIMIX_simcall_mine();
1150
1151   simcall->call = SIMCALL_COND_BROADCAST;
1152   simcall->cond_broadcast.cond = cond;
1153
1154   SIMIX_simcall_push(simcall->issuer);
1155 }
1156
1157
1158 smx_sem_t simcall_sem_init(int capacity)
1159 {
1160   smx_simcall_t simcall = SIMIX_simcall_mine();
1161
1162   simcall->call = SIMCALL_SEM_INIT;
1163   simcall->sem_init.capacity = capacity;
1164
1165   SIMIX_simcall_push(simcall->issuer);
1166   return simcall->sem_init.result;
1167 }
1168
1169 void simcall_sem_destroy(smx_sem_t sem)
1170 {
1171   smx_simcall_t simcall = SIMIX_simcall_mine();
1172
1173   simcall->call = SIMCALL_SEM_DESTROY;
1174   simcall->sem_destroy.sem = sem;
1175
1176   SIMIX_simcall_push(simcall->issuer);
1177 }
1178
1179 void simcall_sem_release(smx_sem_t sem)
1180 {
1181   smx_simcall_t simcall = SIMIX_simcall_mine();
1182
1183   simcall->call = SIMCALL_SEM_RELEASE;
1184   simcall->sem_release.sem = sem;
1185
1186   SIMIX_simcall_push(simcall->issuer);
1187 }
1188
1189 int simcall_sem_would_block(smx_sem_t sem)
1190 {
1191   smx_simcall_t simcall = SIMIX_simcall_mine();
1192
1193   simcall->call = SIMCALL_SEM_WOULD_BLOCK;
1194   simcall->sem_would_block.sem = sem;
1195
1196   SIMIX_simcall_push(simcall->issuer);
1197   return simcall->sem_would_block.result;
1198 }
1199
1200 void simcall_sem_acquire(smx_sem_t sem)
1201 {
1202   smx_simcall_t simcall = SIMIX_simcall_mine();
1203
1204   simcall->call = SIMCALL_SEM_ACQUIRE;
1205   simcall->sem_acquire.sem = sem;
1206
1207   SIMIX_simcall_push(simcall->issuer);
1208 }
1209
1210 void simcall_sem_acquire_timeout(smx_sem_t sem, double timeout)
1211 {
1212   xbt_assert(isfinite(timeout), "timeout is not finite!");
1213   
1214   smx_simcall_t simcall = SIMIX_simcall_mine();
1215
1216   simcall->call = SIMCALL_SEM_ACQUIRE_TIMEOUT;
1217   simcall->sem_acquire_timeout.sem = sem;
1218   simcall->sem_acquire_timeout.timeout = timeout;
1219
1220   SIMIX_simcall_push(simcall->issuer);
1221 }
1222
1223 int simcall_sem_get_capacity(smx_sem_t sem)
1224 {
1225   smx_simcall_t simcall = SIMIX_simcall_mine();
1226
1227   simcall->call = SIMCALL_SEM_GET_CAPACITY;
1228   simcall->sem_get_capacity.sem = sem;
1229
1230   SIMIX_simcall_push(simcall->issuer);
1231   return simcall->sem_get_capacity.result;
1232 }
1233
1234 double simcall_file_read(void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1235 {
1236   smx_simcall_t simcall = SIMIX_simcall_mine();
1237
1238   simcall->call = SIMCALL_FILE_READ;
1239   simcall->file_read.ptr = ptr;
1240   simcall->file_read.size = size;
1241   simcall->file_read.nmemb = nmemb;
1242   simcall->file_read.stream = stream;
1243   SIMIX_simcall_push(simcall->issuer);
1244
1245   return simcall->file_read.result;
1246 }
1247
1248 size_t simcall_file_write(const void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1249 {
1250   smx_simcall_t simcall = SIMIX_simcall_mine();
1251
1252   simcall->call = SIMCALL_FILE_WRITE;
1253   simcall->file_write.ptr = ptr;
1254   simcall->file_write.size = size;
1255   simcall->file_write.nmemb = nmemb;
1256   simcall->file_write.stream = stream;
1257   SIMIX_simcall_push(simcall->issuer);
1258
1259   return simcall->file_write.result;
1260 }
1261
1262 smx_file_t simcall_file_open(const char* mount, const char* path, const char* mode)
1263 {
1264   smx_simcall_t simcall = SIMIX_simcall_mine();
1265
1266   simcall->call = SIMCALL_FILE_OPEN;
1267   simcall->file_open.mount = mount;
1268   simcall->file_open.path = path;
1269   simcall->file_open.mode = mode;
1270   SIMIX_simcall_push(simcall->issuer);
1271
1272   return simcall->file_open.result;
1273 }
1274
1275 int simcall_file_close(smx_file_t fp)
1276 {
1277   smx_simcall_t simcall = SIMIX_simcall_mine();
1278
1279   simcall->call = SIMCALL_FILE_CLOSE;
1280   simcall->file_close.fp = fp;
1281   SIMIX_simcall_push(simcall->issuer);
1282
1283   return simcall->file_close.result;
1284 }
1285
1286 int simcall_file_stat(smx_file_t fd, s_file_stat_t *buf)
1287 {
1288   smx_simcall_t simcall = SIMIX_simcall_mine();
1289   simcall->call = SIMCALL_FILE_STAT;
1290   simcall->file_stat.fd = fd;
1291
1292   SIMIX_simcall_push(simcall->issuer);
1293
1294   *buf = simcall->file_stat.buf;
1295
1296   return simcall->file_stat.result;
1297 }
1298
1299 /* ************************************************************************** */
1300
1301 /** @brief returns a printable string representing a simcall */
1302 const char *SIMIX_simcall_name(e_smx_simcall_t kind) {
1303   return simcall_names[kind];
1304 }