Logo AND Algorithmique Numérique Distribuée

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