Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
kill smx_private.hpp We already have a smx_private.h
[simgrid.git] / src / simix / libsmx.cpp
1 /* libsmx.c - public interface to simix                                       */
2 /* --------                                                                   */
3 /* These functions are the only ones that are visible from the higher levels  */
4 /* (most of them simply add some documentation to the generated simcall body) */
5 /*                                                                            */
6 /* This is somehow the "libc" of SimGrid                                      */
7
8 /* Copyright (c) 2010-2015. The SimGrid Team.
9  * All rights reserved.                                                     */
10
11 /* This program is free software; you can redistribute it and/or modify it
12  * under the terms of the license (GNU LGPL) which comes with this package. */
13
14 #include <cmath>         /* std::isfinite() */
15
16 #include <functional>
17
18 #include "src/mc/mc_replay.h"
19 #include "smx_private.h"
20 #include "src/mc/mc_forward.hpp"
21 #include "xbt/ex.h"
22 #include "mc/mc.h"
23 #include "src/simix/smx_host_private.h"
24
25 #include <simgrid/simix.hpp>
26
27 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
28
29 #include "popping_bodies.cpp"
30
31 void simcall_call(smx_process_t process)
32 {
33   if (process != simix_global->maestro_process) {
34     XBT_DEBUG("Yield process '%s' on simcall %s (%d)", process->name,
35               SIMIX_simcall_name(process->simcall.call), (int)process->simcall.call);
36     SIMIX_process_yield(process);
37   } else {
38     SIMIX_simcall_handle(&process->simcall, 0);
39   }
40 }
41
42 // ***** AS simcalls
43
44 /**
45  * \ingroup simix_host_management
46  * \brief Returns a dict of the properties assigned to a router or AS.
47  *
48  * \param name The name of the router or AS
49  * \return The properties
50  */
51 xbt_dict_t simcall_asr_get_properties(const char *name)
52 {
53   return simcall_BODY_asr_get_properties(name);
54 }
55
56 /**
57  * \ingroup simix_process_management
58  * \brief Creates a synchro that executes some computation of an host.
59  *
60  * This function creates a SURF action and allocates the data necessary
61  * to create the SIMIX synchro. It can raise a host_error exception if the host crashed.
62  *
63  * \param name Name of the execution synchro to create
64  * \param flops_amount amount Computation amount (in flops)
65  * \param priority computation priority
66  * \param bound
67  * \param affinity_mask
68  * \return A new SIMIX execution synchronization
69  */
70 smx_synchro_t simcall_execution_start(const char *name,
71                                     double flops_amount,
72                                     double priority, double bound, unsigned long affinity_mask)
73 {
74   /* checking for infinite values */
75   xbt_assert(std::isfinite(flops_amount), "flops_amount is not finite!");
76   xbt_assert(std::isfinite(priority), "priority is not finite!");
77
78   return simcall_BODY_execution_start(name, flops_amount, priority, bound, affinity_mask);
79 }
80
81 /**
82  * \ingroup simix_process_management
83  * \brief Creates a synchro that may involve parallel computation on
84  * several hosts and communication between them.
85  *
86  * \param name Name of the execution synchro to create
87  * \param host_nb Number of hosts where the synchro will be executed
88  * \param host_list Array (of size host_nb) of hosts where the synchro will be executed
89  * \param flops_amount Array (of size host_nb) of computation amount of hosts (in bytes)
90  * \param bytes_amount Array (of size host_nb * host_nb) representing the communication
91  * amount between each pair of hosts
92  * \param amount the SURF action amount
93  * \param rate the SURF action rate
94  * \return A new SIMIX execution synchronization
95  */
96 smx_synchro_t simcall_execution_parallel_start(const char *name,
97                                          int host_nb,
98                                          sg_host_t *host_list,
99                                          double *flops_amount,
100                                          double *bytes_amount,
101                                          double amount,
102                                          double rate)
103 {
104   int i,j;
105   /* checking for infinite values */
106   for (i = 0 ; i < host_nb ; ++i) {
107     xbt_assert(std::isfinite(flops_amount[i]), "flops_amount[%d] is not finite!", i);
108     if (bytes_amount != NULL) {
109       for (j = 0 ; j < host_nb ; ++j) {
110         xbt_assert(std::isfinite(bytes_amount[i + host_nb * j]),
111                    "bytes_amount[%d+%d*%d] is not finite!", i, host_nb, j);
112       }
113     }
114   }
115
116   xbt_assert(std::isfinite(amount), "amount is not finite!");
117   xbt_assert(std::isfinite(rate), "rate is not finite!");
118
119   return simcall_BODY_execution_parallel_start(name, host_nb, host_list,
120                                             flops_amount,
121                                             bytes_amount,
122                                             amount, rate);
123
124 }
125
126 /**
127  * \ingroup simix_process_management
128  * \brief Destroys an execution synchro.
129  *
130  * Destroys a synchro, freeing its memory. This function cannot be called if there are a conditional waiting for it.
131  * \param execution The execution synchro to destroy
132  */
133 void simcall_execution_destroy(smx_synchro_t execution)
134 {
135   simcall_BODY_execution_destroy(execution);
136 }
137
138 /**
139  * \ingroup simix_process_management
140  * \brief Cancels an execution synchro.
141  *
142  * This functions stops the execution. It calls a surf function.
143  * \param execution The execution synchro to cancel
144  */
145 void simcall_execution_cancel(smx_synchro_t execution)
146 {
147   simcall_BODY_execution_cancel(execution);
148 }
149
150 /**
151  * \ingroup simix_process_management
152  * \brief Returns how much of an execution synchro remains to be done.
153  *
154  * \param execution The execution synchro
155  * \return The remaining amount
156  */
157 double simcall_execution_get_remains(smx_synchro_t execution)
158 {
159   return simcall_BODY_execution_get_remains(execution);
160 }
161
162 /**
163  * \ingroup simix_process_management
164  * \brief Returns the state of an execution synchro.
165  *
166  * \param execution The execution synchro
167  * \return The state
168  */
169 e_smx_state_t simcall_execution_get_state(smx_synchro_t execution)
170 {
171   return simcall_BODY_execution_get_state(execution);
172 }
173
174 /**
175  * \ingroup simix_process_management
176  * \brief Changes the priority of an execution synchro.
177  *
178  * This functions changes the priority only. It calls a surf function.
179  * \param execution The execution synchro
180  * \param priority The new priority
181  */
182 void simcall_execution_set_priority(smx_synchro_t execution, double priority)
183 {
184   /* checking for infinite values */
185   xbt_assert(std::isfinite(priority), "priority is not finite!");
186
187   simcall_BODY_execution_set_priority(execution, priority);
188 }
189
190 /**
191  * \ingroup simix_process_management
192  * \brief Changes the capping (the maximum CPU utilization) of an execution synchro.
193  *
194  * This functions changes the capping only. It calls a surf function.
195  * \param execution The execution synchro
196  * \param bound The new bound
197  */
198 void simcall_execution_set_bound(smx_synchro_t execution, double bound)
199 {
200   simcall_BODY_execution_set_bound(execution, bound);
201 }
202
203 /**
204  * \ingroup simix_process_management
205  * \brief Changes the CPU affinity of an execution synchro.
206  *
207  * This functions changes the CPU affinity of an execution synchro. See taskset(1) on Linux.
208  * \param execution The execution synchro
209  * \param host Host
210  * \param mask Affinity mask
211  */
212 void simcall_execution_set_affinity(smx_synchro_t execution, sg_host_t host, unsigned long mask)
213 {
214   simcall_BODY_execution_set_affinity(execution, host, mask);
215 }
216
217 /**
218  * \ingroup simix_host_management
219  * \brief Waits for the completion of an execution synchro and destroy it.
220  *
221  * \param execution The execution synchro
222  */
223 e_smx_state_t simcall_execution_wait(smx_synchro_t execution)
224 {
225   return (e_smx_state_t) simcall_BODY_execution_wait(execution);
226 }
227
228
229 /**
230  * \ingroup simix_vm_management
231  * \brief Create a VM on the given physical host.
232  *
233  * \param name VM name
234  * \param host Physical host
235  *
236  * \return The host object of the VM
237  */
238 void* simcall_vm_create(const char *name, sg_host_t phys_host)
239 {
240   return simgrid::simix::kernel(std::bind(SIMIX_vm_create, name, phys_host));
241 }
242
243 /**
244  * \ingroup simix_vm_management
245  * \brief Start the given VM to the given physical host
246  *
247  * \param vm VM
248  */
249 void simcall_vm_start(sg_host_t vm)
250 {
251   return simgrid::simix::kernel(std::bind(SIMIX_vm_start, vm));
252 }
253
254 /**
255  * \ingroup simix_vm_management
256  * \brief Get the state of the given VM
257  *
258  * \param vm VM
259  * \return The state of the VM
260  */
261 int simcall_vm_get_state(sg_host_t vm)
262 {
263   return simgrid::simix::kernel(std::bind(SIMIX_vm_get_state, vm));
264 }
265
266 /**
267  * \ingroup simix_vm_management
268  * \brief Get the name of the physical host on which the given VM runs.
269  *
270  * \param vm VM
271  * \return The name of the physical host
272  */
273 void *simcall_vm_get_pm(sg_host_t vm)
274 {
275   return simgrid::simix::kernel(std::bind(SIMIX_vm_get_pm, vm));
276 }
277
278 void simcall_vm_set_bound(sg_host_t vm, double bound)
279 {
280   simgrid::simix::kernel(std::bind(SIMIX_vm_set_bound, vm, bound));
281 }
282
283 void simcall_vm_set_affinity(sg_host_t vm, sg_host_t pm, unsigned long mask)
284 {
285   simgrid::simix::kernel(std::bind(SIMIX_vm_set_affinity, vm, pm, mask));
286 }
287
288 /**
289  * \ingroup simix_vm_management
290  * \brief Migrate the given VM to the given physical host
291  *
292  * \param vm VM
293  * \param host Destination physical host
294  */
295 void simcall_vm_migrate(sg_host_t vm, sg_host_t host)
296 {
297   return simgrid::simix::kernel(std::bind(SIMIX_vm_migrate, vm, host));
298 }
299
300 /**
301  * \ingroup simix_vm_management
302  * \brief Suspend the given VM
303  *
304  * \param vm VM
305  */
306 void simcall_vm_suspend(sg_host_t vm)
307 {
308   simcall_BODY_vm_suspend(vm);
309 }
310
311 /**
312  * \ingroup simix_vm_management
313  * \brief Resume the given VM
314  *
315  * \param vm VM
316  */
317 void simcall_vm_resume(sg_host_t vm)
318 {
319   simcall_BODY_vm_resume(vm);
320 }
321
322 /**
323  * \ingroup simix_vm_management
324  * \brief Save the given VM
325  *
326  * \param vm VM
327  */
328 void simcall_vm_save(sg_host_t vm)
329 {
330   simcall_BODY_vm_save(vm);
331 }
332
333 /**
334  * \ingroup simix_vm_management
335  * \brief Restore the given VM
336  *
337  * \param vm VM
338  */
339 void simcall_vm_restore(sg_host_t vm)
340 {
341   simcall_BODY_vm_restore(vm);
342 }
343
344 /**
345  * \ingroup simix_vm_management
346  * \brief Shutdown the given VM
347  *
348  * \param vm VM
349  */
350 void simcall_vm_shutdown(sg_host_t vm)
351 {
352   simcall_BODY_vm_shutdown(vm);
353 }
354
355 /**
356  * \ingroup simix_vm_management
357  * \brief Destroy the given VM
358  *
359  * \param vm VM
360  */
361 void simcall_vm_destroy(sg_host_t vm)
362 {
363   simgrid::simix::kernel(std::bind(SIMIX_vm_destroy, vm));
364 }
365
366 /**
367  * \ingroup simix_vm_management
368  * \brief Encompassing simcall to prevent the removal of the src or the dst node at the end of a VM migration
369  *  The simcall actually invokes the following calls: 
370  *     simcall_vm_set_affinity(vm, src_pm, 0); 
371  *     simcall_vm_migrate(vm, dst_pm); 
372  *     simcall_vm_resume(vm);
373  *
374  * It is called at the end of the migration_rx_fun function from msg/msg_vm.c
375  *
376  * \param vm VM to migrate
377  * \param src_pm  Source physical host
378  * \param dst_pmt Destination physical host
379  */
380 void simcall_vm_migratefrom_resumeto(sg_host_t vm, sg_host_t src_pm, sg_host_t dst_pm)
381 {
382   simgrid::simix::kernel(std::bind(
383     SIMIX_vm_migratefrom_resumeto, vm, src_pm, dst_pm));
384 }
385
386 /**
387  * \ingroup simix_process_management
388  * \brief Creates and runs a new SIMIX process.
389  *
390  * The structure and the corresponding thread are created and put in the list of ready processes.
391  *
392  * \param name a name for the process. It is for user-level information and can be NULL.
393  * \param code the main function of the process
394  * \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.
395  * It can be retrieved with the function \ref simcall_process_get_data.
396  * \param hostname name of the host where the new agent is executed.
397  * \param kill_time time when the process is killed
398  * \param argc first argument passed to \a code
399  * \param argv second argument passed to \a code
400  * \param properties the properties of the process
401  * \param auto_restart either it is autorestarting or not.
402  */
403 smx_process_t simcall_process_create(const char *name,
404                               xbt_main_func_t code,
405                               void *data,
406                               const char *hostname,
407                               double kill_time,
408                               int argc, char **argv,
409                               xbt_dict_t properties,
410                               int auto_restart)
411 {
412   return (smx_process_t) simcall_BODY_process_create(name, code, data, hostname,
413                               kill_time, argc, argv, properties,
414                               auto_restart);
415 }
416
417 /**
418  * \ingroup simix_process_management
419  * \brief Kills a SIMIX process.
420  *
421  * This function simply kills a  process.
422  *
423  * \param process poor victim
424  */
425 void simcall_process_kill(smx_process_t process)
426 {
427   simcall_BODY_process_kill(process);
428 }
429
430 /**
431  * \ingroup simix_process_management
432  * \brief Kills all SIMIX processes.
433  */
434 void simcall_process_killall(int reset_pid)
435 {
436   simcall_BODY_process_killall(reset_pid);
437 }
438
439 /**
440  * \ingroup simix_process_management
441  * \brief Cleans up a SIMIX process.
442  * \param process poor victim (must have already been killed)
443  */
444 void simcall_process_cleanup(smx_process_t process)
445 {
446   simcall_BODY_process_cleanup(process);
447 }
448
449 /**
450  * \ingroup simix_process_management
451  * \brief Migrates an agent to another location.
452  *
453  * This function changes the value of the host on which \a process is running.
454  *
455  * \param process the process to migrate
456  * \param dest name of the new host
457  */
458 void simcall_process_set_host(smx_process_t process, sg_host_t dest)
459 {
460   simcall_BODY_process_set_host(process, dest);
461 }
462
463 void simcall_process_join(smx_process_t process, double timeout)
464 {
465   simcall_BODY_process_join(process, timeout);
466 }
467
468 /**
469  * \ingroup simix_process_management
470  * \brief Suspends a process.
471  *
472  * This function suspends the process by suspending the synchro
473  * it was waiting for completion.
474  *
475  * \param process a SIMIX process
476  */
477 void simcall_process_suspend(smx_process_t process)
478 {
479   xbt_assert(process, "Invalid parameters");
480
481   simcall_BODY_process_suspend(process);
482 }
483
484 /**
485  * \ingroup simix_process_management
486  * \brief Resumes a suspended process.
487  *
488  * This function resumes a suspended process by resuming the synchro
489  * it was waiting for completion.
490  *
491  * \param process a SIMIX process
492  */
493 void simcall_process_resume(smx_process_t process)
494 {
495   simcall_BODY_process_resume(process);
496 }
497
498 /**
499  * \ingroup simix_process_management
500  * \brief Returns the amount of SIMIX processes in the system
501  *
502  * Maestro internal process is not counted, only user code processes are
503  */
504 int simcall_process_count(void)
505 {
506   return simgrid::simix::kernel(SIMIX_process_count);
507 }
508
509 /**
510  * \ingroup simix_process_management
511  * \brief Return the PID of a #smx_process_t.
512  * \param process a SIMIX process
513  * \return the PID of this process
514  */
515 int simcall_process_get_PID(smx_process_t process)
516 {
517   return SIMIX_process_get_PID(process);
518 }
519
520 /**
521  * \ingroup simix_process_management
522  * \brief Return the parent PID of a #smx_process_t.
523  * \param process a SIMIX process
524  * \return the PID of this process parenrt
525  */
526 int simcall_process_get_PPID(smx_process_t process)
527 {
528   return SIMIX_process_get_PPID(process);
529 }
530
531 /**
532  * \ingroup simix_process_management
533  * \brief Return the user data of a #smx_process_t.
534  * \param process a SIMIX process
535  * \return the user data of this process
536  */
537 void* simcall_process_get_data(smx_process_t process)
538 {
539   return SIMIX_process_get_data(process);
540 }
541
542 /**
543  * \ingroup simix_process_management
544  * \brief Set the user data of a #smx_process_t.
545  *
546  * This functions sets the user data associated to \a process.
547  * \param process SIMIX process
548  * \param data User data
549  */
550 void simcall_process_set_data(smx_process_t process, void *data)
551 {
552   simgrid::simix::kernel(std::bind(SIMIX_process_set_data, process, data));
553 }
554
555 static void kill_process_from_timer(void* arg)
556 {
557   smx_process_t process = (smx_process_t) arg;
558   simix_global->kill_process_function(process);
559   process->kill_timer=NULL;
560 }
561
562 /**
563  * \ingroup simix_process_management
564  * \brief Set the kill time of a process.
565  */
566 void simcall_process_set_kill_time(smx_process_t process, double kill_time)
567 {
568
569   if (kill_time > SIMIX_get_clock()) {
570     if (simix_global->kill_process_function) {
571       XBT_DEBUG("Set kill time %f for process %s(%s)",kill_time, process->name,
572           sg_host_get_name(process->host));
573       process->kill_timer = SIMIX_timer_set(kill_time, kill_process_from_timer, process);
574     }
575   }
576 }
577 /**
578  * \ingroup simix_process_management
579  * \brief Get the kill time of a process (or 0 if unset).
580  */
581 double simcall_process_get_kill_time(smx_process_t process) {
582   return SIMIX_timer_get_date(process->kill_timer);
583 }
584
585 /**
586  * \ingroup simix_process_management
587  * \brief Return the location on which an agent is running.
588  *
589  * This functions returns the sg_host_t corresponding to the location on which
590  * \a process is running.
591  * \param process SIMIX process
592  * \return SIMIX host
593  */
594 sg_host_t simcall_process_get_host(smx_process_t process)
595 {
596   return SIMIX_process_get_host(process);
597 }
598
599 /**
600  * \ingroup simix_process_management
601  * \brief Return the name of an agent.
602  *
603  * This functions checks whether \a process is a valid pointer or not and return its name.
604  * \param process SIMIX process
605  * \return The process name
606  */
607 const char* simcall_process_get_name(smx_process_t process)
608 {
609   return SIMIX_process_get_name(process);
610 }
611
612 /**
613  * \ingroup simix_process_management
614  * \brief Returns true if the process is suspended .
615  *
616  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
617  * \param process SIMIX process
618  * \return 1, if the process is suspended, else 0.
619  */
620 int simcall_process_is_suspended(smx_process_t process)
621 {
622   return simcall_BODY_process_is_suspended(process);
623 }
624
625 /**
626  * \ingroup simix_process_management
627  * \brief Return the properties
628  *
629  * This functions returns the properties associated with this process
630  */
631 xbt_dict_t simcall_process_get_properties(smx_process_t process)
632 {
633   return SIMIX_process_get_properties(process);
634 }
635 /**
636  * \ingroup simix_process_management
637  * \brief Add an on_exit function
638  * Add an on_exit function which will be executed when the process exits/is killed.
639  */
640 XBT_PUBLIC(void) simcall_process_on_exit(smx_process_t process, int_f_pvoid_pvoid_t fun, void *data)
641 {
642   simcall_BODY_process_on_exit(process, fun, data);
643 }
644 /**
645  * \ingroup simix_process_management
646  * \brief Sets the process to be auto-restarted or not by SIMIX when its host comes back up.
647  * Will restart the process when the host comes back up if auto_restart is set to 1.
648  */
649
650 XBT_PUBLIC(void) simcall_process_auto_restart_set(smx_process_t process, int auto_restart)
651 {
652   simcall_BODY_process_auto_restart_set(process, auto_restart);
653 }
654
655 /**
656  * \ingroup simix_process_management
657  * \brief Restarts the process, killing it and starting it again from scratch.
658  */
659 XBT_PUBLIC(smx_process_t) simcall_process_restart(smx_process_t process)
660 {
661   return (smx_process_t) simcall_BODY_process_restart(process);
662 }
663 /**
664  * \ingroup simix_process_management
665  * \brief Creates a new sleep SIMIX synchro.
666  *
667  * This function creates a SURF action and allocates the data necessary
668  * to create the SIMIX synchro. It can raise a host_error exception if the
669  * host crashed. The default SIMIX name of the synchro is "sleep".
670  *
671  *   \param duration Time duration of the sleep.
672  *   \return A result telling whether the sleep was successful
673  */
674 e_smx_state_t simcall_process_sleep(double duration)
675 {
676   /* checking for infinite values */
677   xbt_assert(std::isfinite(duration), "duration is not finite!");
678   return (e_smx_state_t) simcall_BODY_process_sleep(duration);
679 }
680
681 /**
682  *  \ingroup simix_mbox_management
683  *  \brief Creates a new rendez-vous point
684  *  \param name The name of the rendez-vous point
685  *  \return The created rendez-vous point
686  */
687 smx_mailbox_t simcall_mbox_create(const char *name)
688 {
689   return simcall_BODY_mbox_create(name);
690 }
691
692 /**
693  *  \ingroup simix_mbox_management
694  *  \brief Returns a rendez-vous point knowing its name
695  */
696 smx_mailbox_t simcall_mbox_get_by_name(const char *name)
697 {
698   /* FIXME: this is a horrible loss 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   return SIMIX_mbox_get_by_name(name);
703 }
704
705 /**
706  *  \ingroup simix_mbox_management
707  *  \brief returns the communication at the head of the rendez-vous
708  *  \param mbox The rendez-vous point
709  *  \return The communication or NULL if empty
710  */
711 smx_synchro_t simcall_mbox_get_head(smx_mailbox_t mbox)
712 {
713   return simcall_BODY_mbox_get_head(mbox);
714 }
715
716 void simcall_mbox_set_receiver(smx_mailbox_t mbox, smx_process_t process)
717 {
718   simcall_BODY_mbox_set_receiver(mbox, process);
719 }
720
721 smx_process_t simcall_mbox_get_receiver(smx_mailbox_t mbox)
722 {
723   return simcall_BODY_mbox_get_receiver(mbox);
724 }
725
726 /**
727  * \ingroup simix_comm_management
728  */
729 void simcall_comm_send(smx_process_t sender, smx_mailbox_t mbox, double task_size, double rate,
730                          void *src_buff, size_t src_buff_size,
731                          int (*match_fun)(void *, void *, smx_synchro_t),
732                          void (*copy_data_fun)(smx_synchro_t, void*, size_t), void *data,
733                          double timeout)
734 {
735   /* checking for infinite values */
736   xbt_assert(std::isfinite(task_size), "task_size is not finite!");
737   xbt_assert(std::isfinite(rate), "rate is not finite!");
738   xbt_assert(std::isfinite(timeout), "timeout is not finite!");
739
740   xbt_assert(mbox, "No rendez-vous point defined for send");
741
742   if (MC_is_active() || MC_record_replay_is_active()) {
743     /* the model-checker wants two separate simcalls */
744     smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simcall */
745     comm = simcall_comm_isend(sender, mbox, task_size, rate,
746         src_buff, src_buff_size, match_fun, NULL, copy_data_fun, data, 0);
747     simcall_comm_wait(comm, timeout);
748     comm = NULL;
749   }
750   else {
751     simcall_BODY_comm_send(sender, mbox, task_size, rate, src_buff, src_buff_size,
752                          match_fun, copy_data_fun, data, timeout);
753   }
754 }
755
756 /**
757  * \ingroup simix_comm_management
758  */
759 smx_synchro_t simcall_comm_isend(smx_process_t sender, smx_mailbox_t mbox, double task_size, double rate,
760                               void *src_buff, size_t src_buff_size,
761                               int (*match_fun)(void *, void *, smx_synchro_t),
762                               void (*clean_fun)(void *),
763                               void (*copy_data_fun)(smx_synchro_t, void*, size_t),
764                               void *data,
765                               int detached)
766 {
767   /* checking for infinite values */
768   xbt_assert(std::isfinite(task_size), "task_size is not finite!");
769   xbt_assert(std::isfinite(rate), "rate is not finite!");
770
771   xbt_assert(mbox, "No rendez-vous point defined for isend");
772
773   return simcall_BODY_comm_isend(sender, mbox, task_size, rate, src_buff,
774                                  src_buff_size, match_fun,
775                                  clean_fun, copy_data_fun, data, detached);
776 }
777
778 /**
779  * \ingroup simix_comm_management
780  */
781 void simcall_comm_recv(smx_process_t receiver, smx_mailbox_t mbox, void *dst_buff, size_t * dst_buff_size,
782                        int (*match_fun)(void *, void *, smx_synchro_t),
783                        void (*copy_data_fun)(smx_synchro_t, void*, size_t),
784                        void *data, double timeout, double rate)
785 {
786   xbt_assert(std::isfinite(timeout), "timeout is not finite!");
787   xbt_assert(mbox, "No rendez-vous point defined for recv");
788
789   if (MC_is_active() || MC_record_replay_is_active()) {
790     /* the model-checker wants two separate simcalls */
791     smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simcall */
792     comm = simcall_comm_irecv(receiver, mbox, dst_buff, dst_buff_size,
793                               match_fun, copy_data_fun, data, rate);
794     simcall_comm_wait(comm, timeout);
795     comm = NULL;
796   }
797   else {
798     simcall_BODY_comm_recv(receiver, mbox, dst_buff, dst_buff_size,
799                            match_fun, copy_data_fun, data, timeout, rate);
800   }
801 }
802 /**
803  * \ingroup simix_comm_management
804  */
805 smx_synchro_t simcall_comm_irecv(smx_process_t receiver, smx_mailbox_t mbox, void *dst_buff, size_t *dst_buff_size,
806                                 int (*match_fun)(void *, void *, smx_synchro_t),
807                                 void (*copy_data_fun)(smx_synchro_t, void*, size_t),
808                                 void *data, double rate)
809 {
810   xbt_assert(mbox, "No rendez-vous point defined for irecv");
811
812   return simcall_BODY_comm_irecv(receiver, mbox, dst_buff, dst_buff_size,
813                                  match_fun, copy_data_fun, data, rate);
814 }
815
816 /**
817  * \ingroup simix_comm_management
818  */
819 smx_synchro_t simcall_comm_iprobe(smx_mailbox_t mbox, int type, int src, int tag,
820                                 int (*match_fun)(void *, void *, smx_synchro_t), void *data)
821 {
822   xbt_assert(mbox, "No rendez-vous point defined for iprobe");
823
824   return simcall_BODY_comm_iprobe(mbox, type, src, tag, match_fun, data);
825 }
826
827 /**
828  * \ingroup simix_comm_management
829  */
830 void simcall_comm_cancel(smx_synchro_t comm)
831 {
832   simcall_BODY_comm_cancel(comm);
833 }
834
835 /**
836  * \ingroup simix_comm_management
837  */
838 unsigned int simcall_comm_waitany(xbt_dynar_t comms)
839 {
840   return simcall_BODY_comm_waitany(comms);
841 }
842
843 /**
844  * \ingroup simix_comm_management
845  */
846 int simcall_comm_testany(xbt_dynar_t comms)
847 {
848   if (xbt_dynar_is_empty(comms))
849     return -1;
850   return simcall_BODY_comm_testany(comms);
851 }
852
853 /**
854  * \ingroup simix_comm_management
855  */
856 void simcall_comm_wait(smx_synchro_t comm, double timeout)
857 {
858   xbt_assert(std::isfinite(timeout), "timeout is not finite!");
859   simcall_BODY_comm_wait(comm, timeout);
860 }
861
862 /**
863  * \brief Set the category of an synchro.
864  *
865  * This functions changes the category only. It calls a surf function.
866  * \param execution The execution synchro
867  * \param category The tracing category
868  */
869 void simcall_set_category(smx_synchro_t synchro, const char *category)
870 {
871   if (category == NULL) {
872     return;
873   }
874   simcall_BODY_set_category(synchro, category);
875 }
876
877 /**
878  * \ingroup simix_comm_management
879  *
880  */
881 int simcall_comm_test(smx_synchro_t comm)
882 {
883   return simcall_BODY_comm_test(comm);
884 }
885
886 /**
887  * \ingroup simix_comm_management
888  *
889  */
890 double simcall_comm_get_remains(smx_synchro_t comm)
891 {
892   return simcall_BODY_comm_get_remains(comm);
893 }
894
895 /**
896  * \ingroup simix_comm_management
897  *
898  */
899 void *simcall_comm_get_src_data(smx_synchro_t comm)
900 {
901   return simcall_BODY_comm_get_src_data(comm);
902 }
903
904 /**
905  * \ingroup simix_comm_management
906  *
907  */
908 void *simcall_comm_get_dst_data(smx_synchro_t comm)
909 {
910   return simcall_BODY_comm_get_dst_data(comm);
911 }
912
913 /**
914  * \ingroup simix_comm_management
915  *
916  */
917 smx_process_t simcall_comm_get_src_proc(smx_synchro_t comm)
918 {
919   return simcall_BODY_comm_get_src_proc(comm);
920 }
921
922 /**
923  * \ingroup simix_comm_management
924  *
925  */
926 smx_process_t simcall_comm_get_dst_proc(smx_synchro_t comm)
927 {
928   return simcall_BODY_comm_get_dst_proc(comm);
929 }
930
931 /**
932  * \ingroup simix_synchro_management
933  *
934  */
935 smx_mutex_t simcall_mutex_init(void)
936 {
937   if(!simix_global) {
938     fprintf(stderr,"You must run MSG_init before using MSG\n"); // We can't use xbt_die since we may get there before the initialization
939     xbt_abort();
940   }
941   return simcall_BODY_mutex_init();
942 }
943
944 /**
945  * \ingroup simix_synchro_management
946  *
947  */
948 void simcall_mutex_lock(smx_mutex_t mutex)
949 {
950   simcall_BODY_mutex_lock(mutex);
951 }
952
953 /**
954  * \ingroup simix_synchro_management
955  *
956  */
957 int simcall_mutex_trylock(smx_mutex_t mutex)
958 {
959   return simcall_BODY_mutex_trylock(mutex);
960 }
961
962 /**
963  * \ingroup simix_synchro_management
964  *
965  */
966 void simcall_mutex_unlock(smx_mutex_t mutex)
967 {
968   simcall_BODY_mutex_unlock(mutex);
969 }
970
971 /**
972  * \ingroup simix_synchro_management
973  *
974  */
975 smx_cond_t simcall_cond_init(void)
976 {
977   return simcall_BODY_cond_init();
978 }
979
980 /**
981  * \ingroup simix_synchro_management
982  *
983  */
984 void simcall_cond_signal(smx_cond_t cond)
985 {
986   simcall_BODY_cond_signal(cond);
987 }
988
989 /**
990  * \ingroup simix_synchro_management
991  *
992  */
993 void simcall_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
994 {
995   simcall_BODY_cond_wait(cond, mutex);
996 }
997
998 /**
999  * \ingroup simix_synchro_management
1000  *
1001  */
1002 void simcall_cond_wait_timeout(smx_cond_t cond,
1003                                  smx_mutex_t mutex,
1004                                  double timeout)
1005 {
1006   xbt_assert(std::isfinite(timeout), "timeout is not finite!");
1007   simcall_BODY_cond_wait_timeout(cond, mutex, timeout);
1008 }
1009
1010 /**
1011  * \ingroup simix_synchro_management
1012  *
1013  */
1014 void simcall_cond_broadcast(smx_cond_t cond)
1015 {
1016   simcall_BODY_cond_broadcast(cond);
1017 }
1018
1019 /**
1020  * \ingroup simix_synchro_management
1021  *
1022  */
1023 smx_sem_t simcall_sem_init(int capacity)
1024 {
1025   return simcall_BODY_sem_init(capacity);
1026 }
1027
1028 /**
1029  * \ingroup simix_synchro_management
1030  *
1031  */
1032 void simcall_sem_release(smx_sem_t sem)
1033 {
1034   simcall_BODY_sem_release(sem);
1035 }
1036
1037 /**
1038  * \ingroup simix_synchro_management
1039  *
1040  */
1041 int simcall_sem_would_block(smx_sem_t sem)
1042 {
1043   return simcall_BODY_sem_would_block(sem);
1044 }
1045
1046 /**
1047  * \ingroup simix_synchro_management
1048  *
1049  */
1050 void simcall_sem_acquire(smx_sem_t sem)
1051 {
1052   simcall_BODY_sem_acquire(sem);
1053 }
1054
1055 /**
1056  * \ingroup simix_synchro_management
1057  *
1058  */
1059 void simcall_sem_acquire_timeout(smx_sem_t sem, double timeout)
1060 {
1061   xbt_assert(std::isfinite(timeout), "timeout is not finite!");
1062   simcall_BODY_sem_acquire_timeout(sem, timeout);
1063 }
1064
1065 /**
1066  * \ingroup simix_synchro_management
1067  *
1068  */
1069 int simcall_sem_get_capacity(smx_sem_t sem)
1070 {
1071   return simcall_BODY_sem_get_capacity(sem);
1072 }
1073
1074 /**
1075  * \ingroup simix_file_management
1076  *
1077  */
1078 sg_size_t simcall_file_read(smx_file_t fd, sg_size_t size, sg_host_t host)
1079 {
1080   return simcall_BODY_file_read(fd, size, host);
1081 }
1082
1083 /**
1084  * \ingroup simix_file_management
1085  *
1086  */
1087 sg_size_t simcall_file_write(smx_file_t fd, sg_size_t size, sg_host_t host)
1088 {
1089   return simcall_BODY_file_write(fd, size, host);
1090 }
1091
1092 /**
1093  * \ingroup simix_file_management
1094  * \brief
1095  */
1096 smx_file_t simcall_file_open(const char* fullpath, sg_host_t host)
1097 {
1098   return simcall_BODY_file_open(fullpath, host);
1099 }
1100
1101 /**
1102  * \ingroup simix_file_management
1103  *
1104  */
1105 int simcall_file_close(smx_file_t fd, sg_host_t host)
1106 {
1107   return simcall_BODY_file_close(fd, host);
1108 }
1109
1110 /**
1111  * \ingroup simix_file_management
1112  *
1113  */
1114 int simcall_file_unlink(smx_file_t fd, sg_host_t host)
1115 {
1116   return simcall_BODY_file_unlink(fd, host);
1117 }
1118
1119 /**
1120  * \ingroup simix_file_management
1121  *
1122  */
1123 sg_size_t simcall_file_get_size(smx_file_t fd){
1124   return simcall_BODY_file_get_size(fd);
1125 }
1126
1127 /**
1128  * \ingroup simix_file_management
1129  *
1130  */
1131 sg_size_t simcall_file_tell(smx_file_t fd){
1132   return simcall_BODY_file_tell(fd);
1133 }
1134
1135 /**
1136  * \ingroup simix_file_management
1137  *
1138  */
1139 xbt_dynar_t simcall_file_get_info(smx_file_t fd)
1140 {
1141   return simcall_BODY_file_get_info(fd);
1142 }
1143
1144 /**
1145  * \ingroup simix_file_management
1146  *
1147  */
1148 int simcall_file_seek(smx_file_t fd, sg_offset_t offset, int origin){
1149   return simcall_BODY_file_seek(fd, offset, origin);
1150 }
1151
1152 /**
1153  * \ingroup simix_file_management
1154  * \brief Move a file to another location on the *same mount point*.
1155  *
1156  */
1157 int simcall_file_move(smx_file_t fd, const char* fullpath)
1158 {
1159   return simcall_BODY_file_move(fd, fullpath);
1160 }
1161
1162 /**
1163  * \ingroup simix_storage_management
1164  * \brief Returns the free space size on a given storage element.
1165  * \param storage a storage
1166  * \return Return the free space size on a given storage element (as sg_size_t)
1167  */
1168 sg_size_t simcall_storage_get_free_size (smx_storage_t storage){
1169   return simcall_BODY_storage_get_free_size(storage);
1170 }
1171
1172 /**
1173  * \ingroup simix_storage_management
1174  * \brief Returns the used space size on a given storage element.
1175  * \param storage a storage
1176  * \return Return the used space size on a given storage element (as sg_size_t)
1177  */
1178 sg_size_t simcall_storage_get_used_size (smx_storage_t storage){
1179   return simcall_BODY_storage_get_used_size(storage);
1180 }
1181
1182 /**
1183  * \ingroup simix_storage_management
1184  * \brief Returns a dict of the properties assigned to a storage element.
1185  *
1186  * \param storage A storage element
1187  * \return The properties of this storage element
1188  */
1189 xbt_dict_t simcall_storage_get_properties(smx_storage_t storage)
1190 {
1191   return simcall_BODY_storage_get_properties(storage);
1192 }
1193
1194 /**
1195  * \ingroup simix_storage_management
1196  * \brief Returns a dict containing the content of a storage element.
1197  *
1198  * \param storage A storage element
1199  * \return The content of this storage element as a dict (full path file => size)
1200  */
1201 xbt_dict_t simcall_storage_get_content(smx_storage_t storage)
1202 {
1203   return simcall_BODY_storage_get_content(storage);
1204 }
1205
1206 void simcall_run_kernel(std::function<void()> const& code)
1207 {
1208   return simcall_BODY_run_kernel((void*) &code);
1209 }
1210
1211 int simcall_mc_random(int min, int max) {
1212   return simcall_BODY_mc_random(min, max);
1213 }
1214
1215 /* ************************************************************************** */
1216
1217 /** @brief returns a printable string representing a simcall */
1218 const char *SIMIX_simcall_name(e_smx_simcall_t kind) {
1219   return simcall_names[kind];
1220 }