Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot//simgrid/simgrid
[simgrid.git] / src / simix / smx_user.c
1 #include "private.h"
2 #include "mc/mc.h"
3 #include <math.h> /* isfinite() */
4
5 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
6
7 static const char* request_names[] = {
8 #undef SIMIX_REQ_ENUM_ELEMENT
9 #define SIMIX_REQ_ENUM_ELEMENT(x) #x /* generate strings from the enumeration values */
10 SIMIX_REQ_LIST
11 #undef SIMIX_REQ_ENUM_ELEMENT
12 };
13
14 /**
15  * \brief Returns a host given its name.
16  *
17  * \param name The name of the host to get
18  * \return The corresponding host
19  */
20 smx_host_t SIMIX_req_host_get_by_name(const char *name)
21 {
22   smx_req_t req = SIMIX_req_mine();
23
24   req->call = REQ_HOST_GET_BY_NAME;
25   req->host_get_by_name.name = name;
26   SIMIX_request_push();
27   return req->host_get_by_name.result;
28 }
29
30 /**
31  * \brief Returns the name of a host.
32  *
33  * \param host A SIMIX host
34  * \return The name of this host
35  */
36 const char* SIMIX_req_host_get_name(smx_host_t host)
37 {
38   smx_req_t req = SIMIX_req_mine();
39
40   req->call = REQ_HOST_GET_NAME;
41   req->host_get_name.host = host;
42   SIMIX_request_push();
43   return req->host_get_name.result;
44 }
45
46 /**
47  * \brief Returns a dict of the properties assigned to a host.
48  *
49  * \param host A host
50  * \return The properties of this host
51  */
52 xbt_dict_t SIMIX_req_host_get_properties(smx_host_t host)
53 {
54   smx_req_t req = SIMIX_req_mine();
55
56   req->call = REQ_HOST_GET_PROPERTIES;
57   req->host_get_properties.host = host;
58   SIMIX_request_push();
59   return req->host_get_properties.result;
60 }
61
62 /**
63  * \brief Returns the speed of the processor.
64  *
65  * The speed returned does not take into account the current load on the machine.
66  * \param host A SIMIX host
67  * \return The speed of this host (in Mflop/s)
68  */
69 double SIMIX_req_host_get_speed(smx_host_t host)
70 {
71   smx_req_t req = SIMIX_req_mine();
72
73   req->call = REQ_HOST_GET_SPEED;
74   req->host_get_speed.host = host;
75   SIMIX_request_push();
76   return req->host_get_speed.result;
77 }
78
79 /**
80  * \brief Returns the available speed of the processor.
81  *
82  * \return Speed currently available (in Mflop/s)
83  */
84 double SIMIX_req_host_get_available_speed(smx_host_t host)
85 {
86   smx_req_t req = SIMIX_req_mine();
87
88   req->call = REQ_HOST_GET_AVAILABLE_SPEED;
89   req->host_get_available_speed.host = host;
90   SIMIX_request_push();
91   return req->host_get_available_speed.result;
92 }
93
94 /**
95  * \brief Returns the state of a host.
96  *
97  * Two states are possible: 1 if the host is active or 0 if it has crashed.
98  * \param host A SIMIX host
99  * \return 1 if the host is available, 0 otherwise
100  */
101 int SIMIX_req_host_get_state(smx_host_t host)
102 {
103   smx_req_t req = SIMIX_req_mine();
104
105   req->call = REQ_HOST_GET_STATE;
106   req->host_get_state.host = host;
107   SIMIX_request_push();
108   return req->host_get_state.result;
109 }
110
111 /**
112  * \brief Returns the user data associated to a host.
113  *
114  * \param host SIMIX host
115  * \return the user data of this host
116  */
117 void* SIMIX_req_host_get_data(smx_host_t host)
118 {
119   smx_req_t req = SIMIX_req_mine();
120
121   req->call = REQ_HOST_GET_DATA;
122   req->host_get_data.host = host;
123   SIMIX_request_push();
124   return req->host_get_data.result;
125 }
126
127 /**
128  * \brief Sets the user data associated to a host.
129  *
130  * The host must not have previous user data associated to it.
131  * \param A host SIMIX host
132  * \param data The user data to set
133  */
134 void SIMIX_req_host_set_data(smx_host_t host, void *data)
135 {
136   smx_req_t req = SIMIX_req_mine();
137
138   req->call = REQ_HOST_SET_DATA;
139   req->host_set_data.host = host;
140   req->host_set_data.data = data;
141   SIMIX_request_push();
142 }
143
144 /** \brief Creates an action that executes some computation of an host.
145  *
146  * This function creates a SURF action and allocates the data necessary
147  * to create the SIMIX action. It can raise a host_error exception if the host crashed.
148  *
149  * \param name Name of the execution action to create
150  * \param host SIMIX host where the action will be executed
151  * \param amount Computation amount (in bytes)
152  * \return A new SIMIX execution action
153  */
154 smx_action_t SIMIX_req_host_execute(const char *name, smx_host_t host,
155                                     double computation_amount,
156                                     double priority)
157 {
158   /* checking for infinite values */
159   xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
160   xbt_assert(isfinite(priority), "priority is not finite!");
161   
162   smx_req_t req = SIMIX_req_mine();
163
164   req->call = REQ_HOST_EXECUTE;
165   req->host_execute.name = name;
166   req->host_execute.host = host;
167   req->host_execute.computation_amount = computation_amount;
168   req->host_execute.priority = priority;
169   SIMIX_request_push();
170   return req->host_execute.result;
171 }
172
173 /** \brief Creates an action that may involve parallel computation on
174  * several hosts and communication between them.
175  *
176  * \param name Name of the execution action to create
177  * \param host_nb Number of hosts where the action will be executed
178  * \param host_list Array (of size host_nb) of hosts where the action will be executed
179  * \param computation_amount Array (of size host_nb) of computation amount of hosts (in bytes)
180  * \param communication_amount Array (of size host_nb * host_nb) representing the communication
181  * amount between each pair of hosts
182  * \param amount the SURF action amount
183  * \param rate the SURF action rate
184  * \return A new SIMIX execution action
185  */
186 smx_action_t SIMIX_req_host_parallel_execute(const char *name,
187                                          int host_nb,
188                                          smx_host_t *host_list,
189                                          double *computation_amount,
190                                          double *communication_amount,
191                                          double amount,
192                                          double rate)
193 {
194   int i,j;
195   /* checking for infinite values */
196   for (i = 0 ; i < host_nb ; ++i) {
197      xbt_assert(isfinite(computation_amount[i]), "computation_amount[%d] is not finite!", i);
198      for (j = 0 ; j < host_nb ; ++j) {
199         xbt_assert(isfinite(communication_amount[i + host_nb * j]), 
200                    "communication_amount[%d+%d*%d] is not finite!", i, host_nb, j);
201      }   
202   }   
203  
204   xbt_assert(isfinite(amount), "amount is not finite!");
205   xbt_assert(isfinite(rate), "rate is not finite!");
206   
207   smx_req_t req = SIMIX_req_mine();
208
209   req->call = REQ_HOST_PARALLEL_EXECUTE;
210   req->host_parallel_execute.name = name;
211   req->host_parallel_execute.host_nb = host_nb;
212   req->host_parallel_execute.host_list = host_list;
213   req->host_parallel_execute.computation_amount = computation_amount;
214   req->host_parallel_execute.communication_amount = communication_amount;
215   req->host_parallel_execute.amount = amount;
216   req->host_parallel_execute.rate = rate;
217   SIMIX_request_push();
218   return req->host_parallel_execute.result;
219 }
220
221 /**
222  * \brief Destroys an execution action.
223  *
224  * Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
225  * \param action The execution action to destroy
226  */
227 void SIMIX_req_host_execution_destroy(smx_action_t execution)
228 {
229   smx_req_t req = SIMIX_req_mine();
230
231   req->call = REQ_HOST_EXECUTION_DESTROY;
232   req->host_execution_destroy.execution = execution;
233   SIMIX_request_push();
234 }
235
236 /**
237  * \brief Cancels an execution action.
238  *
239  * This functions stops the execution. It calls a surf function.
240  * \param action The execution action to cancel
241  */
242 void SIMIX_req_host_execution_cancel(smx_action_t execution)
243 {
244   smx_req_t req = SIMIX_req_mine();
245
246   req->call = REQ_HOST_EXECUTION_CANCEL;
247   req->host_execution_cancel.execution = execution;
248   SIMIX_request_push();
249 }
250
251 /**
252  * \brief Returns how much of an execution action remains to be done.
253  *
254  * \param Action The execution action
255  * \return The remaining amount
256  */
257 double SIMIX_req_host_execution_get_remains(smx_action_t execution)
258 {
259   smx_req_t req = SIMIX_req_mine();
260
261   req->call = REQ_HOST_EXECUTION_GET_REMAINS;
262   req->host_execution_get_remains.execution = execution;
263   SIMIX_request_push();
264   return req->host_execution_get_remains.result;
265 }
266
267 /**
268  * \brief Returns the state of an execution action.
269  *
270  * \param execution The execution action
271  * \return The state
272  */
273 e_smx_state_t SIMIX_req_host_execution_get_state(smx_action_t execution)
274 {
275   smx_req_t req = SIMIX_req_mine();
276
277   req->call = REQ_HOST_EXECUTION_GET_STATE;
278   req->host_execution_get_state.execution = execution;
279   SIMIX_request_push();
280   return req->host_execution_get_state.result;
281 }
282
283 /**
284  * \brief Changes the priority of an execution action.
285  *
286  * This functions changes the priority only. It calls a surf function.
287  * \param execution The execution action
288  * \param priority The new priority
289  */
290 void SIMIX_req_host_execution_set_priority(smx_action_t execution, double priority)
291 {
292   /* checking for infinite values */
293   xbt_assert(isfinite(priority), "priority is not finite!");
294   
295   smx_req_t req = SIMIX_req_mine();
296
297   req->call = REQ_HOST_EXECUTION_SET_PRIORITY;
298   req->host_execution_set_priority.execution = execution;
299   req->host_execution_set_priority.priority = priority;
300   SIMIX_request_push();
301 }
302
303 /**
304  * \brief Waits for the completion of an execution action and destroy it.
305  *
306  * \param execution The execution action
307  */
308 e_smx_state_t SIMIX_req_host_execution_wait(smx_action_t execution)
309 {
310   smx_req_t req = SIMIX_req_mine();
311
312   req->call = REQ_HOST_EXECUTION_WAIT;
313   req->host_execution_wait.execution = execution;
314   SIMIX_request_push();
315   return req->host_execution_wait.result;
316 }
317
318 /**
319  * \brief Creates and runs a new SIMIX process.
320  *
321  * The structure and the corresponding thread are created and put in the list of ready processes.
322  *
323  * \param process the process created will be stored in this pointer
324  * \param name a name for the process. It is for user-level information and can be NULL.
325  * \param code the main function of the process
326  * \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.
327  * It can be retrieved with the function \ref SIMIX_req_process_get_data.
328  * \param hostname name of the host where the new agent is executed.
329  * \param argc first argument passed to \a code
330  * \param argv second argument passed to \a code
331  * \param properties the properties of the process
332  */
333 void SIMIX_req_process_create(smx_process_t *process, const char *name,
334                               xbt_main_func_t code,
335                               void *data,
336                               const char *hostname,
337                               int argc, char **argv,
338                               xbt_dict_t properties)
339 {
340   smx_req_t req = SIMIX_req_mine();
341
342   req->call = REQ_PROCESS_CREATE;
343   req->process_create.process = process;
344   req->process_create.name = name;
345   req->process_create.code = code;
346   req->process_create.data = data;
347   req->process_create.hostname = hostname;
348   req->process_create.argc = argc;
349   req->process_create.argv = argv;
350   req->process_create.properties = properties;
351   SIMIX_request_push();
352 }
353
354 /** \brief Kills a SIMIX process.
355  *
356  * This function simply kills a  process.
357  *
358  * \param process poor victim
359  */
360 void SIMIX_req_process_kill(smx_process_t process)
361 {
362   smx_req_t req = SIMIX_req_mine();
363
364   req->call = REQ_PROCESS_KILL;
365   req->process_kill.process = process;
366   SIMIX_request_push();
367 }
368
369 /** \brief Kills all SIMIX processes.
370  */
371 void SIMIX_req_process_killall(void)
372 {
373   smx_req_t req = SIMIX_req_mine();
374
375   req->call = REQ_PROCESS_KILLALL;
376   SIMIX_request_push();
377 }
378
379 /** \brief Cleans up a SIMIX process.
380  * \param process poor victim (must have already been killed)
381  */
382 void SIMIX_req_process_cleanup(smx_process_t process)
383 {
384   smx_req_t req = SIMIX_req_mine();
385
386   req->call = REQ_PROCESS_CLEANUP;
387   req->process_cleanup.process = process;
388   SIMIX_request_push();
389 }
390
391 /**
392  * \brief Migrates an agent to another location.
393  *
394  * This function changes the value of the host on which \a process is running.
395  *
396  * \param process the process to migrate
397  * \param source name of the previous host
398  * \param dest name of the new host
399  */
400 void SIMIX_req_process_change_host(smx_process_t process, smx_host_t dest)
401 {
402   smx_req_t req = SIMIX_req_mine();
403
404   req->call = REQ_PROCESS_CHANGE_HOST;
405   req->process_change_host.process = process;
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 }