Logo AND Algorithmique Numérique Distribuée

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