1 /* smx_user.c - public interface to simix */
3 /* Copyright (c) 2010, 2011. Da SimGrid team. All rights reserved. */
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. */
8 # define _SVID_SOURCE /* strdup() */
10 #ifndef _ISOC99_SOURCE
11 # define _ISOC99_SOURCE /* isfinite() */
13 #ifndef _ISO_C99_SOURCE
14 # define _ISO_C99_SOURCE /* isfinite() */
16 #include <math.h> /* isfinite() */
18 #include "smx_private.h"
21 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
23 static const char* simcall_names[] = {
24 #undef SIMCALL_ENUM_ELEMENT
25 #define SIMCALL_ENUM_ELEMENT(x) #x /* generate strings from the enumeration values */
27 #undef SIMCALL_ENUM_ELEMENT
31 * \brief Returns a host given its name.
33 * \param name The name of the host to get
34 * \return The corresponding host
36 smx_host_t simcall_host_get_by_name(const char *name)
38 smx_simcall_t simcall = SIMIX_simcall_mine();
40 simcall->call = SIMCALL_HOST_GET_BY_NAME;
41 simcall->host_get_by_name.name = name;
42 SIMIX_simcall_push(simcall->issuer);
43 return simcall->host_get_by_name.result;
47 * \brief Returns the name of a host.
49 * \param host A SIMIX host
50 * \return The name of this host
52 const char* simcall_host_get_name(smx_host_t host)
54 smx_simcall_t simcall = SIMIX_simcall_mine();
56 simcall->call = SIMCALL_HOST_GET_NAME;
57 simcall->host_get_name.host = host;
58 SIMIX_simcall_push(simcall->issuer);
59 return simcall->host_get_name.result;
63 * \brief Returns a dict of the properties assigned to a host.
66 * \return The properties of this host
68 xbt_dict_t simcall_host_get_properties(smx_host_t host)
70 smx_simcall_t simcall = SIMIX_simcall_mine();
72 simcall->call = SIMCALL_HOST_GET_PROPERTIES;
73 simcall->host_get_properties.host = host;
74 SIMIX_simcall_push(simcall->issuer);
75 return simcall->host_get_properties.result;
79 * \brief Returns the speed of the processor.
81 * The speed returned does not take into account the current load on the machine.
82 * \param host A SIMIX host
83 * \return The speed of this host (in Mflop/s)
85 double simcall_host_get_speed(smx_host_t host)
87 smx_simcall_t simcall = SIMIX_simcall_mine();
89 simcall->call = SIMCALL_HOST_GET_SPEED;
90 simcall->host_get_speed.host = host;
91 SIMIX_simcall_push(simcall->issuer);
92 return simcall->host_get_speed.result;
96 * \brief Returns the available speed of the processor.
98 * \return Speed currently available (in Mflop/s)
100 double simcall_host_get_available_speed(smx_host_t host)
102 smx_simcall_t simcall = SIMIX_simcall_mine();
104 simcall->call = SIMCALL_HOST_GET_AVAILABLE_SPEED;
105 simcall->host_get_available_speed.host = host;
106 SIMIX_simcall_push(simcall->issuer);
107 return simcall->host_get_available_speed.result;
111 * \brief Returns the state of a host.
113 * Two states are possible: 1 if the host is active or 0 if it has crashed.
114 * \param host A SIMIX host
115 * \return 1 if the host is available, 0 otherwise
117 int simcall_host_get_state(smx_host_t host)
119 smx_simcall_t simcall = SIMIX_simcall_mine();
121 simcall->call = SIMCALL_HOST_GET_STATE;
122 simcall->host_get_state.host = host;
123 SIMIX_simcall_push(simcall->issuer);
124 return simcall->host_get_state.result;
128 * \brief Returns the user data associated to a host.
130 * \param host SIMIX host
131 * \return the user data of this host
133 void* simcall_host_get_data(smx_host_t host)
135 smx_simcall_t simcall = SIMIX_simcall_mine();
137 simcall->call = SIMCALL_HOST_GET_DATA;
138 simcall->host_get_data.host = host;
139 SIMIX_simcall_push(simcall->issuer);
140 return simcall->host_get_data.result;
144 * \brief Sets the user data associated to a host.
146 * The host must not have previous user data associated to it.
147 * \param A host SIMIX host
148 * \param data The user data to set
150 void simcall_host_set_data(smx_host_t host, void *data)
152 smx_simcall_t simcall = SIMIX_simcall_mine();
154 simcall->call = SIMCALL_HOST_SET_DATA;
155 simcall->host_set_data.host = host;
156 simcall->host_set_data.data = data;
157 SIMIX_simcall_push(simcall->issuer);
160 /** \brief Creates an action that executes some computation of an host.
162 * This function creates a SURF action and allocates the data necessary
163 * to create the SIMIX action. It can raise a host_error exception if the host crashed.
165 * \param name Name of the execution action to create
166 * \param host SIMIX host where the action will be executed
167 * \param amount Computation amount (in bytes)
168 * \return A new SIMIX execution action
170 smx_action_t simcall_host_execute(const char *name, smx_host_t host,
171 double computation_amount,
174 /* checking for infinite values */
175 xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
176 xbt_assert(isfinite(priority), "priority is not finite!");
178 smx_simcall_t simcall = SIMIX_simcall_mine();
180 simcall->call = SIMCALL_HOST_EXECUTE;
181 simcall->host_execute.name = name;
182 simcall->host_execute.host = host;
183 simcall->host_execute.computation_amount = computation_amount;
184 simcall->host_execute.priority = priority;
185 SIMIX_simcall_push(simcall->issuer);
186 return simcall->host_execute.result;
189 /** \brief Creates an action that may involve parallel computation on
190 * several hosts and communication between them.
192 * \param name Name of the execution action to create
193 * \param host_nb Number of hosts where the action will be executed
194 * \param host_list Array (of size host_nb) of hosts where the action will be executed
195 * \param computation_amount Array (of size host_nb) of computation amount of hosts (in bytes)
196 * \param communication_amount Array (of size host_nb * host_nb) representing the communication
197 * amount between each pair of hosts
198 * \param amount the SURF action amount
199 * \param rate the SURF action rate
200 * \return A new SIMIX execution action
202 smx_action_t simcall_host_parallel_execute(const char *name,
204 smx_host_t *host_list,
205 double *computation_amount,
206 double *communication_amount,
211 /* checking for infinite values */
212 for (i = 0 ; i < host_nb ; ++i) {
213 xbt_assert(isfinite(computation_amount[i]), "computation_amount[%d] is not finite!", i);
214 for (j = 0 ; j < host_nb ; ++j) {
215 xbt_assert(isfinite(communication_amount[i + host_nb * j]),
216 "communication_amount[%d+%d*%d] is not finite!", i, host_nb, j);
220 xbt_assert(isfinite(amount), "amount is not finite!");
221 xbt_assert(isfinite(rate), "rate is not finite!");
223 smx_simcall_t simcall = SIMIX_simcall_mine();
225 simcall->call = SIMCALL_HOST_PARALLEL_EXECUTE;
226 simcall->host_parallel_execute.name = name;
227 simcall->host_parallel_execute.host_nb = host_nb;
228 simcall->host_parallel_execute.host_list = host_list;
229 simcall->host_parallel_execute.computation_amount = computation_amount;
230 simcall->host_parallel_execute.communication_amount = communication_amount;
231 simcall->host_parallel_execute.amount = amount;
232 simcall->host_parallel_execute.rate = rate;
233 SIMIX_simcall_push(simcall->issuer);
234 return simcall->host_parallel_execute.result;
238 * \brief Destroys an execution action.
240 * Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
241 * \param action The execution action to destroy
243 void simcall_host_execution_destroy(smx_action_t execution)
245 smx_simcall_t simcall = SIMIX_simcall_mine();
247 simcall->call = SIMCALL_HOST_EXECUTION_DESTROY;
248 simcall->host_execution_destroy.execution = execution;
249 SIMIX_simcall_push(simcall->issuer);
253 * \brief Cancels an execution action.
255 * This functions stops the execution. It calls a surf function.
256 * \param action The execution action to cancel
258 void simcall_host_execution_cancel(smx_action_t execution)
260 smx_simcall_t simcall = SIMIX_simcall_mine();
262 simcall->call = SIMCALL_HOST_EXECUTION_CANCEL;
263 simcall->host_execution_cancel.execution = execution;
264 SIMIX_simcall_push(simcall->issuer);
268 * \brief Returns how much of an execution action remains to be done.
270 * \param Action The execution action
271 * \return The remaining amount
273 double simcall_host_execution_get_remains(smx_action_t execution)
275 smx_simcall_t simcall = SIMIX_simcall_mine();
277 simcall->call = SIMCALL_HOST_EXECUTION_GET_REMAINS;
278 simcall->host_execution_get_remains.execution = execution;
279 SIMIX_simcall_push(simcall->issuer);
280 return simcall->host_execution_get_remains.result;
284 * \brief Returns the state of an execution action.
286 * \param execution The execution action
289 e_smx_state_t simcall_host_execution_get_state(smx_action_t execution)
291 smx_simcall_t simcall = SIMIX_simcall_mine();
293 simcall->call = SIMCALL_HOST_EXECUTION_GET_STATE;
294 simcall->host_execution_get_state.execution = execution;
295 SIMIX_simcall_push(simcall->issuer);
296 return simcall->host_execution_get_state.result;
300 * \brief Changes the priority of an execution action.
302 * This functions changes the priority only. It calls a surf function.
303 * \param execution The execution action
304 * \param priority The new priority
306 void simcall_host_execution_set_priority(smx_action_t execution, double priority)
308 /* checking for infinite values */
309 xbt_assert(isfinite(priority), "priority is not finite!");
311 smx_simcall_t simcall = SIMIX_simcall_mine();
313 simcall->call = SIMCALL_HOST_EXECUTION_SET_PRIORITY;
314 simcall->host_execution_set_priority.execution = execution;
315 simcall->host_execution_set_priority.priority = priority;
316 SIMIX_simcall_push(simcall->issuer);
320 * \brief Waits for the completion of an execution action and destroy it.
322 * \param execution The execution action
324 e_smx_state_t simcall_host_execution_wait(smx_action_t execution)
326 smx_simcall_t simcall = SIMIX_simcall_mine();
328 simcall->call = SIMCALL_HOST_EXECUTION_WAIT;
329 simcall->host_execution_wait.execution = execution;
330 SIMIX_simcall_push(simcall->issuer);
331 return simcall->host_execution_wait.result;
335 * \brief Creates and runs a new SIMIX process.
337 * The structure and the corresponding thread are created and put in the list of ready processes.
339 * \param process the process created will be stored in this pointer
340 * \param name a name for the process. It is for user-level information and can be NULL.
341 * \param code the main function of the process
342 * \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.
343 * It can be retrieved with the function \ref simcall_process_get_data.
344 * \param hostname name of the host where the new agent is executed.
345 * \param argc first argument passed to \a code
346 * \param argv second argument passed to \a code
347 * \param properties the properties of the process
349 void simcall_process_create(smx_process_t *process, const char *name,
350 xbt_main_func_t code,
352 const char *hostname,
353 int argc, char **argv,
354 xbt_dict_t properties)
356 smx_simcall_t simcall = SIMIX_simcall_mine();
358 simcall->call = SIMCALL_PROCESS_CREATE;
359 simcall->process_create.process = process;
360 simcall->process_create.name = name;
361 simcall->process_create.code = code;
362 simcall->process_create.data = data;
363 simcall->process_create.hostname = hostname;
364 simcall->process_create.argc = argc;
365 simcall->process_create.argv = argv;
366 simcall->process_create.properties = properties;
367 SIMIX_simcall_push(simcall->issuer);
370 /** \brief Kills a SIMIX process.
372 * This function simply kills a process.
374 * \param process poor victim
376 void simcall_process_kill(smx_process_t process)
378 smx_simcall_t simcall = SIMIX_simcall_mine();
380 simcall->call = SIMCALL_PROCESS_KILL;
381 simcall->process_kill.process = process;
382 SIMIX_simcall_push(simcall->issuer);
385 /** \brief Kills all SIMIX processes.
387 void simcall_process_killall(void)
389 smx_simcall_t simcall = SIMIX_simcall_mine();
391 simcall->call = SIMCALL_PROCESS_KILLALL;
392 SIMIX_simcall_push(simcall->issuer);
395 /** \brief Cleans up a SIMIX process.
396 * \param process poor victim (must have already been killed)
398 void simcall_process_cleanup(smx_process_t process)
400 smx_simcall_t simcall = SIMIX_simcall_mine();
402 simcall->call = SIMCALL_PROCESS_CLEANUP;
403 simcall->process_cleanup.process = process;
404 SIMIX_simcall_push(simcall->issuer);
408 * \brief Migrates an agent to another location.
410 * This function changes the value of the host on which \a process is running.
412 * \param process the process to migrate
413 * \param source name of the previous host
414 * \param dest name of the new host
416 void simcall_process_change_host(smx_process_t process, smx_host_t dest)
418 smx_simcall_t simcall = SIMIX_simcall_mine();
420 simcall->call = SIMCALL_PROCESS_CHANGE_HOST;
421 simcall->process_change_host.process = process;
422 simcall->process_change_host.dest = dest;
423 SIMIX_simcall_push(simcall->issuer);
427 * \brief Suspends a process.
429 * This function suspends the process by suspending the action
430 * it was waiting for completion.
432 * \param process a SIMIX process
434 void simcall_process_suspend(smx_process_t process)
436 xbt_assert(process, "Invalid parameters");
438 smx_simcall_t simcall = SIMIX_simcall_mine();
440 simcall->call = SIMCALL_PROCESS_SUSPEND;
441 simcall->process_suspend.process = process;
442 SIMIX_simcall_push(simcall->issuer);
446 * \brief Resumes a suspended process.
448 * This function resumes a suspended process by resuming the action
449 * it was waiting for completion.
451 * \param process a SIMIX process
453 void simcall_process_resume(smx_process_t process)
455 smx_simcall_t simcall = SIMIX_simcall_mine();
457 simcall->call = SIMCALL_PROCESS_RESUME;
458 simcall->process_resume.process = process;
459 SIMIX_simcall_push(simcall->issuer);
463 * \brief Returns the amount of SIMIX processes in the system
465 * Maestro internal process is not counted, only user code processes are
467 int simcall_process_count(void)
469 smx_simcall_t simcall = SIMIX_simcall_mine();
471 simcall->call = SIMCALL_PROCESS_COUNT;
472 SIMIX_simcall_push(simcall->issuer);
473 return simcall->process_count.result;
477 * \brief Return the user data of a #smx_process_t.
478 * \param process a SIMIX process
479 * \return the user data of this process
481 void* simcall_process_get_data(smx_process_t process)
483 if (process == SIMIX_process_self()) {
484 /* avoid a simcall if this function is called by the process itself */
485 return SIMIX_process_get_data(process);
488 smx_simcall_t simcall = SIMIX_simcall_mine();
490 simcall->call = SIMCALL_PROCESS_GET_DATA;
491 simcall->process_get_data.process = process;
492 SIMIX_simcall_push(simcall->issuer);
493 return simcall->process_get_data.result;
497 * \brief Set the user data of a #m_process_t.
499 * This functions checks whether \a process is a valid pointer or not and set the user data associated to \a process if it is possible.
500 * \param process SIMIX process
501 * \param data User data
503 void simcall_process_set_data(smx_process_t process, void *data)
505 if (process == SIMIX_process_self()) {
506 /* avoid a simcall if this function is called by the process itself */
507 SIMIX_process_self_set_data(process, data);
511 smx_simcall_t simcall = SIMIX_simcall_mine();
513 simcall->call = SIMCALL_PROCESS_SET_DATA;
514 simcall->process_set_data.process = process;
515 simcall->process_set_data.data = data;
516 SIMIX_simcall_push(simcall->issuer);
521 * \brief Return the location on which an agent is running.
523 * This functions checks whether \a process is a valid pointer or not and return the m_host_t corresponding to the location on which \a process is running.
524 * \param process SIMIX process
527 smx_host_t simcall_process_get_host(smx_process_t process)
529 smx_simcall_t simcall = SIMIX_simcall_mine();
531 simcall->call = SIMCALL_PROCESS_GET_HOST;
532 simcall->process_get_host.process = process;
533 SIMIX_simcall_push(simcall->issuer);
534 return simcall->process_get_host.result;
538 * \brief Return the name of an agent.
540 * This functions checks whether \a process is a valid pointer or not and return its name.
541 * \param process SIMIX process
542 * \return The process name
544 const char* simcall_process_get_name(smx_process_t process)
546 if (process == SIMIX_process_self()) {
547 /* avoid a simcall if this function is called by the process itself */
548 return process->name;
551 smx_simcall_t simcall = SIMIX_simcall_mine();
553 simcall->call = SIMCALL_PROCESS_GET_NAME;
554 simcall->process_get_name.process = process;
555 SIMIX_simcall_push(simcall->issuer);
556 return simcall->process_get_name.result;
560 * \brief Returns true if the process is suspended .
562 * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
563 * \param process SIMIX process
564 * \return 1, if the process is suspended, else 0.
566 int simcall_process_is_suspended(smx_process_t process)
568 smx_simcall_t simcall = SIMIX_simcall_mine();
570 simcall->call = SIMCALL_PROCESS_IS_SUSPENDED;
571 simcall->process_is_suspended.process = process;
572 SIMIX_simcall_push(simcall->issuer);
573 return simcall->process_is_suspended.result;
576 /** \ingroup m_process_management
577 * \brief Return the properties
579 * This functions returns the properties associated with this process
581 xbt_dict_t simcall_process_get_properties(smx_process_t process)
583 smx_simcall_t simcall = SIMIX_simcall_mine();
585 simcall->call = SIMCALL_PROCESS_GET_PROPERTIES;
586 simcall->process_get_properties.process = process;
587 SIMIX_simcall_push(simcall->issuer);
588 return simcall->process_get_properties.result;
591 /** \brief Creates a new sleep SIMIX action.
593 * This function creates a SURF action and allocates the data necessary
594 * to create the SIMIX action. It can raise a host_error exception if the
595 * host crashed. The default SIMIX name of the action is "sleep".
597 * \param duration Time duration of the sleep.
598 * \return A result telling whether the sleep was successful
600 e_smx_state_t simcall_process_sleep(double duration)
602 /* checking for infinite values */
603 xbt_assert(isfinite(duration), "duration is not finite!");
605 smx_simcall_t simcall = SIMIX_simcall_mine();
607 simcall->call = SIMCALL_PROCESS_SLEEP;
608 simcall->process_sleep.duration = duration;
609 SIMIX_simcall_push(simcall->issuer);
610 return simcall->process_sleep.result;
614 * \brief Creates a new rendez-vous point
615 * \param name The name of the rendez-vous point
616 * \return The created rendez-vous point
618 smx_rdv_t simcall_rdv_create(const char *name)
620 smx_simcall_t simcall = SIMIX_simcall_mine();
622 simcall->call = SIMCALL_RDV_CREATE;
623 simcall->rdv_create.name = name;
625 SIMIX_simcall_push(simcall->issuer);
626 return simcall->rdv_create.result;
631 * \brief Destroy a rendez-vous point
632 * \param name The rendez-vous point to destroy
634 void simcall_rdv_destroy(smx_rdv_t rdv)
636 smx_simcall_t simcall = SIMIX_simcall_mine();
638 simcall->call = SIMCALL_RDV_DESTROY;
639 simcall->rdv_destroy.rdv = rdv;
641 SIMIX_simcall_push(simcall->issuer);
644 smx_rdv_t simcall_rdv_get_by_name(const char *name)
646 xbt_assert(name != NULL, "Invalid parameter for simcall_rdv_get_by_name (name is NULL)");
648 /* FIXME: this is a horrible lost of performance, so we hack it out by
649 * skipping the simcall (for now). It works in parallel, it won't work on
650 * distributed but probably we will change MSG for that. */
653 smx_simcall_t simcall = simcall_mine();
654 simcall->call = SIMCALL_RDV_GEY_BY_NAME;
655 simcall->rdv_get_by_name.name = name;
656 SIMIX_simcall_push(simcall->issuer);
657 return simcall->rdv_get_by_name.result;*/
659 return SIMIX_rdv_get_by_name(name);
663 * \brief Counts the number of communication actions of a given host pending
664 * on a rendez-vous point.
665 * \param rdv The rendez-vous point
666 * \param host The host to be counted
667 * \return The number of comm actions pending in the rdv
669 int simcall_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
671 smx_simcall_t simcall = SIMIX_simcall_mine();
673 simcall->call = SIMCALL_RDV_COMM_COUNT_BY_HOST;
674 simcall->rdv_comm_count_by_host.rdv = rdv;
675 simcall->rdv_comm_count_by_host.host = host;
677 SIMIX_simcall_push(simcall->issuer);
678 return simcall->rdv_comm_count_by_host.result;
682 * \brief returns the communication at the head of the rendez-vous
683 * \param rdv The rendez-vous point
684 * \return The communication or NULL if empty
686 smx_action_t simcall_rdv_get_head(smx_rdv_t rdv)
688 smx_simcall_t simcall = SIMIX_simcall_mine();
690 simcall->call = SIMCALL_RDV_GET_HEAD;
691 simcall->rdv_get_head.rdv = rdv;
693 SIMIX_simcall_push(simcall->issuer);
694 return simcall->rdv_get_head.result;
697 void simcall_comm_send(smx_rdv_t rdv, double task_size, double rate,
698 void *src_buff, size_t src_buff_size,
699 int (*match_fun)(void *, void *), void *data,
702 /* checking for infinite values */
703 xbt_assert(isfinite(task_size), "task_size is not finite!");
704 xbt_assert(isfinite(rate), "rate is not finite!");
705 xbt_assert(isfinite(timeout), "timeout is not finite!");
707 xbt_assert(rdv, "No rendez-vous point defined for send");
710 /* the model-checker wants two separate simcalls */
711 smx_action_t comm = simcall_comm_isend(rdv, task_size, rate,
712 src_buff, src_buff_size, match_fun, NULL, data, 0);
713 simcall_comm_wait(comm, timeout);
716 smx_simcall_t simcall = SIMIX_simcall_mine();
718 simcall->call = SIMCALL_COMM_SEND;
719 simcall->comm_send.rdv = rdv;
720 simcall->comm_send.task_size = task_size;
721 simcall->comm_send.rate = rate;
722 simcall->comm_send.src_buff = src_buff;
723 simcall->comm_send.src_buff_size = src_buff_size;
724 simcall->comm_send.match_fun = match_fun;
725 simcall->comm_send.data = data;
726 simcall->comm_send.timeout = timeout;
728 SIMIX_simcall_push(simcall->issuer);
732 smx_action_t simcall_comm_isend(smx_rdv_t rdv, double task_size, double rate,
733 void *src_buff, size_t src_buff_size,
734 int (*match_fun)(void *, void *),
735 void (*clean_fun)(void *),
739 /* checking for infinite values */
740 xbt_assert(isfinite(task_size), "task_size is not finite!");
741 xbt_assert(isfinite(rate), "rate is not finite!");
743 xbt_assert(rdv, "No rendez-vous point defined for isend");
745 smx_simcall_t simcall = SIMIX_simcall_mine();
747 simcall->call = SIMCALL_COMM_ISEND;
748 simcall->comm_isend.rdv = rdv;
749 simcall->comm_isend.task_size = task_size;
750 simcall->comm_isend.rate = rate;
751 simcall->comm_isend.src_buff = src_buff;
752 simcall->comm_isend.src_buff_size = src_buff_size;
753 simcall->comm_isend.match_fun = match_fun;
754 simcall->comm_isend.clean_fun = clean_fun;
755 simcall->comm_isend.data = data;
756 simcall->comm_isend.detached = detached;
758 SIMIX_simcall_push(simcall->issuer);
759 return simcall->comm_isend.result;
762 void simcall_comm_recv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
763 int (*match_fun)(void *, void *), void *data, double timeout)
765 xbt_assert(isfinite(timeout), "timeout is not finite!");
766 xbt_assert(rdv, "No rendez-vous point defined for recv");
769 /* the model-checker wants two separate simcalls */
770 smx_action_t comm = simcall_comm_irecv(rdv, dst_buff, dst_buff_size,
772 simcall_comm_wait(comm, timeout);
775 smx_simcall_t simcall = SIMIX_simcall_mine();
777 simcall->call = SIMCALL_COMM_RECV;
778 simcall->comm_recv.rdv = rdv;
779 simcall->comm_recv.dst_buff = dst_buff;
780 simcall->comm_recv.dst_buff_size = dst_buff_size;
781 simcall->comm_recv.match_fun = match_fun;
782 simcall->comm_recv.data = data;
783 simcall->comm_recv.timeout = timeout;
785 SIMIX_simcall_push(simcall->issuer);
789 smx_action_t simcall_comm_irecv(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
790 int (*match_fun)(void *, void *), void *data)
792 xbt_assert(rdv, "No rendez-vous point defined for irecv");
794 smx_simcall_t simcall = SIMIX_simcall_mine();
796 simcall->call = SIMCALL_COMM_IRECV;
797 simcall->comm_irecv.rdv = rdv;
798 simcall->comm_irecv.dst_buff = dst_buff;
799 simcall->comm_irecv.dst_buff_size = dst_buff_size;
800 simcall->comm_irecv.match_fun = match_fun;
801 simcall->comm_irecv.data = data;
803 SIMIX_simcall_push(simcall->issuer);
804 return simcall->comm_irecv.result;
807 void simcall_comm_destroy(smx_action_t comm)
809 xbt_assert(comm, "Invalid parameter");
811 /* FIXME remove this simcall type: comms are auto-destroyed now */
814 smx_simcall_t simcall = simcall_mine();
816 simcall->call = SIMCALL_COMM_DESTROY;
817 simcall->comm_destroy.comm = comm;
819 SIMIX_simcall_push(simcall->issuer);
823 void simcall_comm_cancel(smx_action_t comm)
825 smx_simcall_t simcall = SIMIX_simcall_mine();
827 simcall->call = SIMCALL_COMM_CANCEL;
828 simcall->comm_cancel.comm = comm;
830 SIMIX_simcall_push(simcall->issuer);
833 unsigned int simcall_comm_waitany(xbt_dynar_t comms)
835 smx_simcall_t simcall = SIMIX_simcall_mine();
837 simcall->call = SIMCALL_COMM_WAITANY;
838 simcall->comm_waitany.comms = comms;
840 SIMIX_simcall_push(simcall->issuer);
841 return simcall->comm_waitany.result;
844 int simcall_comm_testany(xbt_dynar_t comms)
846 smx_simcall_t simcall = SIMIX_simcall_mine();
847 if (xbt_dynar_is_empty(comms))
850 simcall->call = SIMCALL_COMM_TESTANY;
851 simcall->comm_testany.comms = comms;
853 SIMIX_simcall_push(simcall->issuer);
854 return simcall->comm_testany.result;
857 void simcall_comm_wait(smx_action_t comm, double timeout)
859 xbt_assert(isfinite(timeout), "timeout is not finite!");
861 smx_simcall_t simcall = SIMIX_simcall_mine();
863 simcall->call = SIMCALL_COMM_WAIT;
864 simcall->comm_wait.comm = comm;
865 simcall->comm_wait.timeout = timeout;
867 SIMIX_simcall_push(simcall->issuer);
872 * \brief Set the category of an action.
874 * This functions changes the category only. It calls a surf function.
875 * \param execution The execution action
876 * \param category The tracing category
878 void simcall_set_category(smx_action_t action, const char *category)
880 if (category == NULL) {
884 smx_simcall_t simcall = SIMIX_simcall_mine();
886 simcall->call = SIMCALL_SET_CATEGORY;
887 simcall->set_category.action = action;
888 simcall->set_category.category = category;
890 SIMIX_simcall_push(simcall->issuer);
894 int simcall_comm_test(smx_action_t comm)
896 smx_simcall_t simcall = SIMIX_simcall_mine();
898 simcall->call = SIMCALL_COMM_TEST;
899 simcall->comm_test.comm = comm;
901 SIMIX_simcall_push(simcall->issuer);
902 return simcall->comm_test.result;
905 double simcall_comm_get_remains(smx_action_t comm)
907 smx_simcall_t simcall = SIMIX_simcall_mine();
909 simcall->call = SIMCALL_COMM_GET_REMAINS;
910 simcall->comm_get_remains.comm = comm;
912 SIMIX_simcall_push(simcall->issuer);
913 return simcall->comm_get_remains.result;
916 e_smx_state_t simcall_comm_get_state(smx_action_t comm)
918 smx_simcall_t simcall = SIMIX_simcall_mine();
920 simcall->call = SIMCALL_COMM_GET_STATE;
921 simcall->comm_get_state.comm = comm;
923 SIMIX_simcall_push(simcall->issuer);
924 return simcall->comm_get_state.result;
927 void *simcall_comm_get_src_data(smx_action_t comm)
929 smx_simcall_t simcall = SIMIX_simcall_mine();
931 simcall->call = SIMCALL_COMM_GET_SRC_DATA;
932 simcall->comm_get_src_data.comm = comm;
934 SIMIX_simcall_push(simcall->issuer);
935 return simcall->comm_get_src_data.result;
938 void *simcall_comm_get_dst_data(smx_action_t comm)
940 smx_simcall_t simcall = SIMIX_simcall_mine();
942 simcall->call = SIMCALL_COMM_GET_DST_DATA;
943 simcall->comm_get_dst_data.comm = comm;
945 SIMIX_simcall_push(simcall->issuer);
946 return simcall->comm_get_dst_data.result;
949 smx_process_t simcall_comm_get_src_proc(smx_action_t comm)
951 smx_simcall_t simcall = SIMIX_simcall_mine();
953 simcall->call = SIMCALL_COMM_GET_SRC_PROC;
954 simcall->comm_get_src_proc.comm = comm;
956 SIMIX_simcall_push(simcall->issuer);
957 return simcall->comm_get_src_proc.result;
960 smx_process_t simcall_comm_get_dst_proc(smx_action_t comm)
962 smx_simcall_t simcall = SIMIX_simcall_mine();
964 simcall->call = SIMCALL_COMM_GET_DST_PROC;
965 simcall->comm_get_dst_proc.comm = comm;
967 SIMIX_simcall_push(simcall->issuer);
968 return simcall->comm_get_dst_proc.result;
971 #ifdef HAVE_LATENCY_BOUND_TRACKING
972 int simcall_comm_is_latency_bounded(smx_action_t comm)
974 smx_simcall_t simcall = SIMIX_simcall_mine();
976 simcall->call = SIMCALL_COMM_IS_LATENCY_BOUNDED;
977 simcall->comm_is_latency_bounded.comm = comm;
979 SIMIX_simcall_push(simcall->issuer);
980 return simcall->comm_is_latency_bounded.result;
984 smx_mutex_t simcall_mutex_init(void)
986 smx_simcall_t simcall = SIMIX_simcall_mine();
988 simcall->call = SIMCALL_MUTEX_INIT;
990 SIMIX_simcall_push(simcall->issuer);
991 return simcall->mutex_init.result;
994 void simcall_mutex_destroy(smx_mutex_t mutex)
996 smx_simcall_t simcall = SIMIX_simcall_mine();
998 simcall->call = SIMCALL_MUTEX_DESTROY;
999 simcall->mutex_destroy.mutex = mutex;
1001 SIMIX_simcall_push(simcall->issuer);
1004 void simcall_mutex_lock(smx_mutex_t mutex)
1006 smx_simcall_t simcall = SIMIX_simcall_mine();
1008 simcall->call = SIMCALL_MUTEX_LOCK;
1009 simcall->mutex_lock.mutex = mutex;
1011 SIMIX_simcall_push(simcall->issuer);
1014 int simcall_mutex_trylock(smx_mutex_t mutex)
1016 smx_simcall_t simcall = SIMIX_simcall_mine();
1018 simcall->call = SIMCALL_MUTEX_TRYLOCK;
1019 simcall->mutex_trylock.mutex = mutex;
1021 SIMIX_simcall_push(simcall->issuer);
1022 return simcall->mutex_trylock.result;
1025 void simcall_mutex_unlock(smx_mutex_t mutex)
1027 smx_simcall_t simcall = SIMIX_simcall_mine();
1029 simcall->call = SIMCALL_MUTEX_UNLOCK;
1030 simcall->mutex_unlock.mutex = mutex;
1032 SIMIX_simcall_push(simcall->issuer);
1036 smx_cond_t simcall_cond_init(void)
1038 smx_simcall_t simcall = SIMIX_simcall_mine();
1040 simcall->call = SIMCALL_COND_INIT;
1042 SIMIX_simcall_push(simcall->issuer);
1043 return simcall->cond_init.result;
1046 void simcall_cond_destroy(smx_cond_t cond)
1048 smx_simcall_t simcall = SIMIX_simcall_mine();
1050 simcall->call = SIMCALL_COND_DESTROY;
1051 simcall->cond_destroy.cond = cond;
1053 SIMIX_simcall_push(simcall->issuer);
1056 void simcall_cond_signal(smx_cond_t cond)
1058 smx_simcall_t simcall = SIMIX_simcall_mine();
1060 simcall->call = SIMCALL_COND_SIGNAL;
1061 simcall->cond_signal.cond = cond;
1063 SIMIX_simcall_push(simcall->issuer);
1066 void simcall_cond_wait(smx_cond_t cond, smx_mutex_t mutex)
1068 smx_simcall_t simcall = SIMIX_simcall_mine();
1070 simcall->call = SIMCALL_COND_WAIT;
1071 simcall->cond_wait.cond = cond;
1072 simcall->cond_wait.mutex = mutex;
1074 SIMIX_simcall_push(simcall->issuer);
1077 void simcall_cond_wait_timeout(smx_cond_t cond,
1081 xbt_assert(isfinite(timeout), "timeout is not finite!");
1083 smx_simcall_t simcall = SIMIX_simcall_mine();
1085 simcall->call = SIMCALL_COND_WAIT_TIMEOUT;
1086 simcall->cond_wait_timeout.cond = cond;
1087 simcall->cond_wait_timeout.mutex = mutex;
1088 simcall->cond_wait_timeout.timeout = timeout;
1090 SIMIX_simcall_push(simcall->issuer);
1093 void simcall_cond_broadcast(smx_cond_t cond)
1095 smx_simcall_t simcall = SIMIX_simcall_mine();
1097 simcall->call = SIMCALL_COND_BROADCAST;
1098 simcall->cond_broadcast.cond = cond;
1100 SIMIX_simcall_push(simcall->issuer);
1104 smx_sem_t simcall_sem_init(int capacity)
1106 smx_simcall_t simcall = SIMIX_simcall_mine();
1108 simcall->call = SIMCALL_SEM_INIT;
1109 simcall->sem_init.capacity = capacity;
1111 SIMIX_simcall_push(simcall->issuer);
1112 return simcall->sem_init.result;
1115 void simcall_sem_destroy(smx_sem_t sem)
1117 smx_simcall_t simcall = SIMIX_simcall_mine();
1119 simcall->call = SIMCALL_SEM_DESTROY;
1120 simcall->sem_destroy.sem = sem;
1122 SIMIX_simcall_push(simcall->issuer);
1125 void simcall_sem_release(smx_sem_t sem)
1127 smx_simcall_t simcall = SIMIX_simcall_mine();
1129 simcall->call = SIMCALL_SEM_RELEASE;
1130 simcall->sem_release.sem = sem;
1132 SIMIX_simcall_push(simcall->issuer);
1135 int simcall_sem_would_block(smx_sem_t sem)
1137 smx_simcall_t simcall = SIMIX_simcall_mine();
1139 simcall->call = SIMCALL_SEM_WOULD_BLOCK;
1140 simcall->sem_would_block.sem = sem;
1142 SIMIX_simcall_push(simcall->issuer);
1143 return simcall->sem_would_block.result;
1146 void simcall_sem_acquire(smx_sem_t sem)
1148 smx_simcall_t simcall = SIMIX_simcall_mine();
1150 simcall->call = SIMCALL_SEM_ACQUIRE;
1151 simcall->sem_acquire.sem = sem;
1153 SIMIX_simcall_push(simcall->issuer);
1156 void simcall_sem_acquire_timeout(smx_sem_t sem, double timeout)
1158 xbt_assert(isfinite(timeout), "timeout is not finite!");
1160 smx_simcall_t simcall = SIMIX_simcall_mine();
1162 simcall->call = SIMCALL_SEM_ACQUIRE_TIMEOUT;
1163 simcall->sem_acquire_timeout.sem = sem;
1164 simcall->sem_acquire_timeout.timeout = timeout;
1166 SIMIX_simcall_push(simcall->issuer);
1169 int simcall_sem_get_capacity(smx_sem_t sem)
1171 smx_simcall_t simcall = SIMIX_simcall_mine();
1173 simcall->call = SIMCALL_SEM_GET_CAPACITY;
1174 simcall->sem_get_capacity.sem = sem;
1176 SIMIX_simcall_push(simcall->issuer);
1177 return simcall->sem_get_capacity.result;
1180 size_t simcall_file_read(const char* storage, void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1182 smx_simcall_t simcall = SIMIX_simcall_mine();
1184 simcall->call = SIMCALL_FILE_READ;
1185 simcall->file_read.storage = storage;
1186 simcall->file_read.ptr = ptr;
1187 simcall->file_read.size = size;
1188 simcall->file_read.nmemb = nmemb;
1189 simcall->file_read.stream = stream;
1190 SIMIX_simcall_push(simcall->issuer);
1192 return simcall->file_read.result;
1195 size_t simcall_file_write(const char* storage, const void* ptr, size_t size, size_t nmemb, smx_file_t stream)
1197 smx_simcall_t simcall = SIMIX_simcall_mine();
1199 simcall->call = SIMCALL_FILE_WRITE;
1200 simcall->file_write.storage = storage;
1201 simcall->file_write.ptr = ptr;
1202 simcall->file_write.size = size;
1203 simcall->file_write.nmemb = nmemb;
1204 simcall->file_write.stream = stream;
1205 SIMIX_simcall_push(simcall->issuer);
1207 return simcall->file_write.result;
1210 smx_file_t simcall_file_open(const char* storage, const char* path, const char* mode)
1212 smx_simcall_t simcall = SIMIX_simcall_mine();
1214 simcall->call = SIMCALL_FILE_OPEN;
1215 simcall->file_open.storage = storage;
1216 simcall->file_open.path = path;
1217 simcall->file_open.mode = mode;
1218 SIMIX_simcall_push(simcall->issuer);
1220 return simcall->file_open.result;
1223 int simcall_file_close(const char* storage, smx_file_t fp)
1225 smx_simcall_t simcall = SIMIX_simcall_mine();
1227 simcall->call = SIMCALL_FILE_CLOSE;
1228 simcall->file_close.storage = storage;
1229 simcall->file_close.fp = fp;
1230 SIMIX_simcall_push(simcall->issuer);
1232 return simcall->file_close.result;
1235 int simcall_file_stat(const char* storage, int fd, void* buf)
1237 smx_simcall_t simcall = SIMIX_simcall_mine();
1239 simcall->call = SIMCALL_FILE_STAT;
1240 simcall->file_stat.storage = storage;
1241 simcall->file_stat.fd = fd;
1242 simcall->file_stat.buf = buf;
1243 SIMIX_simcall_push(simcall->issuer);
1245 return simcall->file_stat.result;
1248 /* ************************************************************************** */
1250 /** @brief returns a printable string representing a simcall */
1251 const char *SIMIX_simcall_name(e_smx_simcall_t kind) {
1252 return simcall_names[kind];