Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fbfc647b7d70cb9cdad43a89a78f95a59761ba07
[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, smx_host_t 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.dest = dest;
406   SIMIX_request_push();
407 }
408
409 /**
410  * \brief Suspends a process.
411  *
412  * This function suspends the process by suspending the action
413  * it was waiting for completion.
414  *
415  * \param process a SIMIX process
416  */
417 void SIMIX_req_process_suspend(smx_process_t process)
418 {
419   xbt_assert(process, "Invalid parameters");
420
421   smx_req_t req = SIMIX_req_mine();
422
423   req->call = REQ_PROCESS_SUSPEND;
424   req->process_suspend.process = process;
425   SIMIX_request_push();
426 }
427
428 /**
429  * \brief Resumes a suspended process.
430  *
431  * This function resumes a suspended process by resuming the action
432  * it was waiting for completion.
433  *
434  * \param process a SIMIX process
435  */
436 void SIMIX_req_process_resume(smx_process_t process)
437 {
438   smx_req_t req = SIMIX_req_mine();
439
440   req->call = REQ_PROCESS_RESUME;
441   req->process_resume.process = process;
442   SIMIX_request_push();
443 }
444
445 /**
446  * \brief Returns the amount of SIMIX processes in the system
447  *
448  * Maestro internal process is not counted, only user code processes are
449  */
450 int SIMIX_req_process_count(void)
451 {
452   smx_req_t req = SIMIX_req_mine();
453
454   req->call = REQ_PROCESS_COUNT;
455   SIMIX_request_push();
456   return req->process_count.result;
457 }
458
459 /**
460  * \brief Return the user data of a #smx_process_t.
461  *
462  * 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.
463  * \param process SIMIX process
464  * \return A void pointer to the user data
465  */
466 void* SIMIX_req_process_get_data(smx_process_t process)
467 {
468   if (process == SIMIX_process_self()) {
469     /* avoid a request if this function is called by the process itself */
470     return SIMIX_process_self_get_data();
471   }
472
473   smx_req_t req = SIMIX_req_mine();
474
475   req->call = REQ_PROCESS_GET_DATA;
476   req->process_get_data.process = process;
477   SIMIX_request_push();
478   return req->process_get_data.result;
479 }
480
481 /**
482  * \brief Set the user data of a #m_process_t.
483  *
484  * 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.
485  * \param process SIMIX process
486  * \param data User data
487  */
488 void SIMIX_req_process_set_data(smx_process_t process, void *data)
489 {
490   if (process == SIMIX_process_self()) {
491     /* avoid a request if this function is called by the process itself */
492     SIMIX_process_self_set_data(data);
493   }
494   else {
495
496     smx_req_t req = SIMIX_req_mine();
497
498     req->call = REQ_PROCESS_SET_DATA;
499     req->process_set_data.process = process;
500     req->process_set_data.data = data;
501     SIMIX_request_push();
502   }
503 }
504
505 /**
506  * \brief Return the location on which an agent is running.
507  *
508  * 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.
509  * \param process SIMIX process
510  * \return SIMIX host
511  */
512 smx_host_t SIMIX_req_process_get_host(smx_process_t process)
513 {
514   smx_req_t req = SIMIX_req_mine();
515
516   req->call = REQ_PROCESS_GET_HOST;
517   req->process_get_host.process = process;
518   SIMIX_request_push();
519   return req->process_get_host.result;
520 }
521
522 /**
523  * \brief Return the name of an agent.
524  *
525  * This functions checks whether \a process is a valid pointer or not and return its name.
526  * \param process SIMIX process
527  * \return The process name
528  */
529 const char* SIMIX_req_process_get_name(smx_process_t process)
530 {
531   if (process == SIMIX_process_self()) {
532     /* avoid a request if this function is called by the process itself */
533     return process->name;
534   }
535
536   smx_req_t req = SIMIX_req_mine();
537
538   req->call = REQ_PROCESS_GET_NAME;
539   req->process_get_name.process = process;
540   SIMIX_request_push();
541   return req->process_get_name.result;
542 }
543
544 /**
545  * \brief Returns true if the process is suspended .
546  *
547  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
548  * \param process SIMIX process
549  * \return 1, if the process is suspended, else 0.
550  */
551 int SIMIX_req_process_is_suspended(smx_process_t process)
552 {
553   smx_req_t req = SIMIX_req_mine();
554
555   req->call = REQ_PROCESS_IS_SUSPENDED;
556   req->process_is_suspended.process = process;
557   SIMIX_request_push();
558   return req->process_is_suspended.result;
559 }
560
561 /** \ingroup m_process_management
562  * \brief Return the properties
563  *
564  * This functions returns the properties associated with this process
565  */
566 xbt_dict_t SIMIX_req_process_get_properties(smx_process_t process)
567 {
568   smx_req_t req = SIMIX_req_mine();
569
570   req->call = REQ_PROCESS_GET_PROPERTIES;
571   req->process_get_properties.process = process;
572   SIMIX_request_push();
573   return req->process_get_properties.result;
574 }
575
576 /** \brief Creates a new sleep SIMIX action.
577  *
578  * This function creates a SURF action and allocates the data necessary
579  * to create the SIMIX action. It can raise a host_error exception if the
580  * host crashed. The default SIMIX name of the action is "sleep".
581  *
582  *      \param duration Time duration of the sleep.
583  *      \return A result telling whether the sleep was successful
584  */
585 e_smx_state_t SIMIX_req_process_sleep(double duration)
586 {
587   /* checking for infinite values */
588   xbt_assert(isfinite(duration), "duration is not finite!");
589   
590   smx_req_t req = SIMIX_req_mine();
591
592   req->call = REQ_PROCESS_SLEEP;
593   req->process_sleep.duration = duration;
594   SIMIX_request_push();
595   return req->process_sleep.result;
596 }
597
598 /**
599  *  \brief Creates a new rendez-vous point
600  *  \param name The name of the rendez-vous point
601  *  \return The created rendez-vous point
602  */
603 smx_rdv_t SIMIX_req_rdv_create(const char *name)
604 {
605   smx_req_t req = SIMIX_req_mine();
606
607   req->call = REQ_RDV_CREATE;
608   req->rdv_create.name = name;
609
610   SIMIX_request_push();
611   return req->rdv_create.result;
612 }
613
614
615 /**
616  *  \brief Destroy a rendez-vous point
617  *  \param name The rendez-vous point to destroy
618  */
619 void SIMIX_req_rdv_destroy(smx_rdv_t rdv)
620 {
621   smx_req_t req = SIMIX_req_mine();
622
623   req->call = REQ_RDV_DESTROY;
624   req->rdv_destroy.rdv = rdv;
625
626   SIMIX_request_push();
627 }
628
629 smx_rdv_t SIMIX_req_rdv_get_by_name(const char *name)
630 {
631   xbt_assert(name != NULL, "Invalid parameter for SIMIX_req_rdv_get_by_name (name is NULL)");
632
633   /* FIXME: this is a horrible lost of performance, so we hack it out by
634    * skipping the request (for now). It won't work on distributed but
635    * probably we will change MSG for that. */
636 /*
637   smx_req_t req = SIMIX_req_mine();
638   req->call = REQ_RDV_GEY_BY_NAME;
639   req->rdv_get_by_name.name = name;
640   SIMIX_request_push();
641   return req->rdv_get_by_name.result;*/
642
643   return SIMIX_rdv_get_by_name(name);
644 }
645
646 /**
647  *  \brief counts the number of communication requests of a given host pending
648  *         on a rendez-vous point
649  *  \param rdv The rendez-vous point
650  *  \param host The host to be counted
651  *  \return The number of comm request pending in the rdv
652  */
653 int SIMIX_req_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
654 {
655   smx_req_t req = SIMIX_req_mine();
656
657   req->call = REQ_RDV_COMM_COUNT_BY_HOST;
658   req->rdv_comm_count_by_host.rdv = rdv;
659   req->rdv_comm_count_by_host.host = host;
660
661   SIMIX_request_push();
662   return req->rdv_comm_count_by_host.result;
663 }
664
665 /**
666  *  \brief returns the communication at the head of the rendez-vous
667  *  \param rdv The rendez-vous point
668  *  \return The communication or NULL if empty
669  */
670 smx_action_t SIMIX_req_rdv_get_head(smx_rdv_t rdv)
671 {
672   smx_req_t req = SIMIX_req_mine();
673
674   req->call = REQ_RDV_GET_HEAD;
675   req->rdv_get_head.rdv = rdv;
676
677   SIMIX_request_push();
678   return req->rdv_get_head.result;
679 }
680
681 void SIMIX_req_comm_send(smx_rdv_t rdv, double task_size, double rate,
682                          void *src_buff, size_t src_buff_size,
683                          int (*match_fun)(void *, void *), void *data,
684                          double timeout)
685 {
686   /* checking for infinite values */
687   xbt_assert(isfinite(task_size), "task_size is not finite!");
688   xbt_assert(isfinite(rate), "rate is not finite!");
689   xbt_assert(isfinite(timeout), "timeout is not finite!");
690   
691   xbt_assert(rdv, "No rendez-vous point defined for send");
692
693   if (MC_IS_ENABLED) {
694     /* the model-checker wants two separate requests */
695     smx_action_t comm = SIMIX_req_comm_isend(rdv, task_size, rate,
696         src_buff, src_buff_size, match_fun, data, 0);
697     SIMIX_req_comm_wait(comm, timeout);
698   }
699   else {
700     smx_req_t req = SIMIX_req_mine();
701
702     req->call = REQ_COMM_SEND;
703     req->comm_send.rdv = rdv;
704     req->comm_send.task_size = task_size;
705     req->comm_send.rate = rate;
706     req->comm_send.src_buff = src_buff;
707     req->comm_send.src_buff_size = src_buff_size;
708     req->comm_send.match_fun = match_fun;
709     req->comm_send.data = data;
710     req->comm_send.timeout = timeout;
711
712     SIMIX_request_push();
713   }
714 }
715
716 smx_action_t SIMIX_req_comm_isend(smx_rdv_t rdv, double task_size, double rate,
717                               void *src_buff, size_t src_buff_size,
718                               int (*match_fun)(void *, void *), void *data,
719                               int detached)
720 {
721   /* checking for infinite values */
722   xbt_assert(isfinite(task_size), "task_size is not finite!");
723   xbt_assert(isfinite(rate), "rate is not finite!");
724   
725   xbt_assert(rdv, "No rendez-vous point defined for isend");
726
727   smx_req_t req = SIMIX_req_mine();
728
729   req->call = REQ_COMM_ISEND;
730   req->comm_isend.rdv = rdv;
731   req->comm_isend.task_size = task_size;
732   req->comm_isend.rate = rate;
733   req->comm_isend.src_buff = src_buff;
734   req->comm_isend.src_buff_size = src_buff_size;
735   req->comm_isend.match_fun = match_fun;
736   req->comm_isend.data = data;
737   req->comm_isend.detached = detached;
738
739   SIMIX_request_push();
740   return req->comm_isend.result;
741 }
742
743 void SIMIX_req_comm_recv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
744                          int (*match_fun)(void *, void *), void *data, double timeout)
745 {
746   xbt_assert(isfinite(timeout), "timeout is not finite!");
747   xbt_assert(rdv, "No rendez-vous point defined for recv");
748
749   if (MC_IS_ENABLED) {
750     /* the model-checker wants two separate requests */
751     smx_action_t comm = SIMIX_req_comm_irecv(rdv, dst_buff, dst_buff_size,
752         match_fun, data);
753     SIMIX_req_comm_wait(comm, timeout);
754   }
755   else {
756     smx_req_t req = SIMIX_req_mine();
757
758     req->call = REQ_COMM_RECV;
759     req->comm_recv.rdv = rdv;
760     req->comm_recv.dst_buff = dst_buff;
761     req->comm_recv.dst_buff_size = dst_buff_size;
762     req->comm_recv.match_fun = match_fun;
763     req->comm_recv.data = data;
764     req->comm_recv.timeout = timeout;
765
766     SIMIX_request_push();
767   }
768 }
769
770 smx_action_t SIMIX_req_comm_irecv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
771                                   int (*match_fun)(void *, void *), void *data)
772 {
773   xbt_assert(rdv, "No rendez-vous point defined for irecv");
774
775   smx_req_t req = SIMIX_req_mine();
776
777   req->call = REQ_COMM_IRECV;
778   req->comm_irecv.rdv = rdv;
779   req->comm_irecv.dst_buff = dst_buff;
780   req->comm_irecv.dst_buff_size = dst_buff_size;
781   req->comm_irecv.match_fun = match_fun;
782   req->comm_irecv.data = data;
783
784   SIMIX_request_push();
785   return req->comm_irecv.result;
786 }
787
788 void SIMIX_req_comm_destroy(smx_action_t comm)
789 {
790   xbt_assert(comm, "Invalid parameter");
791
792   /* FIXME remove this request type: comms are auto-destroyed now,
793    * but what happens with unfinished comms? */
794
795   /*
796   smx_req_t req = SIMIX_req_mine();
797
798   req->call = REQ_COMM_DESTROY;
799   req->comm_destroy.comm = comm;
800
801   SIMIX_request_push();
802   */
803 }
804
805 void SIMIX_req_comm_cancel(smx_action_t comm)
806 {
807   smx_req_t req = SIMIX_req_mine();
808
809   req->call = REQ_COMM_CANCEL;
810   req->comm_cancel.comm = comm;
811
812   SIMIX_request_push();
813 }
814
815 unsigned int SIMIX_req_comm_waitany(xbt_dynar_t comms)
816 {
817   smx_req_t req = SIMIX_req_mine();
818
819   req->call = REQ_COMM_WAITANY;
820   req->comm_waitany.comms = comms;
821
822   SIMIX_request_push();
823   return req->comm_waitany.result;
824 }
825
826 int SIMIX_req_comm_testany(xbt_dynar_t comms)
827 {
828   smx_req_t req = SIMIX_req_mine();
829   if (xbt_dynar_length(comms)==0)
830     return -1;
831
832   req->call = REQ_COMM_TESTANY;
833   req->comm_testany.comms = comms;
834
835   SIMIX_request_push();
836   return req->comm_testany.result;
837 }
838
839 void SIMIX_req_comm_wait(smx_action_t comm, double timeout)
840 {
841   xbt_assert(isfinite(timeout), "timeout is not finite!");
842   
843   smx_req_t req = SIMIX_req_mine();
844
845   req->call = REQ_COMM_WAIT;
846   req->comm_wait.comm = comm;
847   req->comm_wait.timeout = timeout;
848
849   SIMIX_request_push();
850 }
851
852 #ifdef HAVE_TRACING
853 /**
854  * \brief Set the category of an action.
855  *
856  * This functions changes the category only. It calls a surf function.
857  * \param execution The execution action
858  * \param category The tracing category
859  */
860 void SIMIX_req_set_category(smx_action_t action, const char *category)
861 {
862   if (category == NULL) {
863     return;
864   }
865
866   smx_req_t req = SIMIX_req_mine();
867
868   req->call = REQ_SET_CATEGORY;
869   req->set_category.action = action;
870   req->set_category.category = category;
871
872   SIMIX_request_push();
873 }
874 #endif
875
876 int SIMIX_req_comm_test(smx_action_t comm)
877 {
878   smx_req_t req = SIMIX_req_mine();
879
880   req->call = REQ_COMM_TEST;
881   req->comm_test.comm = comm;
882
883   SIMIX_request_push();
884   return req->comm_test.result;
885 }
886
887 double SIMIX_req_comm_get_remains(smx_action_t comm)
888 {
889   smx_req_t req = SIMIX_req_mine();
890
891   req->call = REQ_COMM_GET_REMAINS;
892   req->comm_get_remains.comm = comm;
893
894   SIMIX_request_push();
895   return req->comm_get_remains.result;
896 }
897
898 e_smx_state_t SIMIX_req_comm_get_state(smx_action_t comm)
899 {
900   smx_req_t req = SIMIX_req_mine();
901
902   req->call = REQ_COMM_GET_STATE;
903   req->comm_get_state.comm = comm;
904
905   SIMIX_request_push();
906   return req->comm_get_state.result;
907 }
908
909 void *SIMIX_req_comm_get_src_data(smx_action_t comm)
910 {
911   smx_req_t req = SIMIX_req_mine();
912
913   req->call = REQ_COMM_GET_SRC_DATA;
914   req->comm_get_src_data.comm = comm;
915
916   SIMIX_request_push();
917   return req->comm_get_src_data.result;
918 }
919
920 void *SIMIX_req_comm_get_dst_data(smx_action_t comm)
921 {
922   smx_req_t req = SIMIX_req_mine();
923
924   req->call = REQ_COMM_GET_DST_DATA;
925   req->comm_get_dst_data.comm = comm;
926
927   SIMIX_request_push();
928   return req->comm_get_dst_data.result;
929 }
930
931 smx_process_t SIMIX_req_comm_get_src_proc(smx_action_t comm)
932 {
933   smx_req_t req = SIMIX_req_mine();
934
935   req->call = REQ_COMM_GET_SRC_PROC;
936   req->comm_get_src_proc.comm = comm;
937
938   SIMIX_request_push();
939   return req->comm_get_src_proc.result;
940 }
941
942 smx_process_t SIMIX_req_comm_get_dst_proc(smx_action_t comm)
943 {
944   smx_req_t req = SIMIX_req_mine();
945
946   req->call = REQ_COMM_GET_DST_PROC;
947   req->comm_get_dst_proc.comm = comm;
948
949   SIMIX_request_push();
950   return req->comm_get_dst_proc.result;
951 }
952
953 #ifdef HAVE_LATENCY_BOUND_TRACKING
954 int SIMIX_req_comm_is_latency_bounded(smx_action_t comm)
955 {
956   smx_req_t req = SIMIX_req_mine();
957
958   req->call = REQ_COMM_IS_LATENCY_BOUNDED;
959   req->comm_is_latency_bounded.comm = comm;
960
961   SIMIX_request_push();
962   return req->comm_is_latency_bounded.result;
963 }
964 #endif
965
966 smx_mutex_t SIMIX_req_mutex_init(void)
967 {
968   smx_req_t req = SIMIX_req_mine();
969
970   req->call = REQ_MUTEX_INIT;
971
972   SIMIX_request_push();
973   return req->mutex_init.result;
974 }
975
976 void SIMIX_req_mutex_destroy(smx_mutex_t mutex)
977 {
978   smx_req_t req = SIMIX_req_mine();
979
980   req->call = REQ_MUTEX_DESTROY;
981   req->mutex_destroy.mutex = mutex;
982
983   SIMIX_request_push();
984 }
985
986 void SIMIX_req_mutex_lock(smx_mutex_t mutex)
987 {
988   smx_req_t req = SIMIX_req_mine();
989
990   req->call = REQ_MUTEX_LOCK;
991   req->mutex_lock.mutex = mutex;
992
993   SIMIX_request_push();
994 }
995
996 int SIMIX_req_mutex_trylock(smx_mutex_t mutex)
997 {
998   smx_req_t req = SIMIX_req_mine();
999
1000   req->call = REQ_MUTEX_TRYLOCK;
1001   req->mutex_trylock.mutex = mutex;
1002
1003   SIMIX_request_push();
1004   return req->mutex_trylock.result;
1005 }
1006
1007 void SIMIX_req_mutex_unlock(smx_mutex_t mutex)
1008 {
1009   smx_req_t req = SIMIX_req_mine();
1010
1011   req->call = REQ_MUTEX_UNLOCK;
1012   req->mutex_unlock.mutex = mutex;
1013
1014   SIMIX_request_push();
1015 }
1016
1017
1018 smx_cond_t SIMIX_req_cond_init(void)
1019 {
1020   smx_req_t req = SIMIX_req_mine();
1021
1022   req->call = REQ_COND_INIT;
1023
1024   SIMIX_request_push();
1025   return req->cond_init.result;
1026 }
1027
1028 void SIMIX_req_cond_destroy(smx_cond_t cond)
1029 {
1030   smx_req_t req = SIMIX_req_mine();
1031
1032   req->call = REQ_COND_DESTROY;
1033   req->cond_destroy.cond = cond;
1034
1035   SIMIX_request_push();
1036 }
1037
1038 void SIMIX_req_cond_signal(smx_cond_t cond)
1039 {
1040   smx_req_t req = SIMIX_req_mine();
1041
1042   req->call = REQ_COND_SIGNAL;
1043   req->cond_signal.cond = cond;
1044
1045   SIMIX_request_push();
1046 }
1047
1048 void SIMIX_req_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
1049 {
1050   smx_req_t req = SIMIX_req_mine();
1051
1052   req->call = REQ_COND_WAIT;
1053   req->cond_wait.cond = cond;
1054   req->cond_wait.mutex = mutex;
1055
1056   SIMIX_request_push();
1057 }
1058
1059 void SIMIX_req_cond_wait_timeout(smx_cond_t cond,
1060                                  smx_mutex_t mutex,
1061                                  double timeout)
1062 {
1063   xbt_assert(isfinite(timeout), "timeout is not finite!");
1064   
1065   smx_req_t req = SIMIX_req_mine();
1066
1067   req->call = REQ_COND_WAIT_TIMEOUT;
1068   req->cond_wait_timeout.cond = cond;
1069   req->cond_wait_timeout.mutex = mutex;
1070   req->cond_wait_timeout.timeout = timeout;
1071
1072   SIMIX_request_push();
1073 }
1074
1075 void SIMIX_req_cond_broadcast(smx_cond_t cond)
1076 {
1077   smx_req_t req = SIMIX_req_mine();
1078
1079   req->call = REQ_COND_BROADCAST;
1080   req->cond_broadcast.cond = cond;
1081
1082   SIMIX_request_push();
1083 }
1084
1085
1086 smx_sem_t SIMIX_req_sem_init(int capacity)
1087 {
1088   smx_req_t req = SIMIX_req_mine();
1089
1090   req->call = REQ_SEM_INIT;
1091   req->sem_init.capacity = capacity;
1092
1093   SIMIX_request_push();
1094   return req->sem_init.result;
1095 }
1096
1097 void SIMIX_req_sem_destroy(smx_sem_t sem)
1098 {
1099   smx_req_t req = SIMIX_req_mine();
1100
1101   req->call = REQ_SEM_DESTROY;
1102   req->sem_destroy.sem = sem;
1103
1104   SIMIX_request_push();
1105 }
1106
1107 void SIMIX_req_sem_release(smx_sem_t sem)
1108 {
1109   smx_req_t req = SIMIX_req_mine();
1110
1111   req->call = REQ_SEM_RELEASE;
1112   req->sem_release.sem = sem;
1113
1114   SIMIX_request_push();
1115 }
1116
1117 int SIMIX_req_sem_would_block(smx_sem_t sem)
1118 {
1119   smx_req_t req = SIMIX_req_mine();
1120
1121   req->call = REQ_SEM_WOULD_BLOCK;
1122   req->sem_would_block.sem = sem;
1123
1124   SIMIX_request_push();
1125   return req->sem_would_block.result;
1126 }
1127
1128 void SIMIX_req_sem_acquire(smx_sem_t sem)
1129 {
1130   smx_req_t req = SIMIX_req_mine();
1131
1132   req->call = REQ_SEM_ACQUIRE;
1133   req->sem_acquire.sem = sem;
1134
1135   SIMIX_request_push();
1136 }
1137
1138 void SIMIX_req_sem_acquire_timeout(smx_sem_t sem, double timeout)
1139 {
1140   xbt_assert(isfinite(timeout), "timeout is not finite!");
1141   
1142   smx_req_t req = SIMIX_req_mine();
1143
1144   req->call = REQ_SEM_ACQUIRE_TIMEOUT;
1145   req->sem_acquire_timeout.sem = sem;
1146   req->sem_acquire_timeout.timeout = timeout;
1147
1148   SIMIX_request_push();
1149 }
1150
1151 int SIMIX_req_sem_get_capacity(smx_sem_t sem)
1152 {
1153   smx_req_t req = SIMIX_req_mine();
1154
1155   req->call = REQ_SEM_GET_CAPACITY;
1156   req->sem_get_capacity.sem = sem;
1157
1158   SIMIX_request_push();
1159   return req->sem_get_capacity.result;
1160 }
1161 /* ************************************************************************** */
1162
1163 /** @brief returns a printable string representing the request kind */
1164 const char *SIMIX_request_name(int kind) {
1165   return request_names[kind];
1166 }