Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cf09a368659e53619972299a9cbc4717d7915ec1
[simgrid.git] / src / simix / smx_user.c
1 /* smx_user.c - public interface to simix                                   */
2
3 /* Copyright (c) 2010-2012. 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
8 #include "smx_private.h"
9 #include "mc/mc.h"
10 #include "xbt/ex.h"
11 #include <math.h>         /* isfinite() */
12
13 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
14
15 static const char* simcall_names[] = {
16 #undef SIMCALL_ENUM_ELEMENT
17 #define SIMCALL_ENUM_ELEMENT(x) #x /* generate strings from the enumeration values */
18 SIMCALL_LIST
19 #undef SIMCALL_ENUM_ELEMENT
20 };
21
22 /**
23  * \ingroup simix_host_management
24  * \brief Returns a host given its name.
25  *
26  * \param name The name of the host to get
27  * \return The corresponding host
28  */
29 smx_host_t simcall_host_get_by_name(const char *name)
30 {
31   smx_simcall_t simcall = SIMIX_simcall_mine();
32
33   simcall->call = SIMCALL_HOST_GET_BY_NAME;
34   simcall->host_get_by_name.name = name;
35   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
36     simcall->host_get_by_name.result = NULL;
37   SIMIX_simcall_push(simcall->issuer);
38   return simcall->host_get_by_name.result;
39 }
40
41 /**
42  * \ingroup simix_host_management
43  * \brief Returns the name of a host.
44  *
45  * \param host A SIMIX host
46  * \return The name of this host
47  */
48 const char* simcall_host_get_name(smx_host_t host)
49 {
50   smx_simcall_t simcall = SIMIX_simcall_mine();
51
52   simcall->call = SIMCALL_HOST_GET_NAME;
53   simcall->host_get_name.host = host;
54   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
55     simcall->host_get_name.result = NULL;
56   SIMIX_simcall_push(simcall->issuer);
57   return simcall->host_get_name.result;
58 }
59
60 /**
61  * \ingroup simix_host_management
62  * \brief Returns a dict of the properties assigned to a host.
63  *
64  * \param host A host
65  * \return The properties of this host
66  */
67 xbt_dict_t simcall_host_get_properties(smx_host_t host)
68 {
69   smx_simcall_t simcall = SIMIX_simcall_mine();
70
71   simcall->call = SIMCALL_HOST_GET_PROPERTIES;
72   simcall->host_get_properties.host = host;
73   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
74     simcall->host_get_properties.result = NULL;
75   SIMIX_simcall_push(simcall->issuer);
76   return simcall->host_get_properties.result;
77 }
78
79 /**
80  * \ingroup simix_host_management
81  * \brief Returns a dict of the properties assigned to a router or AS.
82  *
83  * \param name The name of the router or AS
84  * \return The properties
85  */
86 xbt_dict_t simcall_asr_get_properties(const char *name)
87 {
88   smx_simcall_t simcall = SIMIX_simcall_mine();
89
90   simcall->call = SIMCALL_ASR_GET_PROPERTIES;
91   simcall->asr_get_properties.name = name;
92   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
93     simcall->asr_get_properties.result = NULL;
94   SIMIX_simcall_push(simcall->issuer);
95   return simcall->asr_get_properties.result;
96 }
97
98
99 /**
100  * \ingroup simix_host_management
101  * \brief Returns the speed of the processor.
102  *
103  * The speed returned does not take into account the current load on the machine.
104  * \param host A SIMIX host
105  * \return The speed of this host (in Mflop/s)
106  */
107 double simcall_host_get_speed(smx_host_t host)
108 {
109   smx_simcall_t simcall = SIMIX_simcall_mine();
110
111   simcall->call = SIMCALL_HOST_GET_SPEED;
112   simcall->host_get_speed.host = host;
113   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
114     simcall->host_get_speed.result = 0.0;
115   SIMIX_simcall_push(simcall->issuer);
116   return simcall->host_get_speed.result;
117 }
118
119 /**
120  * \ingroup simix_host_management
121  * \brief Returns the available speed of the processor.
122  *
123  * \return Speed currently available (in Mflop/s)
124  */
125 double simcall_host_get_available_speed(smx_host_t host)
126 {
127   smx_simcall_t simcall = SIMIX_simcall_mine();
128
129   simcall->call = SIMCALL_HOST_GET_AVAILABLE_SPEED;
130   simcall->host_get_available_speed.host = host;
131   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
132     simcall->host_get_available_speed.result = 0.0;
133   SIMIX_simcall_push(simcall->issuer);
134   return simcall->host_get_available_speed.result;
135 }
136
137 /**
138  * \ingroup simix_host_management
139  * \brief Returns the state of a host.
140  *
141  * Two states are possible: 1 if the host is active or 0 if it has crashed.
142  * \param host A SIMIX host
143  * \return 1 if the host is available, 0 otherwise
144  */
145 int simcall_host_get_state(smx_host_t host)
146 {
147   smx_simcall_t simcall = SIMIX_simcall_mine();
148
149   simcall->call = SIMCALL_HOST_GET_STATE;
150   simcall->host_get_state.host = host;
151   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
152     simcall->host_get_state.result = -1;
153   SIMIX_simcall_push(simcall->issuer);
154   return simcall->host_get_state.result;
155 }
156
157 /**
158  * \ingroup simix_host_management
159  * \brief Returns the user data associated to a host.
160  *
161  * \param host SIMIX host
162  * \return the user data of this host
163  */
164 void* simcall_host_get_data(smx_host_t host)
165 {
166   smx_simcall_t simcall = SIMIX_simcall_mine();
167
168   simcall->call = SIMCALL_HOST_GET_DATA;
169   simcall->host_get_data.host = host;
170   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
171     simcall->host_get_data.result = NULL;
172   SIMIX_simcall_push(simcall->issuer);
173   return simcall->host_get_data.result;
174 }
175
176 /**
177  * \ingroup simix_host_management
178  * \brief Sets the user data associated to a host.
179  *
180  * The host must not have previous user data associated to it.
181  * \param host A SIMIX host
182  * \param data The user data to set
183  */
184 void simcall_host_set_data(smx_host_t host, void *data)
185 {
186   smx_simcall_t simcall = SIMIX_simcall_mine();
187
188   simcall->call = SIMCALL_HOST_SET_DATA;
189   simcall->host_set_data.host = host;
190   simcall->host_set_data.data = data;
191   SIMIX_simcall_push(simcall->issuer);
192 }
193
194 /**
195  * \ingroup simix_host_management
196  * \brief Creates an action that executes some computation of an host.
197  *
198  * This function creates a SURF action and allocates the data necessary
199  * to create the SIMIX action. It can raise a host_error exception if the host crashed.
200  *
201  * \param name Name of the execution action to create
202  * \param host SIMIX host where the action will be executed
203  * \param computation_amount amount Computation amount (in bytes)
204  * \param priority computation priority
205  * \return A new SIMIX execution action
206  */
207 smx_action_t simcall_host_execute(const char *name, smx_host_t host,
208                                     double computation_amount,
209                                     double priority)
210 {
211   /* checking for infinite values */
212   xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
213   xbt_assert(isfinite(priority), "priority is not finite!");
214   
215   smx_simcall_t simcall = SIMIX_simcall_mine();
216
217   simcall->call = SIMCALL_HOST_EXECUTE;
218   simcall->host_execute.name = name;
219   simcall->host_execute.host = host;
220   simcall->host_execute.computation_amount = computation_amount;
221   simcall->host_execute.priority = priority;
222   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
223     simcall->host_execute.result = NULL;
224   SIMIX_simcall_push(simcall->issuer);
225   return simcall->host_execute.result;
226 }
227
228 /**
229  * \ingroup simix_host_management
230  * \brief Creates an action that may involve parallel computation on
231  * several hosts and communication between them.
232  *
233  * \param name Name of the execution action to create
234  * \param host_nb Number of hosts where the action will be executed
235  * \param host_list Array (of size host_nb) of hosts where the action will be executed
236  * \param computation_amount Array (of size host_nb) of computation amount of hosts (in bytes)
237  * \param communication_amount Array (of size host_nb * host_nb) representing the communication
238  * amount between each pair of hosts
239  * \param amount the SURF action amount
240  * \param rate the SURF action rate
241  * \return A new SIMIX execution action
242  */
243 smx_action_t simcall_host_parallel_execute(const char *name,
244                                          int host_nb,
245                                          smx_host_t *host_list,
246                                          double *computation_amount,
247                                          double *communication_amount,
248                                          double amount,
249                                          double rate)
250 {
251   int i,j;
252   /* checking for infinite values */
253   for (i = 0 ; i < host_nb ; ++i) {
254      xbt_assert(isfinite(computation_amount[i]), "computation_amount[%d] is not finite!", i);
255      for (j = 0 ; j < host_nb ; ++j) {
256         xbt_assert(isfinite(communication_amount[i + host_nb * j]), 
257              "communication_amount[%d+%d*%d] is not finite!", i, host_nb, j);
258      }   
259   }   
260  
261   xbt_assert(isfinite(amount), "amount is not finite!");
262   xbt_assert(isfinite(rate), "rate is not finite!");
263   
264   smx_simcall_t simcall = SIMIX_simcall_mine();
265
266   simcall->call = SIMCALL_HOST_PARALLEL_EXECUTE;
267   simcall->host_parallel_execute.name = name;
268   simcall->host_parallel_execute.host_nb = host_nb;
269   simcall->host_parallel_execute.host_list = host_list;
270   simcall->host_parallel_execute.computation_amount = computation_amount;
271   simcall->host_parallel_execute.communication_amount = communication_amount;
272   simcall->host_parallel_execute.amount = amount;
273   simcall->host_parallel_execute.rate = rate;
274   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
275     simcall->host_parallel_execute.result = NULL;
276   SIMIX_simcall_push(simcall->issuer);
277   return simcall->host_parallel_execute.result;
278 }
279
280 /**
281  * \ingroup simix_host_management
282  * \brief Destroys an execution action.
283  *
284  * Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
285  * \param execution The execution action to destroy
286  */
287 void simcall_host_execution_destroy(smx_action_t execution)
288 {
289   smx_simcall_t simcall = SIMIX_simcall_mine();
290
291   simcall->call = SIMCALL_HOST_EXECUTION_DESTROY;
292   simcall->host_execution_destroy.execution = execution;
293   SIMIX_simcall_push(simcall->issuer);
294 }
295
296 /**
297  * \ingroup simix_host_management
298  * \brief Cancels an execution action.
299  *
300  * This functions stops the execution. It calls a surf function.
301  * \param execution The execution action to cancel
302  */
303 void simcall_host_execution_cancel(smx_action_t execution)
304 {
305   smx_simcall_t simcall = SIMIX_simcall_mine();
306
307   simcall->call = SIMCALL_HOST_EXECUTION_CANCEL;
308   simcall->host_execution_cancel.execution = execution;
309   SIMIX_simcall_push(simcall->issuer);
310 }
311
312 /**
313  * \ingroup simix_host_management
314  * \brief Returns how much of an execution action remains to be done.
315  *
316  * \param execution The execution action
317  * \return The remaining amount
318  */
319 double simcall_host_execution_get_remains(smx_action_t execution)
320 {
321   smx_simcall_t simcall = SIMIX_simcall_mine();
322
323   simcall->call = SIMCALL_HOST_EXECUTION_GET_REMAINS;
324   simcall->host_execution_get_remains.execution = execution;
325   if(MC_is_active()) /* Initializeialize result to a default value for snapshot comparison done during simcall */
326     simcall->host_execution_get_remains.result = 0.0;
327   SIMIX_simcall_push(simcall->issuer);
328   return simcall->host_execution_get_remains.result;
329 }
330
331 /**
332  * \ingroup simix_host_management
333  * \brief Returns the state of an execution action.
334  *
335  * \param execution The execution action
336  * \return The state
337  */
338 e_smx_state_t simcall_host_execution_get_state(smx_action_t execution)
339 {
340   smx_simcall_t simcall = SIMIX_simcall_mine();
341
342   simcall->call = SIMCALL_HOST_EXECUTION_GET_STATE;
343   simcall->host_execution_get_state.execution = execution;
344   simcall->host_execution_get_state.result = -1;
345   SIMIX_simcall_push(simcall->issuer);
346   return simcall->host_execution_get_state.result;
347 }
348
349 /**
350  * \ingroup simix_host_management
351  * \brief Changes the priority of an execution action.
352  *
353  * This functions changes the priority only. It calls a surf function.
354  * \param execution The execution action
355  * \param priority The new priority
356  */
357 void simcall_host_execution_set_priority(smx_action_t execution, double priority)
358 {
359   /* checking for infinite values */
360   xbt_assert(isfinite(priority), "priority is not finite!");
361   
362   smx_simcall_t simcall = SIMIX_simcall_mine();
363
364   simcall->call = SIMCALL_HOST_EXECUTION_SET_PRIORITY;
365   simcall->host_execution_set_priority.execution = execution;
366   simcall->host_execution_set_priority.priority = priority;
367   SIMIX_simcall_push(simcall->issuer);
368 }
369
370 /**
371  * \ingroup simix_host_management
372  * \brief Waits for the completion of an execution action and destroy it.
373  *
374  * \param execution The execution action
375  */
376 e_smx_state_t simcall_host_execution_wait(smx_action_t execution)
377 {
378   smx_simcall_t simcall = SIMIX_simcall_mine();
379
380   simcall->call = SIMCALL_HOST_EXECUTION_WAIT;
381   simcall->host_execution_wait.execution = execution;
382   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
383     simcall->host_execution_wait.result = -1;
384   SIMIX_simcall_push(simcall->issuer);
385   return simcall->host_execution_wait.result;
386 }
387
388 /**
389  * \ingroup simix_process_management
390  * \brief Creates and runs a new SIMIX process.
391  *
392  * The structure and the corresponding thread are created and put in the list of ready processes.
393  *
394  * \param process the process created will be stored in this pointer
395  * \param name a name for the process. It is for user-level information and can be NULL.
396  * \param code the main function of the process
397  * \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.
398  * It can be retrieved with the function \ref simcall_process_get_data.
399  * \param hostname name of the host where the new agent is executed.
400  * \param kill_time time when the process is killed
401  * \param argc first argument passed to \a code
402  * \param argv second argument passed to \a code
403  * \param properties the properties of the process
404  * \param auto_restart either it is autorestarting or not.
405  */
406 void simcall_process_create(smx_process_t *process, const char *name,
407                               xbt_main_func_t code,
408                               void *data,
409                               const char *hostname,
410                               double kill_time,
411                               int argc, char **argv,
412                               xbt_dict_t properties,
413                               int auto_restart)
414 {
415   smx_simcall_t simcall = SIMIX_simcall_mine();
416
417   simcall->call = SIMCALL_PROCESS_CREATE;
418   simcall->process_create.process = process;
419   simcall->process_create.name = name;
420   simcall->process_create.code = code;
421   simcall->process_create.data = data;
422   simcall->process_create.hostname = hostname;
423   simcall->process_create.kill_time = kill_time;
424   simcall->process_create.argc = argc;
425   simcall->process_create.argv = argv;
426   simcall->process_create.properties = properties;
427   simcall->process_create.auto_restart = auto_restart;
428   SIMIX_simcall_push(simcall->issuer);
429 }
430
431 /**
432  * \ingroup simix_process_management
433  * \brief Kills a SIMIX process.
434  *
435  * This function simply kills a  process.
436  *
437  * \param process poor victim
438  */
439 void simcall_process_kill(smx_process_t process)
440 {
441   smx_simcall_t simcall = SIMIX_simcall_mine();
442
443   simcall->call = SIMCALL_PROCESS_KILL;
444   simcall->process_kill.process = process;
445   SIMIX_simcall_push(simcall->issuer);
446 }
447
448 /**
449  * \ingroup simix_process_management
450  * \brief Kills all SIMIX processes.
451  */
452 void simcall_process_killall(void)
453 {
454   smx_simcall_t simcall = SIMIX_simcall_mine();
455
456   simcall->call = SIMCALL_PROCESS_KILLALL;
457   SIMIX_simcall_push(simcall->issuer);
458 }
459
460 /**
461  * \ingroup simix_process_management
462  * \brief Cleans up a SIMIX process.
463  * \param process poor victim (must have already been killed)
464  */
465 void simcall_process_cleanup(smx_process_t process)
466 {
467   smx_simcall_t simcall = SIMIX_simcall_mine();
468
469   simcall->call = SIMCALL_PROCESS_CLEANUP;
470   simcall->process_cleanup.process = process;
471   SIMIX_simcall_push(simcall->issuer);
472 }
473
474 /**
475  * \ingroup simix_process_management
476  * \brief Migrates an agent to another location.
477  *
478  * This function changes the value of the host on which \a process is running.
479  *
480  * \param process the process to migrate
481  * \param dest name of the new host
482  */
483 void simcall_process_change_host(smx_process_t process, smx_host_t dest)
484 {
485   smx_simcall_t simcall = SIMIX_simcall_mine();
486
487   simcall->call = SIMCALL_PROCESS_CHANGE_HOST;
488   simcall->process_change_host.process = process;
489   simcall->process_change_host.dest = dest;
490   SIMIX_simcall_push(simcall->issuer);
491 }
492
493 /**
494  * \ingroup simix_process_management
495  * \brief Suspends a process.
496  *
497  * This function suspends the process by suspending the action
498  * it was waiting for completion.
499  *
500  * \param process a SIMIX process
501  */
502 void simcall_process_suspend(smx_process_t process)
503 {
504   xbt_assert(process, "Invalid parameters");
505
506   smx_simcall_t simcall = SIMIX_simcall_mine();
507
508   simcall->call = SIMCALL_PROCESS_SUSPEND;
509   simcall->process_suspend.process = process;
510   SIMIX_simcall_push(simcall->issuer);
511 }
512
513 /**
514  * \ingroup simix_process_management
515  * \brief Resumes a suspended process.
516  *
517  * This function resumes a suspended process by resuming the action
518  * it was waiting for completion.
519  *
520  * \param process a SIMIX process
521  */
522 void simcall_process_resume(smx_process_t process)
523 {
524   smx_simcall_t simcall = SIMIX_simcall_mine();
525
526   simcall->call = SIMCALL_PROCESS_RESUME;
527   simcall->process_resume.process = process;
528   SIMIX_simcall_push(simcall->issuer);
529 }
530
531 /**
532  * \ingroup simix_process_management
533  * \brief Returns the amount of SIMIX processes in the system
534  *
535  * Maestro internal process is not counted, only user code processes are
536  */
537 int simcall_process_count(void)
538 {
539   smx_simcall_t simcall = SIMIX_simcall_mine();
540
541   simcall->call = SIMCALL_PROCESS_COUNT;
542   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
543     simcall->process_count.result = -1;
544   SIMIX_simcall_push(simcall->issuer);
545   return simcall->process_count.result;
546 }
547
548 /**
549  * \ingroup simix_process_management
550  * \brief Return the user data of a #smx_process_t.
551  * \param process a SIMIX process
552  * \return the user data of this process
553  */
554 void* simcall_process_get_data(smx_process_t process)
555 {
556   if (process == SIMIX_process_self()) {
557     /* avoid a simcall if this function is called by the process itself */
558     return SIMIX_process_get_data(process);
559   }
560
561   smx_simcall_t simcall = SIMIX_simcall_mine();
562
563   simcall->call = SIMCALL_PROCESS_GET_DATA;
564   simcall->process_get_data.process = process;
565   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
566     simcall->process_get_data.result = NULL;
567   SIMIX_simcall_push(simcall->issuer);
568   return simcall->process_get_data.result;
569 }
570
571 /**
572  * \ingroup simix_process_management
573  * \brief Set the user data of a #smx_process_t.
574  *
575  * This functions sets the user data associated to \a process.
576  * \param process SIMIX process
577  * \param data User data
578  */
579 void simcall_process_set_data(smx_process_t process, void *data)
580 {
581   if (process == SIMIX_process_self()) {
582     /* avoid a simcall if this function is called by the process itself */
583     SIMIX_process_self_set_data(process, data);
584   }
585   else {
586
587     smx_simcall_t simcall = SIMIX_simcall_mine();
588
589     simcall->call = SIMCALL_PROCESS_SET_DATA;
590     simcall->process_set_data.process = process;
591     simcall->process_set_data.data = data;
592     SIMIX_simcall_push(simcall->issuer);
593   }
594 }
595
596 /**
597  * \ingroup simix_process_management
598  * \brief Set the kill time of a process.
599  * \param process a process
600  * \param kill_time a double
601  */
602 void simcall_process_set_kill_time(smx_process_t process, double kill_time)
603 {
604
605   if (kill_time > SIMIX_get_clock()) {
606     if (simix_global->kill_process_function) {
607       XBT_DEBUG("Set kill time %f for process %s(%s)",kill_time, process->name,
608           process->smx_host->name);
609       SIMIX_timer_set(kill_time, simix_global->kill_process_function, process);
610     }
611   }
612 }
613
614 /**
615  * \ingroup simix_process_management
616  * \brief Return the location on which an agent is running.
617  *
618  * This functions returns the smx_host_t corresponding to the location on which
619  * \a process is running.
620  * \param process SIMIX process
621  * \return SIMIX host
622  */
623 smx_host_t simcall_process_get_host(smx_process_t process)
624 {
625   smx_simcall_t simcall = SIMIX_simcall_mine();
626
627   simcall->call = SIMCALL_PROCESS_GET_HOST;
628   simcall->process_get_host.process = process;
629   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
630     simcall->process_get_host.result = NULL;
631   SIMIX_simcall_push(simcall->issuer);
632   return simcall->process_get_host.result;
633 }
634
635 /**
636  * \ingroup simix_process_management
637  * \brief Return the name of an agent.
638  *
639  * This functions checks whether \a process is a valid pointer or not and return its name.
640  * \param process SIMIX process
641  * \return The process name
642  */
643 const char* simcall_process_get_name(smx_process_t process)
644 {
645   if (process == SIMIX_process_self()) {
646     /* avoid a simcall if this function is called by the process itself */
647     return process->name;
648   }
649
650   smx_simcall_t simcall = SIMIX_simcall_mine();
651
652   simcall->call = SIMCALL_PROCESS_GET_NAME;
653   simcall->process_get_name.process = process;
654   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
655     simcall->process_get_name.result = NULL;
656   SIMIX_simcall_push(simcall->issuer);
657   return simcall->process_get_name.result;
658 }
659
660 /**
661  * \ingroup simix_process_management
662  * \brief Returns true if the process is suspended .
663  *
664  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
665  * \param process SIMIX process
666  * \return 1, if the process is suspended, else 0.
667  */
668 int simcall_process_is_suspended(smx_process_t process)
669 {
670   smx_simcall_t simcall = SIMIX_simcall_mine();
671
672   simcall->call = SIMCALL_PROCESS_IS_SUSPENDED;
673   simcall->process_is_suspended.process = process;
674   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
675     simcall->process_is_suspended.result = -1;
676   SIMIX_simcall_push(simcall->issuer);
677   return simcall->process_is_suspended.result;
678 }
679
680 /**
681  * \ingroup simix_process_management
682  * \brief Return the properties
683  *
684  * This functions returns the properties associated with this process
685  */
686 xbt_dict_t simcall_process_get_properties(smx_process_t process)
687 {
688   smx_simcall_t simcall = SIMIX_simcall_mine();
689
690   simcall->call = SIMCALL_PROCESS_GET_PROPERTIES;
691   simcall->process_get_properties.process = process;
692   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
693     simcall->process_get_properties.result = NULL;
694   SIMIX_simcall_push(simcall->issuer);
695   return simcall->process_get_properties.result;
696 }
697 /**
698  * \ingroup simix_process_management
699  * \brief Add an on_exit function
700  * Add an on_exit function which will be executed when the process exits/is killed.
701  */
702 XBT_PUBLIC(void) simcall_process_on_exit(smx_process_t process, int_f_pvoid_t fun, void *data)
703 {
704   smx_simcall_t simcall = SIMIX_simcall_mine();
705
706   simcall->call = SIMCALL_PROCESS_ON_EXIT;
707   simcall->process_on_exit.process = process;
708   simcall->process_on_exit.fun = fun;
709   simcall->process_on_exit.data = data;
710
711   SIMIX_simcall_push(simcall->issuer);
712 }
713 /**
714  * \ingroup simix_process_management
715  * \brief Sets the process to be auto-restarted or not by SIMIX when its host comes back up.
716  * Will restart the process when the host comes back up if auto_restart is set to 1.
717  */
718
719 XBT_PUBLIC(void) simcall_process_auto_restart_set(smx_process_t process, int auto_restart)
720 {
721   smx_simcall_t simcall = SIMIX_simcall_mine();
722
723   simcall->call = SIMCALL_PROCESS_AUTO_RESTART_SET;
724   simcall->process_auto_restart.process = process;
725   simcall->process_auto_restart.auto_restart = auto_restart;
726
727   SIMIX_simcall_push(simcall->issuer);
728 }
729
730 /**
731  * \ingroup simix_process_management
732  * \brief Restarts the process, killing it and starting it again from scratch.
733  */
734 XBT_PUBLIC(smx_process_t) simcall_process_restart(smx_process_t process)
735 {
736   smx_simcall_t simcall = SIMIX_simcall_mine();
737
738   simcall->call = SIMCALL_PROCESS_RESTART;
739   simcall->process_restart.process = process;
740   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
741     simcall->process_restart.result = NULL;
742
743   SIMIX_simcall_push(simcall->issuer);
744
745   return simcall->process_restart.result;
746 }
747 /**
748  * \ingroup simix_process_management
749  * \brief Creates a new sleep SIMIX action.
750  *
751  * This function creates a SURF action and allocates the data necessary
752  * to create the SIMIX action. It can raise a host_error exception if the
753  * host crashed. The default SIMIX name of the action is "sleep".
754  *
755  *   \param duration Time duration of the sleep.
756  *   \return A result telling whether the sleep was successful
757  */
758 e_smx_state_t simcall_process_sleep(double duration)
759 {
760   /* checking for infinite values */
761   xbt_assert(isfinite(duration), "duration is not finite!");
762   
763   smx_simcall_t simcall = SIMIX_simcall_mine();
764
765   simcall->call = SIMCALL_PROCESS_SLEEP;
766   simcall->process_sleep.duration = duration;
767   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
768     simcall->process_sleep.result = -1;
769   SIMIX_simcall_push(simcall->issuer);
770   return simcall->process_sleep.result;
771 }
772
773 /**
774  *  \ingroup simix_rdv_management
775  *  \brief Creates a new rendez-vous point
776  *  \param name The name of the rendez-vous point
777  *  \return The created rendez-vous point
778  */
779 smx_rdv_t simcall_rdv_create(const char *name)
780 {
781   smx_simcall_t simcall = SIMIX_simcall_mine();
782
783   simcall->call = SIMCALL_RDV_CREATE;
784   simcall->rdv_create.name = name;
785   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
786     simcall->rdv_create.result = NULL;
787
788   SIMIX_simcall_push(simcall->issuer);
789   return simcall->rdv_create.result;
790 }
791
792
793 /**
794  *  \ingroup simix_rdv_management
795  *  \brief Destroy a rendez-vous point
796  *  \param rdv The rendez-vous point to destroy
797  */
798 void simcall_rdv_destroy(smx_rdv_t rdv)
799 {
800   smx_simcall_t simcall = SIMIX_simcall_mine();
801
802   simcall->call = SIMCALL_RDV_DESTROY;
803   simcall->rdv_destroy.rdv = rdv;
804
805   SIMIX_simcall_push(simcall->issuer);
806 }
807 /**
808  *  \ingroup simix_rdv_management
809  *  \brief Returns a rendez-vous point knowing its name
810  */
811 smx_rdv_t simcall_rdv_get_by_name(const char *name)
812 {
813   xbt_assert(name != NULL, "Invalid parameter for simcall_rdv_get_by_name (name is NULL)");
814
815   /* FIXME: this is a horrible lost of performance, so we hack it out by
816    * skipping the simcall (for now). It works in parallel, it won't work on
817    * distributed but probably we will change MSG for that. */
818
819   /*
820   smx_simcall_t simcall = simcall_mine();
821   simcall->call = SIMCALL_RDV_GEY_BY_NAME;
822   simcall->rdv_get_by_name.name = name;
823   SIMIX_simcall_push(simcall->issuer);
824   return simcall->rdv_get_by_name.result;*/
825
826   return SIMIX_rdv_get_by_name(name);
827 }
828
829 /**
830  *  \ingroup simix_rdv_management
831  *  \brief Counts the number of communication actions of a given host pending
832  *         on a rendez-vous point.
833  *  \param rdv The rendez-vous point
834  *  \param host The host to be counted
835  *  \return The number of comm actions pending in the rdv
836  */
837 int simcall_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
838 {
839   smx_simcall_t simcall = SIMIX_simcall_mine();
840
841   simcall->call = SIMCALL_RDV_COMM_COUNT_BY_HOST;
842   simcall->rdv_comm_count_by_host.rdv = rdv;
843   simcall->rdv_comm_count_by_host.host = host;
844   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
845     simcall->rdv_comm_count_by_host.result = -1;
846
847   SIMIX_simcall_push(simcall->issuer);
848   return simcall->rdv_comm_count_by_host.result;
849 }
850
851 /**
852  *  \ingroup simix_rdv_management
853  *  \brief returns the communication at the head of the rendez-vous
854  *  \param rdv The rendez-vous point
855  *  \return The communication or NULL if empty
856  */
857 smx_action_t simcall_rdv_get_head(smx_rdv_t rdv)
858 {
859   smx_simcall_t simcall = SIMIX_simcall_mine();
860
861   simcall->call = SIMCALL_RDV_GET_HEAD;
862   simcall->rdv_get_head.rdv = rdv;
863   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
864     simcall->rdv_get_head.result = NULL;
865
866   SIMIX_simcall_push(simcall->issuer);
867   return simcall->rdv_get_head.result;
868 }
869
870 void simcall_rdv_set_receiver(smx_rdv_t rdv , smx_process_t process)
871 {
872   smx_simcall_t simcall = SIMIX_simcall_mine();
873
874   simcall->call = SIMCALL_RDV_SET_RECV;
875   simcall->rdv_set_rcv_proc.rdv = rdv;
876   simcall->rdv_set_rcv_proc.receiver = process;
877
878   SIMIX_simcall_push(simcall->issuer);
879 }
880
881 smx_process_t simcall_rdv_get_receiver(smx_rdv_t rdv)
882 {
883   smx_simcall_t simcall = SIMIX_simcall_mine();
884
885   simcall->call = SIMCALL_RDV_GET_RECV;
886   simcall->rdv_get_rcv_proc.rdv = rdv;
887   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
888     simcall->rdv_get_rcv_proc.result = NULL;
889
890   SIMIX_simcall_push(simcall->issuer);
891   return simcall->rdv_get_rcv_proc.result;
892 }
893
894 /**
895  * \ingroup simix_comm_management
896  */
897 void simcall_comm_send(smx_rdv_t rdv, double task_size, double rate,
898                          void *src_buff, size_t src_buff_size,
899                          int (*match_fun)(void *, void *, smx_action_t), void *data,
900                          double timeout)
901 {
902   /* checking for infinite values */
903   xbt_assert(isfinite(task_size), "task_size is not finite!");
904   xbt_assert(isfinite(rate), "rate is not finite!");
905   xbt_assert(isfinite(timeout), "timeout is not finite!");
906   
907   xbt_assert(rdv, "No rendez-vous point defined for send");
908
909   if (MC_is_active()) {
910     /* the model-checker wants two separate simcalls */
911     smx_action_t comm = simcall_comm_isend(rdv, task_size, rate,
912         src_buff, src_buff_size, match_fun, NULL, data, 0);
913     simcall_comm_wait(comm, timeout);
914   }
915   else {
916     smx_simcall_t simcall = SIMIX_simcall_mine();
917
918     simcall->call = SIMCALL_COMM_SEND;
919     simcall->comm_send.rdv = rdv;
920     simcall->comm_send.task_size = task_size;
921     simcall->comm_send.rate = rate;
922     simcall->comm_send.src_buff = src_buff;
923     simcall->comm_send.src_buff_size = src_buff_size;
924     simcall->comm_send.match_fun = match_fun;
925     simcall->comm_send.data = data;
926     simcall->comm_send.timeout = timeout;
927
928     SIMIX_simcall_push(simcall->issuer);
929   }
930 }
931 /**
932  * \ingroup simix_comm_management
933  */
934 smx_action_t simcall_comm_isend(smx_rdv_t rdv, double task_size, double rate,
935                               void *src_buff, size_t src_buff_size,
936                               int (*match_fun)(void *, void *, smx_action_t),
937                               void (*clean_fun)(void *),
938                               void *data,
939                               int detached)
940 {
941   /* checking for infinite values */
942   xbt_assert(isfinite(task_size), "task_size is not finite!");
943   xbt_assert(isfinite(rate), "rate is not finite!");
944   
945   xbt_assert(rdv, "No rendez-vous point defined for isend");
946
947   smx_simcall_t simcall = SIMIX_simcall_mine();
948
949   simcall->call = SIMCALL_COMM_ISEND;
950   simcall->comm_isend.rdv = rdv;
951   simcall->comm_isend.task_size = task_size;
952   simcall->comm_isend.rate = rate;
953   simcall->comm_isend.src_buff = src_buff;
954   simcall->comm_isend.src_buff_size = src_buff_size;
955   simcall->comm_isend.match_fun = match_fun;
956   simcall->comm_isend.clean_fun = clean_fun;
957   simcall->comm_isend.data = data;
958   simcall->comm_isend.detached = detached;
959   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
960     simcall->comm_isend.result = NULL;
961
962   SIMIX_simcall_push(simcall->issuer);
963   return simcall->comm_isend.result;
964 }
965 /**
966  * \ingroup simix_comm_management
967  */
968 void simcall_comm_recv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
969                          int (*match_fun)(void *, void *, smx_action_t), void *data, double timeout)
970 {
971   xbt_assert(isfinite(timeout), "timeout is not finite!");
972   xbt_assert(rdv, "No rendez-vous point defined for recv");
973
974   if (MC_is_active()) {
975     /* the model-checker wants two separate simcalls */
976     smx_action_t comm = simcall_comm_irecv(rdv, dst_buff, dst_buff_size,
977         match_fun, data);
978     simcall_comm_wait(comm, timeout);
979   }
980   else {
981     smx_simcall_t simcall = SIMIX_simcall_mine();
982
983     simcall->call = SIMCALL_COMM_RECV;
984     simcall->comm_recv.rdv = rdv;
985     simcall->comm_recv.dst_buff = dst_buff;
986     simcall->comm_recv.dst_buff_size = dst_buff_size;
987     simcall->comm_recv.match_fun = match_fun;
988     simcall->comm_recv.data = data;
989     simcall->comm_recv.timeout = timeout;
990
991     SIMIX_simcall_push(simcall->issuer);
992   }
993 }
994 /**
995  * \ingroup simix_comm_management
996  */
997 smx_action_t simcall_comm_irecv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
998                                   int (*match_fun)(void *, void *, smx_action_t), void *data)
999 {
1000   xbt_assert(rdv, "No rendez-vous point defined for irecv");
1001
1002   smx_simcall_t simcall = SIMIX_simcall_mine();
1003
1004   simcall->call = SIMCALL_COMM_IRECV;
1005   simcall->comm_irecv.rdv = rdv;
1006   simcall->comm_irecv.dst_buff = dst_buff;
1007   simcall->comm_irecv.dst_buff_size = dst_buff_size;
1008   simcall->comm_irecv.match_fun = match_fun;
1009   simcall->comm_irecv.data = data;
1010   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1011     simcall->comm_irecv.result = NULL;
1012
1013   SIMIX_simcall_push(simcall->issuer);
1014   return simcall->comm_irecv.result;
1015 }
1016
1017
1018 /**
1019  * \ingroup simix_comm_management
1020  */
1021 smx_action_t simcall_comm_iprobe(smx_rdv_t rdv, int src, int tag,
1022                                 int (*match_fun)(void *, void *, smx_action_t), void *data)
1023 {
1024   xbt_assert(rdv, "No rendez-vous point defined for iprobe");
1025
1026   smx_simcall_t simcall = SIMIX_simcall_mine();
1027
1028   simcall->call = SIMCALL_COMM_IPROBE;
1029   simcall->comm_iprobe.rdv = rdv;
1030   simcall->comm_iprobe.src = src;
1031   simcall->comm_iprobe.match_fun = match_fun;
1032   simcall->comm_iprobe.data = data;
1033   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1034     simcall->comm_iprobe.result = NULL;
1035   SIMIX_simcall_push(simcall->issuer);
1036   return simcall->comm_iprobe.result;
1037 }
1038
1039
1040 void simcall_comm_destroy(smx_action_t comm)
1041 {
1042   xbt_assert(comm, "Invalid parameter");
1043
1044   /* FIXME remove this simcall type: comms are auto-destroyed now */
1045
1046   /*
1047   smx_simcall_t simcall = simcall_mine();
1048
1049   simcall->call = SIMCALL_COMM_DESTROY;
1050   simcall->comm_destroy.comm = comm;
1051
1052   SIMIX_simcall_push(simcall->issuer);
1053   */
1054 }
1055 /**
1056  * \ingroup simix_comm_management
1057  */
1058 void simcall_comm_cancel(smx_action_t comm)
1059 {
1060   smx_simcall_t simcall = SIMIX_simcall_mine();
1061
1062   simcall->call = SIMCALL_COMM_CANCEL;
1063   simcall->comm_cancel.comm = comm;
1064
1065   SIMIX_simcall_push(simcall->issuer);
1066 }
1067 /**
1068  * \ingroup simix_comm_management
1069  */
1070 unsigned int simcall_comm_waitany(xbt_dynar_t comms)
1071 {
1072   smx_simcall_t simcall = SIMIX_simcall_mine();
1073
1074   simcall->call = SIMCALL_COMM_WAITANY;
1075   simcall->comm_waitany.comms = comms;
1076   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1077     simcall->comm_waitany.result = -1;
1078
1079   SIMIX_simcall_push(simcall->issuer);
1080   return simcall->comm_waitany.result;
1081 }
1082 /**
1083  * \ingroup simix_comm_management
1084  */
1085 int simcall_comm_testany(xbt_dynar_t comms)
1086 {
1087   smx_simcall_t simcall = SIMIX_simcall_mine();
1088   if (xbt_dynar_is_empty(comms))
1089     return -1;
1090
1091   simcall->call = SIMCALL_COMM_TESTANY;
1092   simcall->comm_testany.comms = comms;
1093     if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1094       simcall->comm_testany.result = -1;
1095
1096   SIMIX_simcall_push(simcall->issuer);
1097   return simcall->comm_testany.result;
1098 }
1099 /**
1100  * \ingroup simix_comm_management
1101  */
1102 void simcall_comm_wait(smx_action_t comm, double timeout)
1103 {
1104   xbt_assert(isfinite(timeout), "timeout is not finite!");
1105   
1106   smx_simcall_t simcall = SIMIX_simcall_mine();
1107
1108   simcall->call = SIMCALL_COMM_WAIT;
1109   simcall->comm_wait.comm = comm;
1110   simcall->comm_wait.timeout = timeout;
1111
1112   SIMIX_simcall_push(simcall->issuer);
1113 }
1114
1115 #ifdef HAVE_TRACING
1116 /**
1117  * \brief Set the category of an action.
1118  *
1119  * This functions changes the category only. It calls a surf function.
1120  * \param execution The execution action
1121  * \param category The tracing category
1122  */
1123 void simcall_set_category(smx_action_t action, const char *category)
1124 {
1125   if (category == NULL) {
1126     return;
1127   }
1128
1129   smx_simcall_t simcall = SIMIX_simcall_mine();
1130
1131   simcall->call = SIMCALL_SET_CATEGORY;
1132   simcall->set_category.action = action;
1133   simcall->set_category.category = category;
1134
1135   SIMIX_simcall_push(simcall->issuer);
1136 }
1137 #endif
1138 /**
1139  * \ingroup simix_comm_management
1140  *
1141  */
1142 int simcall_comm_test(smx_action_t comm)
1143 {
1144   smx_simcall_t simcall = SIMIX_simcall_mine();
1145
1146   simcall->call = SIMCALL_COMM_TEST;
1147   simcall->comm_test.comm = comm;
1148   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1149     simcall->comm_test.result = -1;
1150
1151   SIMIX_simcall_push(simcall->issuer);
1152   return simcall->comm_test.result;
1153 }
1154 /**
1155  * \ingroup simix_comm_management
1156  *
1157  */
1158 double simcall_comm_get_remains(smx_action_t comm)
1159 {
1160   smx_simcall_t simcall = SIMIX_simcall_mine();
1161
1162   simcall->call = SIMCALL_COMM_GET_REMAINS;
1163   simcall->comm_get_remains.comm = comm;
1164   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1165     simcall->comm_get_remains.result = 0.0;
1166
1167   SIMIX_simcall_push(simcall->issuer);
1168   return simcall->comm_get_remains.result;
1169 }
1170 /**
1171  * \ingroup simix_comm_management
1172  *
1173  */
1174 e_smx_state_t simcall_comm_get_state(smx_action_t comm)
1175 {
1176   smx_simcall_t simcall = SIMIX_simcall_mine();
1177
1178   simcall->call = SIMCALL_COMM_GET_STATE;
1179   simcall->comm_get_state.comm = comm;
1180   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1181     simcall->comm_get_state.result = -1;
1182
1183   SIMIX_simcall_push(simcall->issuer);
1184   return simcall->comm_get_state.result;
1185 }
1186 /**
1187  * \ingroup simix_comm_management
1188  *
1189  */
1190 void *simcall_comm_get_src_data(smx_action_t comm)
1191 {
1192   smx_simcall_t simcall = SIMIX_simcall_mine();
1193
1194   simcall->call = SIMCALL_COMM_GET_SRC_DATA;
1195   simcall->comm_get_src_data.comm = comm;
1196   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1197     simcall->comm_get_src_data.result = NULL;
1198
1199   SIMIX_simcall_push(simcall->issuer);
1200   return simcall->comm_get_src_data.result;
1201 }
1202 /**
1203  * \ingroup simix_comm_management
1204  *
1205  */
1206 void *simcall_comm_get_dst_data(smx_action_t comm)
1207 {
1208   smx_simcall_t simcall = SIMIX_simcall_mine();
1209
1210   simcall->call = SIMCALL_COMM_GET_DST_DATA;
1211   simcall->comm_get_dst_data.comm = comm;
1212   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1213     simcall->comm_get_dst_data.result = NULL;
1214
1215   SIMIX_simcall_push(simcall->issuer);
1216   return simcall->comm_get_dst_data.result;
1217 }
1218 /**
1219  * \ingroup simix_comm_management
1220  *
1221  */
1222 smx_process_t simcall_comm_get_src_proc(smx_action_t comm)
1223 {
1224   smx_simcall_t simcall = SIMIX_simcall_mine();
1225
1226   simcall->call = SIMCALL_COMM_GET_SRC_PROC;
1227   simcall->comm_get_src_proc.comm = comm;
1228   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1229     simcall->comm_get_src_proc.result = NULL;
1230
1231   SIMIX_simcall_push(simcall->issuer);
1232   return simcall->comm_get_src_proc.result;
1233 }
1234 /**
1235  * \ingroup simix_comm_management
1236  *
1237  */
1238 smx_process_t simcall_comm_get_dst_proc(smx_action_t comm)
1239 {
1240   smx_simcall_t simcall = SIMIX_simcall_mine();
1241
1242   simcall->call = SIMCALL_COMM_GET_DST_PROC;
1243   simcall->comm_get_dst_proc.comm = comm;
1244   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1245     simcall->comm_get_dst_proc.result = NULL;
1246
1247   SIMIX_simcall_push(simcall->issuer);
1248   return simcall->comm_get_dst_proc.result;
1249 }
1250
1251 #ifdef HAVE_LATENCY_BOUND_TRACKING
1252 int simcall_comm_is_latency_bounded(smx_action_t comm)
1253 {
1254   smx_simcall_t simcall = SIMIX_simcall_mine();
1255
1256   simcall->call = SIMCALL_COMM_IS_LATENCY_BOUNDED;
1257   simcall->comm_is_latency_bounded.comm = comm;
1258   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1259     simcall->comm_is_latency_bounded.result = -1;
1260
1261   SIMIX_simcall_push(simcall->issuer);
1262   return simcall->comm_is_latency_bounded.result;
1263 }
1264 #endif
1265 /**
1266  * \ingroup simix_synchro_management
1267  *
1268  */
1269 smx_mutex_t simcall_mutex_init(void)
1270 {
1271   if(!simix_global) {
1272     fprintf(stderr,"You must run MSG_init before using MSG\n"); // We can't use xbt_die since we may get there before the initialization
1273     xbt_abort();
1274   }
1275   smx_simcall_t simcall = SIMIX_simcall_mine();
1276
1277   simcall->call = SIMCALL_MUTEX_INIT;
1278   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1279     simcall->mutex_init.result = NULL;
1280
1281   SIMIX_simcall_push(simcall->issuer);
1282   return simcall->mutex_init.result;
1283 }
1284 /**
1285  * \ingroup simix_synchro_management
1286  *
1287  */
1288 void simcall_mutex_destroy(smx_mutex_t mutex)
1289 {
1290   smx_simcall_t simcall = SIMIX_simcall_mine();
1291
1292   simcall->call = SIMCALL_MUTEX_DESTROY;
1293   simcall->mutex_destroy.mutex = mutex;
1294
1295   SIMIX_simcall_push(simcall->issuer);
1296 }
1297 /**
1298  * \ingroup simix_synchro_management
1299  *
1300  */
1301 void simcall_mutex_lock(smx_mutex_t mutex)
1302 {
1303   smx_simcall_t simcall = SIMIX_simcall_mine();
1304
1305   simcall->call = SIMCALL_MUTEX_LOCK;
1306   simcall->mutex_lock.mutex = mutex;
1307
1308   SIMIX_simcall_push(simcall->issuer);
1309 }
1310 /**
1311  * \ingroup simix_synchro_management
1312  *
1313  */
1314 int simcall_mutex_trylock(smx_mutex_t mutex)
1315 {
1316   smx_simcall_t simcall = SIMIX_simcall_mine();
1317
1318   simcall->call = SIMCALL_MUTEX_TRYLOCK;
1319   simcall->mutex_trylock.mutex = mutex;
1320   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1321     simcall->mutex_trylock.result = -1;
1322
1323   SIMIX_simcall_push(simcall->issuer);
1324   return simcall->mutex_trylock.result;
1325 }
1326 /**
1327  * \ingroup simix_synchro_management
1328  *
1329  */
1330 void simcall_mutex_unlock(smx_mutex_t mutex)
1331 {
1332   smx_simcall_t simcall = SIMIX_simcall_mine();
1333
1334   simcall->call = SIMCALL_MUTEX_UNLOCK;
1335   simcall->mutex_unlock.mutex = mutex;
1336
1337   SIMIX_simcall_push(simcall->issuer);
1338 }
1339 /**
1340  * \ingroup simix_synchro_management
1341  *
1342  */
1343 smx_cond_t simcall_cond_init(void)
1344 {
1345   smx_simcall_t simcall = SIMIX_simcall_mine();
1346
1347   simcall->call = SIMCALL_COND_INIT;
1348   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1349     simcall->cond_init.result = NULL;
1350
1351   SIMIX_simcall_push(simcall->issuer);
1352   return simcall->cond_init.result;
1353 }
1354 /**
1355  * \ingroup simix_synchro_management
1356  *
1357  */
1358 void simcall_cond_destroy(smx_cond_t cond)
1359 {
1360   smx_simcall_t simcall = SIMIX_simcall_mine();
1361
1362   simcall->call = SIMCALL_COND_DESTROY;
1363   simcall->cond_destroy.cond = cond;
1364
1365   SIMIX_simcall_push(simcall->issuer);
1366 }
1367 /**
1368  * \ingroup simix_synchro_management
1369  *
1370  */
1371 void simcall_cond_signal(smx_cond_t cond)
1372 {
1373   smx_simcall_t simcall = SIMIX_simcall_mine();
1374
1375   simcall->call = SIMCALL_COND_SIGNAL;
1376   simcall->cond_signal.cond = cond;
1377
1378   SIMIX_simcall_push(simcall->issuer);
1379 }
1380 /**
1381  * \ingroup simix_synchro_management
1382  *
1383  */
1384 void simcall_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
1385 {
1386   smx_simcall_t simcall = SIMIX_simcall_mine();
1387
1388   simcall->call = SIMCALL_COND_WAIT;
1389   simcall->cond_wait.cond = cond;
1390   simcall->cond_wait.mutex = mutex;
1391
1392   SIMIX_simcall_push(simcall->issuer);
1393 }
1394 /**
1395  * \ingroup simix_synchro_management
1396  *
1397  */
1398 void simcall_cond_wait_timeout(smx_cond_t cond,
1399                                  smx_mutex_t mutex,
1400                                  double timeout)
1401 {
1402   xbt_assert(isfinite(timeout), "timeout is not finite!");
1403   
1404   smx_simcall_t simcall = SIMIX_simcall_mine();
1405
1406   simcall->call = SIMCALL_COND_WAIT_TIMEOUT;
1407   simcall->cond_wait_timeout.cond = cond;
1408   simcall->cond_wait_timeout.mutex = mutex;
1409   simcall->cond_wait_timeout.timeout = timeout;
1410
1411   SIMIX_simcall_push(simcall->issuer);
1412 }
1413 /**
1414  * \ingroup simix_synchro_management
1415  *
1416  */
1417 void simcall_cond_broadcast(smx_cond_t cond)
1418 {
1419   smx_simcall_t simcall = SIMIX_simcall_mine();
1420
1421   simcall->call = SIMCALL_COND_BROADCAST;
1422   simcall->cond_broadcast.cond = cond;
1423
1424   SIMIX_simcall_push(simcall->issuer);
1425 }
1426 /**
1427  * \ingroup simix_synchro_management
1428  *
1429  */
1430 smx_sem_t simcall_sem_init(int capacity)
1431 {
1432   smx_simcall_t simcall = SIMIX_simcall_mine();
1433
1434   simcall->call = SIMCALL_SEM_INIT;
1435   simcall->sem_init.capacity = capacity;
1436   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1437     simcall->sem_init.result = NULL;
1438
1439   SIMIX_simcall_push(simcall->issuer);
1440   return simcall->sem_init.result;
1441 }
1442 /**
1443  * \ingroup simix_synchro_management
1444  *
1445  */
1446 void simcall_sem_destroy(smx_sem_t sem)
1447 {
1448   smx_simcall_t simcall = SIMIX_simcall_mine();
1449
1450   simcall->call = SIMCALL_SEM_DESTROY;
1451   simcall->sem_destroy.sem = sem;
1452
1453   SIMIX_simcall_push(simcall->issuer);
1454 }
1455 /**
1456  * \ingroup simix_synchro_management
1457  *
1458  */
1459 void simcall_sem_release(smx_sem_t sem)
1460 {
1461   smx_simcall_t simcall = SIMIX_simcall_mine();
1462
1463   simcall->call = SIMCALL_SEM_RELEASE;
1464   simcall->sem_release.sem = sem;
1465
1466   SIMIX_simcall_push(simcall->issuer);
1467 }
1468 /**
1469  * \ingroup simix_synchro_management
1470  *
1471  */
1472 int simcall_sem_would_block(smx_sem_t sem)
1473 {
1474   smx_simcall_t simcall = SIMIX_simcall_mine();
1475
1476   simcall->call = SIMCALL_SEM_WOULD_BLOCK;
1477   simcall->sem_would_block.sem = sem;
1478   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1479     simcall->sem_would_block.result = -1;
1480
1481   SIMIX_simcall_push(simcall->issuer);
1482   return simcall->sem_would_block.result;
1483 }
1484 /**
1485  * \ingroup simix_synchro_management
1486  *
1487  */
1488 void simcall_sem_acquire(smx_sem_t sem)
1489 {
1490   smx_simcall_t simcall = SIMIX_simcall_mine();
1491
1492   simcall->call = SIMCALL_SEM_ACQUIRE;
1493   simcall->sem_acquire.sem = sem;
1494
1495   SIMIX_simcall_push(simcall->issuer);
1496 }
1497 /**
1498  * \ingroup simix_synchro_management
1499  *
1500  */
1501 void simcall_sem_acquire_timeout(smx_sem_t sem, double timeout)
1502 {
1503   xbt_assert(isfinite(timeout), "timeout is not finite!");
1504   
1505   smx_simcall_t simcall = SIMIX_simcall_mine();
1506
1507   simcall->call = SIMCALL_SEM_ACQUIRE_TIMEOUT;
1508   simcall->sem_acquire_timeout.sem = sem;
1509   simcall->sem_acquire_timeout.timeout = timeout;
1510
1511   SIMIX_simcall_push(simcall->issuer);
1512 }
1513 /**
1514  * \ingroup simix_synchro_management
1515  *
1516  */
1517 int simcall_sem_get_capacity(smx_sem_t sem)
1518 {
1519   smx_simcall_t simcall = SIMIX_simcall_mine();
1520
1521   simcall->call = SIMCALL_SEM_GET_CAPACITY;
1522   simcall->sem_get_capacity.sem = sem;
1523   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1524     simcall->sem_get_capacity.result = -1;
1525
1526   SIMIX_simcall_push(simcall->issuer);
1527   return simcall->sem_get_capacity.result;
1528 }
1529 /**
1530  * \ingroup simix_file_management
1531  *
1532  */
1533 double simcall_file_read(void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1534 {
1535   smx_simcall_t simcall = SIMIX_simcall_mine();
1536
1537   simcall->call = SIMCALL_FILE_READ;
1538   simcall->file_read.ptr = ptr;
1539   simcall->file_read.size = size;
1540   simcall->file_read.nmemb = nmemb;
1541   simcall->file_read.stream = stream;
1542   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1543     simcall->file_read.result = 0.0;
1544   SIMIX_simcall_push(simcall->issuer);
1545
1546   return simcall->file_read.result;
1547 }
1548 /**
1549  * \ingroup simix_file_management
1550  *
1551  */
1552 size_t simcall_file_write(const void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1553 {
1554   smx_simcall_t simcall = SIMIX_simcall_mine();
1555
1556   simcall->call = SIMCALL_FILE_WRITE;
1557   simcall->file_write.ptr = ptr;
1558   simcall->file_write.size = size;
1559   simcall->file_write.nmemb = nmemb;
1560   simcall->file_write.stream = stream;
1561   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1562     simcall->file_write.result = 0;
1563   SIMIX_simcall_push(simcall->issuer);
1564
1565   return simcall->file_write.result;
1566 }
1567 /**
1568  * \ingroup simix_file_management
1569  * \brief
1570  */
1571 smx_file_t simcall_file_open(const char* mount, const char* path, const char* mode)
1572 {
1573   smx_simcall_t simcall = SIMIX_simcall_mine();
1574
1575   simcall->call = SIMCALL_FILE_OPEN;
1576   simcall->file_open.mount = mount;
1577   simcall->file_open.path = path;
1578   simcall->file_open.mode = mode;
1579   if(MC_is_active()) /* Initialize result to NULL for snapshot comparison done during simcall */
1580     simcall->file_open.result = NULL;
1581   SIMIX_simcall_push(simcall->issuer);
1582
1583   return simcall->file_open.result;
1584 }
1585 /**
1586  * \ingroup simix_file_management
1587  *
1588  */
1589 int simcall_file_close(smx_file_t fp)
1590 {
1591   smx_simcall_t simcall = SIMIX_simcall_mine();
1592
1593   simcall->call = SIMCALL_FILE_CLOSE;
1594   simcall->file_close.fp = fp;
1595   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1596     simcall->file_close.result = -1;
1597   SIMIX_simcall_push(simcall->issuer);
1598
1599   return simcall->file_close.result;
1600 }
1601 /**
1602  * \ingroup simix_file_management
1603  *
1604  */
1605 int simcall_file_stat(smx_file_t fd, s_file_stat_t *buf)
1606 {
1607   smx_simcall_t simcall = SIMIX_simcall_mine();
1608   simcall->call = SIMCALL_FILE_STAT;
1609   simcall->file_stat.fd = fd;
1610   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1611     simcall->file_stat.result = -1;
1612
1613   SIMIX_simcall_push(simcall->issuer);
1614
1615   *buf = simcall->file_stat.buf;
1616
1617   return simcall->file_stat.result;
1618 }
1619
1620 /**
1621  * \ingroup simix_file_management
1622  *
1623  */
1624 int simcall_file_unlink(smx_file_t fd)
1625 {
1626   smx_simcall_t simcall = SIMIX_simcall_mine();
1627   simcall->call = SIMCALL_FILE_UNLINK;
1628   simcall->file_unlink.fd = fd;
1629   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1630     simcall->file_unlink.result = -1;
1631
1632   SIMIX_simcall_push(simcall->issuer);
1633
1634   return simcall->file_unlink.result;
1635 }
1636
1637 /**
1638  * \ingroup simix_file_management
1639  *
1640  */
1641 xbt_dict_t simcall_file_ls(const char* mount, const char* path)
1642 {
1643   smx_simcall_t simcall = SIMIX_simcall_mine();
1644   simcall->call = SIMCALL_FILE_LS;
1645   simcall->file_ls.mount = mount;
1646   simcall->file_ls.path = path;
1647   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1648     simcall->file_ls.result = NULL;
1649
1650   SIMIX_simcall_push(simcall->issuer);
1651
1652   return simcall->file_ls.result;
1653 }
1654
1655 #ifdef HAVE_MC
1656
1657 void *simcall_mc_snapshot(void)
1658 {
1659   smx_simcall_t simcall = SIMIX_simcall_mine();
1660   simcall->call = SIMCALL_MC_SNAPSHOT;
1661   
1662   SIMIX_simcall_push(simcall->issuer);
1663
1664   return simcall->mc_snapshot.s;
1665 }
1666
1667 int simcall_mc_compare_snapshots(void *s1, void *s2){
1668   
1669   smx_simcall_t simcall = SIMIX_simcall_mine();
1670   simcall->call = SIMCALL_MC_COMPARE_SNAPSHOTS;
1671   simcall->mc_compare_snapshots.snapshot1 = s1;
1672   simcall->mc_compare_snapshots.snapshot2 = s2;
1673   
1674   if(MC_is_active()) /* Initialize result to a default value for snapshot comparison done during simcall */
1675     simcall->mc_compare_snapshots.result = -1;
1676   
1677   SIMIX_simcall_push(simcall->issuer);
1678   
1679   return simcall->mc_compare_snapshots.result;
1680 }
1681
1682 #endif /* HAVE_MC */
1683
1684 /* ****************************************************************************************** */
1685 /* TUTORIAL: New API                                                                          */
1686 /* All functions for simcall                                                                  */
1687 /* ****************************************************************************************** */
1688 int simcall_new_api_fct(const char* param1, double param2){
1689   smx_simcall_t simcall = SIMIX_simcall_mine();
1690   simcall->call = SIMCALL_NEW_API_INIT;
1691   simcall->new_api.param1 = param1;
1692   simcall->new_api.param2 = param2;
1693
1694   SIMIX_simcall_push(simcall->issuer);
1695   return simcall->new_api.result;
1696 }
1697
1698 /* ************************************************************************** */
1699
1700 /** @brief returns a printable string representing a simcall */
1701 const char *SIMIX_simcall_name(e_smx_simcall_t kind) {
1702   return simcall_names[kind];
1703 }