Logo AND Algorithmique Numérique Distribuée

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