Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Enforces that double parameters are finite (fixes #12243)
[simgrid.git] / src / simix / smx_user.c
1 #include "private.h"
2 #include "mc/mc.h"
3
4 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
5
6 static const char* request_names[] = {
7 #undef SIMIX_REQ_ENUM_ELEMENT
8 #define SIMIX_REQ_ENUM_ELEMENT(x) #x /* generate strings from the enumeration values */
9 SIMIX_REQ_LIST
10 #undef SIMIX_REQ_ENUM_ELEMENT
11 };
12
13 /**
14  * \brief Returns a host given its name.
15  *
16  * \param name The name of the host to get
17  * \return The corresponding host
18  */
19 smx_host_t SIMIX_req_host_get_by_name(const char *name)
20 {
21   smx_req_t req = SIMIX_req_mine();
22
23   req->call = REQ_HOST_GET_BY_NAME;
24   req->host_get_by_name.name = name;
25   SIMIX_request_push();
26   return req->host_get_by_name.result;
27 }
28
29 /**
30  * \brief Returns the name of a host.
31  *
32  * \param host A SIMIX host
33  * \return The name of this host
34  */
35 const char* SIMIX_req_host_get_name(smx_host_t host)
36 {
37   smx_req_t req = SIMIX_req_mine();
38
39   req->call = REQ_HOST_GET_NAME;
40   req->host_get_name.host = host;
41   SIMIX_request_push();
42   return req->host_get_name.result;
43 }
44
45 /**
46  * \brief Returns a dict of the properties assigned to a host.
47  *
48  * \param host A host
49  * \return The properties of this host
50  */
51 xbt_dict_t SIMIX_req_host_get_properties(smx_host_t host)
52 {
53   smx_req_t req = SIMIX_req_mine();
54
55   req->call = REQ_HOST_GET_PROPERTIES;
56   req->host_get_properties.host = host;
57   SIMIX_request_push();
58   return req->host_get_properties.result;
59 }
60
61 /**
62  * \brief Returns the speed of the processor.
63  *
64  * The speed returned does not take into account the current load on the machine.
65  * \param host A SIMIX host
66  * \return The speed of this host (in Mflop/s)
67  */
68 double SIMIX_req_host_get_speed(smx_host_t host)
69 {
70   smx_req_t req = SIMIX_req_mine();
71
72   req->call = REQ_HOST_GET_SPEED;
73   req->host_get_speed.host = host;
74   SIMIX_request_push();
75   return req->host_get_speed.result;
76 }
77
78 /**
79  * \brief Returns the available speed of the processor.
80  *
81  * \return Speed currently available (in Mflop/s)
82  */
83 double SIMIX_req_host_get_available_speed(smx_host_t host)
84 {
85   smx_req_t req = SIMIX_req_mine();
86
87   req->call = REQ_HOST_GET_AVAILABLE_SPEED;
88   req->host_get_available_speed.host = host;
89   SIMIX_request_push();
90   return req->host_get_available_speed.result;
91 }
92
93 /**
94  * \brief Returns the state of a host.
95  *
96  * Two states are possible: 1 if the host is active or 0 if it has crashed.
97  * \param host A SIMIX host
98  * \return 1 if the host is available, 0 otherwise
99  */
100 int SIMIX_req_host_get_state(smx_host_t host)
101 {
102   smx_req_t req = SIMIX_req_mine();
103
104   req->call = REQ_HOST_GET_STATE;
105   req->host_get_state.host = host;
106   SIMIX_request_push();
107   return req->host_get_state.result;
108 }
109
110 /**
111  * \brief Returns the user data associated to a host.
112  *
113  * \param host SIMIX host
114  * \return the user data of this host
115  */
116 void* SIMIX_req_host_get_data(smx_host_t host)
117 {
118   smx_req_t req = SIMIX_req_mine();
119
120   req->call = REQ_HOST_GET_DATA;
121   req->host_get_data.host = host;
122   SIMIX_request_push();
123   return req->host_get_data.result;
124 }
125
126 /**
127  * \brief Sets the user data associated to a host.
128  *
129  * The host must not have previous user data associated to it.
130  * \param A host SIMIX host
131  * \param data The user data to set
132  */
133 void SIMIX_req_host_set_data(smx_host_t host, void *data)
134 {
135   smx_req_t req = SIMIX_req_mine();
136
137   req->call = REQ_HOST_SET_DATA;
138   req->host_set_data.host = host;
139   req->host_set_data.data = data;
140   SIMIX_request_push();
141 }
142
143 /** \brief Creates an action that executes some computation of an host.
144  *
145  * This function creates a SURF action and allocates the data necessary
146  * to create the SIMIX action. It can raise a host_error exception if the host crashed.
147  *
148  * \param name Name of the execution action to create
149  * \param host SIMIX host where the action will be executed
150  * \param amount Computation amount (in bytes)
151  * \return A new SIMIX execution action
152  */
153 smx_action_t SIMIX_req_host_execute(const char *name, smx_host_t host,
154                                     double computation_amount,
155                                     double priority)
156 {
157   /* checking for infinite values */
158   xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
159   xbt_assert(isfinite(priority), "priority is not finite!");
160   
161   smx_req_t req = SIMIX_req_mine();
162
163   req->call = REQ_HOST_EXECUTE;
164   req->host_execute.name = name;
165   req->host_execute.host = host;
166   req->host_execute.computation_amount = computation_amount;
167   req->host_execute.priority = priority;
168   SIMIX_request_push();
169   return req->host_execute.result;
170 }
171
172 /** \brief Creates an action that may involve parallel computation on
173  * several hosts and communication between them.
174  *
175  * \param name Name of the execution action to create
176  * \param host_nb Number of hosts where the action will be executed
177  * \param host_list Array (of size host_nb) of hosts where the action will be executed
178  * \param computation_amount Array (of size host_nb) of computation amount of hosts (in bytes)
179  * \param communication_amount Array (of size host_nb * host_nb) representing the communication
180  * amount between each pair of hosts
181  * \param amount the SURF action amount
182  * \param rate the SURF action rate
183  * \return A new SIMIX execution action
184  */
185 smx_action_t SIMIX_req_host_parallel_execute(const char *name,
186                                          int host_nb,
187                                          smx_host_t *host_list,
188                                          double *computation_amount,
189                                          double *communication_amount,
190                                          double amount,
191                                          double rate)
192 {
193   int i,j;
194   /* checking for infinite values */
195   for (i = 0 ; i < host_nb ; ++i) {
196      xbt_assert(isfinite(computation_amount[i]), "computation_amount[%d] is not finite!", i);
197      for (j = 0 ; j < host_nb ; ++j) {
198         xbt_assert(isfinite(communication_amount[i + host_nb * j]), 
199                    "communication_amount[%d+%d*%d] is not finite!", i, host_nb, j);
200      }   
201   }   
202  
203   xbt_assert(isfinite(amount), "amount is not finite!");
204   xbt_assert(isfinite(rate), "rate is not finite!");
205   
206   smx_req_t req = SIMIX_req_mine();
207
208   req->call = REQ_HOST_PARALLEL_EXECUTE;
209   req->host_parallel_execute.name = name;
210   req->host_parallel_execute.host_nb = host_nb;
211   req->host_parallel_execute.host_list = host_list;
212   req->host_parallel_execute.computation_amount = computation_amount;
213   req->host_parallel_execute.communication_amount = communication_amount;
214   req->host_parallel_execute.amount = amount;
215   req->host_parallel_execute.rate = rate;
216   SIMIX_request_push();
217   return req->host_parallel_execute.result;
218 }
219
220 /**
221  * \brief Destroys an execution action.
222  *
223  * Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
224  * \param action The execution action to destroy
225  */
226 void SIMIX_req_host_execution_destroy(smx_action_t execution)
227 {
228   smx_req_t req = SIMIX_req_mine();
229
230   req->call = REQ_HOST_EXECUTION_DESTROY;
231   req->host_execution_destroy.execution = execution;
232   SIMIX_request_push();
233 }
234
235 /**
236  * \brief Cancels an execution action.
237  *
238  * This functions stops the execution. It calls a surf function.
239  * \param action The execution action to cancel
240  */
241 void SIMIX_req_host_execution_cancel(smx_action_t execution)
242 {
243   smx_req_t req = SIMIX_req_mine();
244
245   req->call = REQ_HOST_EXECUTION_CANCEL;
246   req->host_execution_cancel.execution = execution;
247   SIMIX_request_push();
248 }
249
250 /**
251  * \brief Returns how much of an execution action remains to be done.
252  *
253  * \param Action The execution action
254  * \return The remaining amount
255  */
256 double SIMIX_req_host_execution_get_remains(smx_action_t execution)
257 {
258   smx_req_t req = SIMIX_req_mine();
259
260   req->call = REQ_HOST_EXECUTION_GET_REMAINS;
261   req->host_execution_get_remains.execution = execution;
262   SIMIX_request_push();
263   return req->host_execution_get_remains.result;
264 }
265
266 /**
267  * \brief Returns the state of an execution action.
268  *
269  * \param execution The execution action
270  * \return The state
271  */
272 e_smx_state_t SIMIX_req_host_execution_get_state(smx_action_t execution)
273 {
274   smx_req_t req = SIMIX_req_mine();
275
276   req->call = REQ_HOST_EXECUTION_GET_STATE;
277   req->host_execution_get_state.execution = execution;
278   SIMIX_request_push();
279   return req->host_execution_get_state.result;
280 }
281
282 /**
283  * \brief Changes the priority of an execution action.
284  *
285  * This functions changes the priority only. It calls a surf function.
286  * \param execution The execution action
287  * \param priority The new priority
288  */
289 void SIMIX_req_host_execution_set_priority(smx_action_t execution, double priority)
290 {
291   /* checking for infinite values */
292   xbt_assert(isfinite(priority), "priority is not finite!");
293   
294   smx_req_t req = SIMIX_req_mine();
295
296   req->call = REQ_HOST_EXECUTION_SET_PRIORITY;
297   req->host_execution_set_priority.execution = execution;
298   req->host_execution_set_priority.priority = priority;
299   SIMIX_request_push();
300 }
301
302 /**
303  * \brief Waits for the completion of an execution action and destroy it.
304  *
305  * \param execution The execution action
306  */
307 e_smx_state_t SIMIX_req_host_execution_wait(smx_action_t execution)
308 {
309   smx_req_t req = SIMIX_req_mine();
310
311   req->call = REQ_HOST_EXECUTION_WAIT;
312   req->host_execution_wait.execution = execution;
313   SIMIX_request_push();
314   return req->host_execution_wait.result;
315 }
316
317 /**
318  * \brief Creates and runs a new SIMIX process.
319  *
320  * The structure and the corresponding thread are created and put in the list of ready processes.
321  *
322  * \param process the process created will be stored in this pointer
323  * \param name a name for the process. It is for user-level information and can be NULL.
324  * \param code the main function of the process
325  * \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.
326  * It can be retrieved with the function \ref SIMIX_req_process_get_data.
327  * \param hostname name of the host where the new agent is executed.
328  * \param argc first argument passed to \a code
329  * \param argv second argument passed to \a code
330  * \param properties the properties of the process
331  */
332 void SIMIX_req_process_create(smx_process_t *process, const char *name,
333                               xbt_main_func_t code,
334                               void *data,
335                               const char *hostname,
336                               int argc, char **argv,
337                               xbt_dict_t properties)
338 {
339   smx_req_t req = SIMIX_req_mine();
340
341   req->call = REQ_PROCESS_CREATE;
342   req->process_create.process = process;
343   req->process_create.name = name;
344   req->process_create.code = code;
345   req->process_create.data = data;
346   req->process_create.hostname = hostname;
347   req->process_create.argc = argc;
348   req->process_create.argv = argv;
349   req->process_create.properties = properties;
350   SIMIX_request_push();
351 }
352
353 /** \brief Kills a SIMIX process.
354  *
355  * This function simply kills a  process.
356  *
357  * \param process poor victim
358  */
359 void SIMIX_req_process_kill(smx_process_t process)
360 {
361   smx_req_t req = SIMIX_req_mine();
362
363   req->call = REQ_PROCESS_KILL;
364   req->process_kill.process = process;
365   SIMIX_request_push();
366 }
367
368 /** \brief Kills all SIMIX processes.
369  */
370 void SIMIX_req_process_killall(void)
371 {
372   smx_req_t req = SIMIX_req_mine();
373
374   req->call = REQ_PROCESS_KILLALL;
375   SIMIX_request_push();
376 }
377
378 /** \brief Cleans up a SIMIX process.
379  * \param process poor victim (must have already been killed)
380  */
381 void SIMIX_req_process_cleanup(smx_process_t process)
382 {
383   smx_req_t req = SIMIX_req_mine();
384
385   req->call = REQ_PROCESS_CLEANUP;
386   req->process_cleanup.process = process;
387   SIMIX_request_push();
388 }
389
390 /**
391  * \brief Migrates an agent to another location.
392  *
393  * This function changes the value of the host on which \a process is running.
394  *
395  * \param process the process to migrate
396  * \param source name of the previous host
397  * \param dest name of the new host
398  */
399 void SIMIX_req_process_change_host(smx_process_t process, const char *source, const char *dest)
400 {
401   smx_req_t req = SIMIX_req_mine();
402
403   req->call = REQ_PROCESS_CHANGE_HOST;
404   req->process_change_host.process = process;
405   req->process_change_host.source = source;
406   req->process_change_host.dest = dest;
407   SIMIX_request_push();
408 }
409
410 /**
411  * \brief Suspends a process.
412  *
413  * This function suspends the process by suspending the action
414  * it was waiting for completion.
415  *
416  * \param process a SIMIX process
417  */
418 void SIMIX_req_process_suspend(smx_process_t process)
419 {
420   xbt_assert(process, "Invalid parameters");
421
422   smx_req_t req = SIMIX_req_mine();
423
424   req->call = REQ_PROCESS_SUSPEND;
425   req->process_suspend.process = process;
426   SIMIX_request_push();
427 }
428
429 /**
430  * \brief Resumes a suspended process.
431  *
432  * This function resumes a suspended process by resuming the action
433  * it was waiting for completion.
434  *
435  * \param process a SIMIX process
436  */
437 void SIMIX_req_process_resume(smx_process_t process)
438 {
439   smx_req_t req = SIMIX_req_mine();
440
441   req->call = REQ_PROCESS_RESUME;
442   req->process_resume.process = process;
443   SIMIX_request_push();
444 }
445
446 /**
447  * \brief Returns the amount of SIMIX processes in the system
448  *
449  * Maestro internal process is not counted, only user code processes are
450  */
451 int SIMIX_req_process_count(void)
452 {
453   smx_req_t req = SIMIX_req_mine();
454
455   req->call = REQ_PROCESS_COUNT;
456   SIMIX_request_push();
457   return req->process_count.result;
458 }
459
460 /**
461  * \brief Return the user data of a #smx_process_t.
462  *
463  * This functions checks whether \a process is a valid pointer or not and return the user data associated to \a process if it is possible.
464  * \param process SIMIX process
465  * \return A void pointer to the user data
466  */
467 void* SIMIX_req_process_get_data(smx_process_t process)
468 {
469   if (process == SIMIX_process_self()) {
470     /* avoid a request if this function is called by the process itself */
471     return SIMIX_process_self_get_data();
472   }
473
474   smx_req_t req = SIMIX_req_mine();
475
476   req->call = REQ_PROCESS_GET_DATA;
477   req->process_get_data.process = process;
478   SIMIX_request_push();
479   return req->process_get_data.result;
480 }
481
482 /**
483  * \brief Set the user data of a #m_process_t.
484  *
485  * 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.
486  * \param process SIMIX process
487  * \param data User data
488  */
489 void SIMIX_req_process_set_data(smx_process_t process, void *data)
490 {
491   if (process == SIMIX_process_self()) {
492     /* avoid a request if this function is called by the process itself */
493     SIMIX_process_self_set_data(data);
494   }
495   else {
496
497     smx_req_t req = SIMIX_req_mine();
498
499     req->call = REQ_PROCESS_SET_DATA;
500     req->process_set_data.process = process;
501     req->process_set_data.data = data;
502     SIMIX_request_push();
503   }
504 }
505
506 /**
507  * \brief Return the location on which an agent is running.
508  *
509  * 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.
510  * \param process SIMIX process
511  * \return SIMIX host
512  */
513 smx_host_t SIMIX_req_process_get_host(smx_process_t process)
514 {
515   smx_req_t req = SIMIX_req_mine();
516
517   req->call = REQ_PROCESS_GET_HOST;
518   req->process_get_host.process = process;
519   SIMIX_request_push();
520   return req->process_get_host.result;
521 }
522
523 /**
524  * \brief Return the name of an agent.
525  *
526  * This functions checks whether \a process is a valid pointer or not and return its name.
527  * \param process SIMIX process
528  * \return The process name
529  */
530 const char* SIMIX_req_process_get_name(smx_process_t process)
531 {
532   if (process == SIMIX_process_self()) {
533     /* avoid a request if this function is called by the process itself */
534     return process->name;
535   }
536
537   smx_req_t req = SIMIX_req_mine();
538
539   req->call = REQ_PROCESS_GET_NAME;
540   req->process_get_name.process = process;
541   SIMIX_request_push();
542   return req->process_get_name.result;
543 }
544
545 /**
546  * \brief Returns true if the process is suspended .
547  *
548  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
549  * \param process SIMIX process
550  * \return 1, if the process is suspended, else 0.
551  */
552 int SIMIX_req_process_is_suspended(smx_process_t process)
553 {
554   smx_req_t req = SIMIX_req_mine();
555
556   req->call = REQ_PROCESS_IS_SUSPENDED;
557   req->process_is_suspended.process = process;
558   SIMIX_request_push();
559   return req->process_is_suspended.result;
560 }
561
562 /** \ingroup m_process_management
563  * \brief Return the properties
564  *
565  * This functions returns the properties associated with this process
566  */
567 xbt_dict_t SIMIX_req_process_get_properties(smx_process_t process)
568 {
569   smx_req_t req = SIMIX_req_mine();
570
571   req->call = REQ_PROCESS_GET_PROPERTIES;
572   req->process_get_properties.process = process;
573   SIMIX_request_push();
574   return req->process_get_properties.result;
575 }
576
577 /** \brief Creates a new sleep SIMIX action.
578  *
579  * This function creates a SURF action and allocates the data necessary
580  * to create the SIMIX action. It can raise a host_error exception if the
581  * host crashed. The default SIMIX name of the action is "sleep".
582  *
583  *      \param duration Time duration of the sleep.
584  *      \return A result telling whether the sleep was successful
585  */
586 e_smx_state_t SIMIX_req_process_sleep(double duration)
587 {
588   /* checking for infinite values */
589   xbt_assert(isfinite(duration), "duration is not finite!");
590   
591   smx_req_t req = SIMIX_req_mine();
592
593   req->call = REQ_PROCESS_SLEEP;
594   req->process_sleep.duration = duration;
595   SIMIX_request_push();
596   return req->process_sleep.result;
597 }
598
599 /**
600  *  \brief Creates a new rendez-vous point
601  *  \param name The name of the rendez-vous point
602  *  \return The created rendez-vous point
603  */
604 smx_rdv_t SIMIX_req_rdv_create(const char *name)
605 {
606   smx_req_t req = SIMIX_req_mine();
607
608   req->call = REQ_RDV_CREATE;
609   req->rdv_create.name = name;
610
611   SIMIX_request_push();
612   return req->rdv_create.result;
613 }
614
615
616 /**
617  *  \brief Destroy a rendez-vous point
618  *  \param name The rendez-vous point to destroy
619  */
620 void SIMIX_req_rdv_destroy(smx_rdv_t rdv)
621 {
622   smx_req_t req = SIMIX_req_mine();
623
624   req->call = REQ_RDV_DESTROY;
625   req->rdv_destroy.rdv = rdv;
626
627   SIMIX_request_push();
628 }
629
630 smx_rdv_t SIMIX_req_rdv_get_by_name(const char *name)
631 {
632   xbt_assert(name != NULL, "Invalid parameter for SIMIX_req_rdv_get_by_name (name is NULL)");
633
634   /* FIXME: this is a horrible lost of performance, so we hack it out by
635    * skipping the request (for now). It won't work on distributed but
636    * probably we will change MSG for that. */
637 /*
638   smx_req_t req = SIMIX_req_mine();
639   req->call = REQ_RDV_GEY_BY_NAME;
640   req->rdv_get_by_name.name = name;
641   SIMIX_request_push();
642   return req->rdv_get_by_name.result;*/
643
644   return SIMIX_rdv_get_by_name(name);
645 }
646
647 /**
648  *  \brief counts the number of communication requests of a given host pending
649  *         on a rendez-vous point
650  *  \param rdv The rendez-vous point
651  *  \param host The host to be counted
652  *  \return The number of comm request pending in the rdv
653  */
654 int SIMIX_req_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
655 {
656   smx_req_t req = SIMIX_req_mine();
657
658   req->call = REQ_RDV_COMM_COUNT_BY_HOST;
659   req->rdv_comm_count_by_host.rdv = rdv;
660   req->rdv_comm_count_by_host.host = host;
661
662   SIMIX_request_push();
663   return req->rdv_comm_count_by_host.result;
664 }
665
666 /**
667  *  \brief returns the communication at the head of the rendez-vous
668  *  \param rdv The rendez-vous point
669  *  \return The communication or NULL if empty
670  */
671 smx_action_t SIMIX_req_rdv_get_head(smx_rdv_t rdv)
672 {
673   smx_req_t req = SIMIX_req_mine();
674
675   req->call = REQ_RDV_GET_HEAD;
676   req->rdv_get_head.rdv = rdv;
677
678   SIMIX_request_push();
679   return req->rdv_get_head.result;
680 }
681
682 void SIMIX_req_comm_send(smx_rdv_t rdv, double task_size, double rate,
683                          void *src_buff, size_t src_buff_size,
684                          int (*match_fun)(void *, void *), void *data,
685                          double timeout)
686 {
687   /* checking for infinite values */
688   xbt_assert(isfinite(task_size), "task_size is not finite!");
689   xbt_assert(isfinite(rate), "rate is not finite!");
690   xbt_assert(isfinite(timeout), "timeout is not finite!");
691   
692   xbt_assert(rdv, "No rendez-vous point defined for send");
693
694   if (MC_IS_ENABLED) {
695     /* the model-checker wants two separate requests */
696     smx_action_t comm = SIMIX_req_comm_isend(rdv, task_size, rate,
697         src_buff, src_buff_size, match_fun, data, 0);
698     SIMIX_req_comm_wait(comm, timeout);
699   }
700   else {
701     smx_req_t req = SIMIX_req_mine();
702
703     req->call = REQ_COMM_SEND;
704     req->comm_send.rdv = rdv;
705     req->comm_send.task_size = task_size;
706     req->comm_send.rate = rate;
707     req->comm_send.src_buff = src_buff;
708     req->comm_send.src_buff_size = src_buff_size;
709     req->comm_send.match_fun = match_fun;
710     req->comm_send.data = data;
711     req->comm_send.timeout = timeout;
712
713     SIMIX_request_push();
714   }
715 }
716
717 smx_action_t SIMIX_req_comm_isend(smx_rdv_t rdv, double task_size, double rate,
718                               void *src_buff, size_t src_buff_size,
719                               int (*match_fun)(void *, void *), void *data,
720                               int detached)
721 {
722   /* checking for infinite values */
723   xbt_assert(isfinite(task_size), "task_size is not finite!");
724   xbt_assert(isfinite(rate), "rate is not finite!");
725   
726   xbt_assert(rdv, "No rendez-vous point defined for isend");
727
728   smx_req_t req = SIMIX_req_mine();
729
730   req->call = REQ_COMM_ISEND;
731   req->comm_isend.rdv = rdv;
732   req->comm_isend.task_size = task_size;
733   req->comm_isend.rate = rate;
734   req->comm_isend.src_buff = src_buff;
735   req->comm_isend.src_buff_size = src_buff_size;
736   req->comm_isend.match_fun = match_fun;
737   req->comm_isend.data = data;
738   req->comm_isend.detached = detached;
739
740   SIMIX_request_push();
741   return req->comm_isend.result;
742 }
743
744 void SIMIX_req_comm_recv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
745                          int (*match_fun)(void *, void *), void *data, double timeout)
746 {
747   xbt_assert(isfinite(timeout), "timeout is not finite!");
748   xbt_assert(rdv, "No rendez-vous point defined for recv");
749
750   if (MC_IS_ENABLED) {
751     /* the model-checker wants two separate requests */
752     smx_action_t comm = SIMIX_req_comm_irecv(rdv, dst_buff, dst_buff_size,
753         match_fun, data);
754     SIMIX_req_comm_wait(comm, timeout);
755   }
756   else {
757     smx_req_t req = SIMIX_req_mine();
758
759     req->call = REQ_COMM_RECV;
760     req->comm_recv.rdv = rdv;
761     req->comm_recv.dst_buff = dst_buff;
762     req->comm_recv.dst_buff_size = dst_buff_size;
763     req->comm_recv.match_fun = match_fun;
764     req->comm_recv.data = data;
765     req->comm_recv.timeout = timeout;
766
767     SIMIX_request_push();
768   }
769 }
770
771 smx_action_t SIMIX_req_comm_irecv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
772                                   int (*match_fun)(void *, void *), void *data)
773 {
774   xbt_assert(rdv, "No rendez-vous point defined for irecv");
775
776   smx_req_t req = SIMIX_req_mine();
777
778   req->call = REQ_COMM_IRECV;
779   req->comm_irecv.rdv = rdv;
780   req->comm_irecv.dst_buff = dst_buff;
781   req->comm_irecv.dst_buff_size = dst_buff_size;
782   req->comm_irecv.match_fun = match_fun;
783   req->comm_irecv.data = data;
784
785   SIMIX_request_push();
786   return req->comm_irecv.result;
787 }
788
789 void SIMIX_req_comm_destroy(smx_action_t comm)
790 {
791   xbt_assert(comm, "Invalid parameter");
792
793   /* FIXME remove this request type: comms are auto-destroyed now,
794    * but what happens with unfinished comms? */
795
796   /*
797   smx_req_t req = SIMIX_req_mine();
798
799   req->call = REQ_COMM_DESTROY;
800   req->comm_destroy.comm = comm;
801
802   SIMIX_request_push();
803   */
804 }
805
806 void SIMIX_req_comm_cancel(smx_action_t comm)
807 {
808   smx_req_t req = SIMIX_req_mine();
809
810   req->call = REQ_COMM_CANCEL;
811   req->comm_cancel.comm = comm;
812
813   SIMIX_request_push();
814 }
815
816 unsigned int SIMIX_req_comm_waitany(xbt_dynar_t comms)
817 {
818   smx_req_t req = SIMIX_req_mine();
819
820   req->call = REQ_COMM_WAITANY;
821   req->comm_waitany.comms = comms;
822
823   SIMIX_request_push();
824   return req->comm_waitany.result;
825 }
826
827 int SIMIX_req_comm_testany(xbt_dynar_t comms)
828 {
829   smx_req_t req = SIMIX_req_mine();
830   if (xbt_dynar_length(comms)==0)
831     return -1;
832
833   req->call = REQ_COMM_TESTANY;
834   req->comm_testany.comms = comms;
835
836   SIMIX_request_push();
837   return req->comm_testany.result;
838 }
839
840 void SIMIX_req_comm_wait(smx_action_t comm, double timeout)
841 {
842   xbt_assert(isfinite(timeout), "timeout is not finite!");
843   
844   smx_req_t req = SIMIX_req_mine();
845
846   req->call = REQ_COMM_WAIT;
847   req->comm_wait.comm = comm;
848   req->comm_wait.timeout = timeout;
849
850   SIMIX_request_push();
851 }
852
853 #ifdef HAVE_TRACING
854 /**
855  * \brief Set the category of an action.
856  *
857  * This functions changes the category only. It calls a surf function.
858  * \param execution The execution action
859  * \param category The tracing category
860  */
861 void SIMIX_req_set_category(smx_action_t action, const char *category)
862 {
863   if (category == NULL) {
864     return;
865   }
866
867   smx_req_t req = SIMIX_req_mine();
868
869   req->call = REQ_SET_CATEGORY;
870   req->set_category.action = action;
871   req->set_category.category = category;
872
873   SIMIX_request_push();
874 }
875 #endif
876
877 int SIMIX_req_comm_test(smx_action_t comm)
878 {
879   smx_req_t req = SIMIX_req_mine();
880
881   req->call = REQ_COMM_TEST;
882   req->comm_test.comm = comm;
883
884   SIMIX_request_push();
885   return req->comm_test.result;
886 }
887
888 double SIMIX_req_comm_get_remains(smx_action_t comm)
889 {
890   smx_req_t req = SIMIX_req_mine();
891
892   req->call = REQ_COMM_GET_REMAINS;
893   req->comm_get_remains.comm = comm;
894
895   SIMIX_request_push();
896   return req->comm_get_remains.result;
897 }
898
899 e_smx_state_t SIMIX_req_comm_get_state(smx_action_t comm)
900 {
901   smx_req_t req = SIMIX_req_mine();
902
903   req->call = REQ_COMM_GET_STATE;
904   req->comm_get_state.comm = comm;
905
906   SIMIX_request_push();
907   return req->comm_get_state.result;
908 }
909
910 void *SIMIX_req_comm_get_src_data(smx_action_t comm)
911 {
912   smx_req_t req = SIMIX_req_mine();
913
914   req->call = REQ_COMM_GET_SRC_DATA;
915   req->comm_get_src_data.comm = comm;
916
917   SIMIX_request_push();
918   return req->comm_get_src_data.result;
919 }
920
921 void *SIMIX_req_comm_get_dst_data(smx_action_t comm)
922 {
923   smx_req_t req = SIMIX_req_mine();
924
925   req->call = REQ_COMM_GET_DST_DATA;
926   req->comm_get_dst_data.comm = comm;
927
928   SIMIX_request_push();
929   return req->comm_get_dst_data.result;
930 }
931
932 smx_process_t SIMIX_req_comm_get_src_proc(smx_action_t comm)
933 {
934   smx_req_t req = SIMIX_req_mine();
935
936   req->call = REQ_COMM_GET_SRC_PROC;
937   req->comm_get_src_proc.comm = comm;
938
939   SIMIX_request_push();
940   return req->comm_get_src_proc.result;
941 }
942
943 smx_process_t SIMIX_req_comm_get_dst_proc(smx_action_t comm)
944 {
945   smx_req_t req = SIMIX_req_mine();
946
947   req->call = REQ_COMM_GET_DST_PROC;
948   req->comm_get_dst_proc.comm = comm;
949
950   SIMIX_request_push();
951   return req->comm_get_dst_proc.result;
952 }
953
954 #ifdef HAVE_LATENCY_BOUND_TRACKING
955 int SIMIX_req_comm_is_latency_bounded(smx_action_t comm)
956 {
957   smx_req_t req = SIMIX_req_mine();
958
959   req->call = REQ_COMM_IS_LATENCY_BOUNDED;
960   req->comm_is_latency_bounded.comm = comm;
961
962   SIMIX_request_push();
963   return req->comm_is_latency_bounded.result;
964 }
965 #endif
966
967 smx_mutex_t SIMIX_req_mutex_init(void)
968 {
969   smx_req_t req = SIMIX_req_mine();
970
971   req->call = REQ_MUTEX_INIT;
972
973   SIMIX_request_push();
974   return req->mutex_init.result;
975 }
976
977 void SIMIX_req_mutex_destroy(smx_mutex_t mutex)
978 {
979   smx_req_t req = SIMIX_req_mine();
980
981   req->call = REQ_MUTEX_DESTROY;
982   req->mutex_destroy.mutex = mutex;
983
984   SIMIX_request_push();
985 }
986
987 void SIMIX_req_mutex_lock(smx_mutex_t mutex)
988 {
989   smx_req_t req = SIMIX_req_mine();
990
991   req->call = REQ_MUTEX_LOCK;
992   req->mutex_lock.mutex = mutex;
993
994   SIMIX_request_push();
995 }
996
997 int SIMIX_req_mutex_trylock(smx_mutex_t mutex)
998 {
999   smx_req_t req = SIMIX_req_mine();
1000
1001   req->call = REQ_MUTEX_TRYLOCK;
1002   req->mutex_trylock.mutex = mutex;
1003
1004   SIMIX_request_push();
1005   return req->mutex_trylock.result;
1006 }
1007
1008 void SIMIX_req_mutex_unlock(smx_mutex_t mutex)
1009 {
1010   smx_req_t req = SIMIX_req_mine();
1011
1012   req->call = REQ_MUTEX_UNLOCK;
1013   req->mutex_unlock.mutex = mutex;
1014
1015   SIMIX_request_push();
1016 }
1017
1018
1019 smx_cond_t SIMIX_req_cond_init(void)
1020 {
1021   smx_req_t req = SIMIX_req_mine();
1022
1023   req->call = REQ_COND_INIT;
1024
1025   SIMIX_request_push();
1026   return req->cond_init.result;
1027 }
1028
1029 void SIMIX_req_cond_destroy(smx_cond_t cond)
1030 {
1031   smx_req_t req = SIMIX_req_mine();
1032
1033   req->call = REQ_COND_DESTROY;
1034   req->cond_destroy.cond = cond;
1035
1036   SIMIX_request_push();
1037 }
1038
1039 void SIMIX_req_cond_signal(smx_cond_t cond)
1040 {
1041   smx_req_t req = SIMIX_req_mine();
1042
1043   req->call = REQ_COND_SIGNAL;
1044   req->cond_signal.cond = cond;
1045
1046   SIMIX_request_push();
1047 }
1048
1049 void SIMIX_req_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
1050 {
1051   smx_req_t req = SIMIX_req_mine();
1052
1053   req->call = REQ_COND_WAIT;
1054   req->cond_wait.cond = cond;
1055   req->cond_wait.mutex = mutex;
1056
1057   SIMIX_request_push();
1058 }
1059
1060 void SIMIX_req_cond_wait_timeout(smx_cond_t cond,
1061                                  smx_mutex_t mutex,
1062                                  double timeout)
1063 {
1064   xbt_assert(isfinite(timeout), "timeout is not finite!");
1065   
1066   smx_req_t req = SIMIX_req_mine();
1067
1068   req->call = REQ_COND_WAIT_TIMEOUT;
1069   req->cond_wait_timeout.cond = cond;
1070   req->cond_wait_timeout.mutex = mutex;
1071   req->cond_wait_timeout.timeout = timeout;
1072
1073   SIMIX_request_push();
1074 }
1075
1076 void SIMIX_req_cond_broadcast(smx_cond_t cond)
1077 {
1078   smx_req_t req = SIMIX_req_mine();
1079
1080   req->call = REQ_COND_BROADCAST;
1081   req->cond_broadcast.cond = cond;
1082
1083   SIMIX_request_push();
1084 }
1085
1086
1087 smx_sem_t SIMIX_req_sem_init(int capacity)
1088 {
1089   smx_req_t req = SIMIX_req_mine();
1090
1091   req->call = REQ_SEM_INIT;
1092   req->sem_init.capacity = capacity;
1093
1094   SIMIX_request_push();
1095   return req->sem_init.result;
1096 }
1097
1098 void SIMIX_req_sem_destroy(smx_sem_t sem)
1099 {
1100   smx_req_t req = SIMIX_req_mine();
1101
1102   req->call = REQ_SEM_DESTROY;
1103   req->sem_destroy.sem = sem;
1104
1105   SIMIX_request_push();
1106 }
1107
1108 void SIMIX_req_sem_release(smx_sem_t sem)
1109 {
1110   smx_req_t req = SIMIX_req_mine();
1111
1112   req->call = REQ_SEM_RELEASE;
1113   req->sem_release.sem = sem;
1114
1115   SIMIX_request_push();
1116 }
1117
1118 int SIMIX_req_sem_would_block(smx_sem_t sem)
1119 {
1120   smx_req_t req = SIMIX_req_mine();
1121
1122   req->call = REQ_SEM_WOULD_BLOCK;
1123   req->sem_would_block.sem = sem;
1124
1125   SIMIX_request_push();
1126   return req->sem_would_block.result;
1127 }
1128
1129 void SIMIX_req_sem_acquire(smx_sem_t sem)
1130 {
1131   smx_req_t req = SIMIX_req_mine();
1132
1133   req->call = REQ_SEM_ACQUIRE;
1134   req->sem_acquire.sem = sem;
1135
1136   SIMIX_request_push();
1137 }
1138
1139 void SIMIX_req_sem_acquire_timeout(smx_sem_t sem, double timeout)
1140 {
1141   xbt_assert(isfinite(timeout), "timeout is not finite!");
1142   
1143   smx_req_t req = SIMIX_req_mine();
1144
1145   req->call = REQ_SEM_ACQUIRE_TIMEOUT;
1146   req->sem_acquire_timeout.sem = sem;
1147   req->sem_acquire_timeout.timeout = timeout;
1148
1149   SIMIX_request_push();
1150 }
1151
1152 int SIMIX_req_sem_get_capacity(smx_sem_t sem)
1153 {
1154   smx_req_t req = SIMIX_req_mine();
1155
1156   req->call = REQ_SEM_GET_CAPACITY;
1157   req->sem_get_capacity.sem = sem;
1158
1159   SIMIX_request_push();
1160   return req->sem_get_capacity.result;
1161 }
1162 /* ************************************************************************** */
1163
1164 /** @brief returns a printable string representing the request kind */
1165 const char *SIMIX_request_name(int kind) {
1166   return request_names[kind];
1167 }