Logo AND Algorithmique Numérique Distribuée

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