Logo AND Algorithmique Numérique Distribuée

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