Logo AND Algorithmique Numérique Distribuée

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