Logo AND Algorithmique Numérique Distribuée

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