Logo AND Algorithmique Numérique Distribuée

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