Logo AND Algorithmique Numérique Distribuée

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