Logo AND Algorithmique Numérique Distribuée

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