3 /* Copyright (c) 2002-2007 Arnaud Legrand. */
4 /* Copyright (c) 2007 Bruno Donassolo. */
5 /* All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
10 #include "msg/private.h"
11 #include "xbt/sysdep.h"
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
15 "Logging specific to MSG (gos)");
17 /** \defgroup msg_gos_functions MSG Operating System Functions
18 * \brief This section describes the functions that can be used
19 * by an agent for handling some task.
22 static MSG_error_t __MSG_task_get_with_time_out_from_host(m_task_t * task,
30 m_process_t process = MSG_process_self();
33 simdata_task_t t_simdata = NULL;
34 simdata_host_t h_simdata = NULL;
36 xbt_fifo_item_t item = NULL;
38 smx_cond_t cond = NULL; //conditional wait if the task isn't on the channel yet
41 xbt_assert1((channel >= 0)
42 && (channel < msg_global->max_channel), "Invalid channel %d",
45 xbt_assert0(task, "Null pointer for the task\n");
49 ("MSG_task_get() was asked to write in a non empty task struct.");
53 h_simdata = h->simdata;
55 DEBUG2("Waiting for a task on channel %d (%s)", channel, h->name);
57 SIMIX_mutex_lock(h->simdata->mutex);
59 if (xbt_fifo_size(h_simdata->mbox[channel]) > 0) {
61 t = xbt_fifo_shift(h_simdata->mbox[channel]);
64 xbt_fifo_foreach(h->simdata->mbox[channel], item, t, m_task_t) {
65 if (t->simdata->source == host)
69 xbt_fifo_remove_item(h->simdata->mbox[channel], item);
75 if (max_duration > 0) {
77 SIMIX_mutex_unlock(h->simdata->mutex);
78 h_simdata->sleeping[channel] = NULL;
79 SIMIX_cond_destroy(cond);
80 MSG_RETURN(MSG_TRANSFER_FAILURE);
83 xbt_assert1(!(h_simdata->sleeping[channel]),
84 "A process is already blocked on channel %d", channel);
86 cond = SIMIX_cond_init();
87 h_simdata->sleeping[channel] = cond;
88 if (max_duration > 0) {
89 SIMIX_cond_wait_timeout(cond, h->simdata->mutex, max_duration);
91 SIMIX_cond_wait(h_simdata->sleeping[channel], h->simdata->mutex);
93 if (SIMIX_host_get_state(h_simdata->s_host) == 0)
94 MSG_RETURN(MSG_HOST_FAILURE);
98 SIMIX_mutex_unlock(h->simdata->mutex);
100 DEBUG1("OK, got a task (%s)", t->name);
101 /* clean conditional */
103 SIMIX_cond_destroy(cond);
104 h_simdata->sleeping[channel] = NULL;
107 t_simdata = t->simdata;
108 t_simdata->receiver = process;
111 SIMIX_mutex_lock(t_simdata->mutex);
115 /* create SIMIX action to the communication */
117 SIMIX_action_communicate(t_simdata->sender->simdata->m_host->
119 process->simdata->m_host->simdata->s_host,
120 t->name, t_simdata->message_size,
122 /* if the process is suspend, create the action but stop its execution, it will be restart when the sender process resume */
123 if (MSG_process_is_suspended(t_simdata->sender)) {
124 DEBUG1("Process sender (%s) suspended", t_simdata->sender->name);
125 SIMIX_action_set_priority(t_simdata->comm, 0);
127 process->simdata->waiting_task = t;
128 SIMIX_register_action_to_condition(t_simdata->comm, t_simdata->cond);
129 SIMIX_cond_wait(t_simdata->cond, t_simdata->mutex);
130 SIMIX_unregister_action_to_condition(t_simdata->comm, t_simdata->cond);
131 process->simdata->waiting_task = NULL;
133 /* the task has already finished and the pointer must be null */
134 if (t->simdata->sender) {
135 t->simdata->sender->simdata->waiting_task = NULL;
136 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
137 //t->simdata->comm = NULL;
138 //t->simdata->compute = NULL;
140 /* for this process, don't need to change in get function */
141 t->simdata->receiver = NULL;
142 SIMIX_mutex_unlock(t_simdata->mutex);
145 if (SIMIX_action_get_state(t_simdata->comm) == SURF_ACTION_DONE) {
146 //t_simdata->comm = NULL;
147 SIMIX_action_destroy(t_simdata->comm);
148 t_simdata->comm = NULL;
150 } else if (SIMIX_host_get_state(h_simdata->s_host) == 0) {
151 //t_simdata->comm = NULL;
152 SIMIX_action_destroy(t_simdata->comm);
153 t_simdata->comm = NULL;
154 MSG_RETURN(MSG_HOST_FAILURE);
156 //t_simdata->comm = NULL;
157 SIMIX_action_destroy(t_simdata->comm);
158 t_simdata->comm = NULL;
159 MSG_RETURN(MSG_TRANSFER_FAILURE);
164 /** \ingroup msg_gos_functions
165 * \brief Listen on a channel and wait for receiving a task.
167 * It takes two parameters.
168 * \param task a memory location for storing a #m_task_t. It will
169 hold a task when this function will return. Thus \a task should not
170 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
171 those two condition does not hold, there will be a warning message.
172 * \param channel the channel on which the agent should be
173 listening. This value has to be >=0 and < than the maximal
174 number of channels fixed with MSG_set_channel_number().
175 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
176 * if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
178 MSG_error_t MSG_task_get(m_task_t * task, m_channel_t channel)
180 return MSG_task_get_with_time_out(task, channel, -1);
183 /** \ingroup msg_gos_functions
184 * \brief Listen on a channel and wait for receiving a task with a timeout.
186 * It takes three parameters.
187 * \param task a memory location for storing a #m_task_t. It will
188 hold a task when this function will return. Thus \a task should not
189 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
190 those two condition does not hold, there will be a warning message.
191 * \param channel the channel on which the agent should be
192 listening. This value has to be >=0 and < than the maximal
193 number of channels fixed with MSG_set_channel_number().
194 * \param max_duration the maximum time to wait for a task before giving
195 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
196 will not be modified and will still be
197 equal to \c NULL when returning.
198 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
199 if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
201 MSG_error_t MSG_task_get_with_time_out(m_task_t * task,
205 return __MSG_task_get_with_time_out_from_host(task, channel,
209 /** \ingroup msg_gos_functions
210 * \brief Listen on \a channel and waits for receiving a task from \a host.
212 * It takes three parameters.
213 * \param task a memory location for storing a #m_task_t. It will
214 hold a task when this function will return. Thus \a task should not
215 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
216 those two condition does not hold, there will be a warning message.
217 * \param channel the channel on which the agent should be
218 listening. This value has to be >=0 and < than the maximal
219 number of channels fixed with MSG_set_channel_number().
220 * \param host the host that is to be watched.
221 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
222 if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
224 MSG_error_t MSG_task_get_from_host(m_task_t * task, int channel,
227 return __MSG_task_get_with_time_out_from_host(task, channel, -1, host);
230 /** \ingroup msg_gos_functions
231 * \brief Test whether there is a pending communication on a channel.
233 * It takes one parameter.
234 * \param channel the channel on which the agent should be
235 listening. This value has to be >=0 and < than the maximal
236 number of channels fixed with MSG_set_channel_number().
237 * \return 1 if there is a pending communication and 0 otherwise
239 int MSG_task_Iprobe(m_channel_t channel)
243 xbt_assert1((channel >= 0)
244 && (channel < msg_global->max_channel), "Invalid channel %d",
248 DEBUG2("Probing on channel %d (%s)", channel, h->name);
251 return (xbt_fifo_get_first_item(h->simdata->mbox[channel]) != NULL);
254 /** \ingroup msg_gos_functions
255 * \brief Test whether there is a pending communication on a channel, and who sent it.
257 * It takes one parameter.
258 * \param channel the channel on which the agent should be
259 listening. This value has to be >=0 and < than the maximal
260 number of channels fixed with MSG_set_channel_number().
261 * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
263 int MSG_task_probe_from(m_channel_t channel)
266 xbt_fifo_item_t item;
269 xbt_assert1((channel >= 0)
270 && (channel < msg_global->max_channel), "Invalid channel %d",
276 DEBUG2("Probing on channel %d (%s)", channel, h->name);
278 item = xbt_fifo_get_first_item(h->simdata->mbox[channel]);
279 if ((!item) || (!(t = xbt_fifo_get_item_content(item))))
282 return MSG_process_get_PID(t->simdata->sender);
285 /** \ingroup msg_gos_functions
286 * \brief Wait for at most \a max_duration second for a task reception
287 on \a channel. *\a PID is updated with the PID of the first process
288 that triggered this event if any.
290 * It takes three parameters:
291 * \param channel the channel on which the agent should be
292 listening. This value has to be >=0 and < than the maximal.
293 number of channels fixed with MSG_set_channel_number().
294 * \param PID a memory location for storing an int.
295 * \param max_duration the maximum time to wait for a task before
296 giving up. In the case of a reception, *\a PID will be updated
297 with the PID of the first process to send a task.
298 * \return #MSG_HOST_FAILURE if the host is shut down in the meantime
299 and #MSG_OK otherwise.
301 MSG_error_t MSG_channel_select_from(m_channel_t channel,
302 double max_duration, int *PID)
305 simdata_host_t h_simdata = NULL;
306 xbt_fifo_item_t item;
311 xbt_assert1((channel >= 0)
312 && (channel < msg_global->max_channel), "Invalid channel %d",
318 if (max_duration == 0.0) {
319 *PID = MSG_task_probe_from(channel);
324 h_simdata = h->simdata;
326 DEBUG2("Probing on channel %d (%s)", channel, h->name);
327 while (!(item = xbt_fifo_get_first_item(h->simdata->mbox[channel]))) {
328 if (max_duration > 0) {
333 SIMIX_mutex_lock(h_simdata->mutex);
334 xbt_assert1(!(h_simdata->sleeping[channel]),
335 "A process is already blocked on this channel %d",
337 cond = SIMIX_cond_init();
338 h_simdata->sleeping[channel] = cond; /* I'm waiting. Wake me up when you're ready */
339 if (max_duration > 0) {
340 SIMIX_cond_wait_timeout(cond, h_simdata->mutex, max_duration);
342 SIMIX_cond_wait(cond, h_simdata->mutex);
344 SIMIX_cond_destroy(cond);
345 SIMIX_mutex_unlock(h_simdata->mutex);
346 if (SIMIX_host_get_state(h_simdata->s_host) == 0) {
347 MSG_RETURN(MSG_HOST_FAILURE);
349 h_simdata->sleeping[channel] = NULL;
352 if (!item || !(t = xbt_fifo_get_item_content(item))) {
356 *PID = MSG_process_get_PID(t->simdata->sender);
363 /** \ingroup msg_gos_functions
365 * \brief Return the number of tasks waiting to be received on a \a
366 channel and sent by \a host.
368 * It takes two parameters.
369 * \param channel the channel on which the agent should be
370 listening. This value has to be >=0 and < than the maximal
371 number of channels fixed with MSG_set_channel_number().
372 * \param host the host that is to be watched.
373 * \return the number of tasks waiting to be received on \a channel
376 int MSG_task_probe_from_host(int channel, m_host_t host)
378 xbt_fifo_item_t item;
383 xbt_assert1((channel >= 0)
384 && (channel < msg_global->max_channel), "Invalid channel %d",
389 DEBUG2("Probing on channel %d (%s)", channel, h->name);
391 xbt_fifo_foreach(h->simdata->mbox[channel], item, t, m_task_t) {
392 if (t->simdata->source == host)
399 /** \ingroup msg_gos_functions \brief Put a task on a channel of an
400 * host (with a timeout on the waiting of the destination host) and
401 * waits for the end of the transmission.
403 * This function is used for describing the behavior of an agent. It
404 * takes four parameter.
405 * \param task a #m_task_t to send on another location. This task
406 will not be usable anymore when the function will return. There is
407 no automatic task duplication and you have to save your parameters
408 before calling this function. Tasks are unique and once it has been
409 sent to another location, you should not access it anymore. You do
410 not need to call MSG_task_destroy() but to avoid using, as an
411 effect of inattention, this task anymore, you definitely should
412 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
413 can be transfered iff it has been correctly created with
415 * \param dest the destination of the message
416 * \param channel the channel on which the agent should put this
417 task. This value has to be >=0 and < than the maximal number of
418 channels fixed with MSG_set_channel_number().
419 * \param max_duration the maximum time to wait for a task before giving
420 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
422 * \return #MSG_FATAL if \a task is not properly initialized and
423 #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
424 this function was called was shut down. Returns
425 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
426 (network failure, dest failure, timeout...)
428 MSG_error_t MSG_task_put_with_timeout(m_task_t task, m_host_t dest,
434 m_process_t process = MSG_process_self();
435 simdata_task_t task_simdata = NULL;
436 m_host_t local_host = NULL;
437 m_host_t remote_host = NULL;
440 xbt_assert1((channel >= 0)
441 && (channel < msg_global->max_channel), "Invalid channel %d",
444 task_simdata = task->simdata;
445 task_simdata->sender = process;
446 task_simdata->source = MSG_process_get_host(process);
447 xbt_assert0(task_simdata->using == 1,
448 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
449 task_simdata->comm = NULL;
451 local_host = ((simdata_process_t) process->simdata)->m_host;
454 DEBUG4("Trying to send a task (%g kB) from %s to %s on channel %d",
455 task->simdata->message_size / 1000, local_host->name,
456 remote_host->name, channel);
458 SIMIX_mutex_lock(remote_host->simdata->mutex);
459 xbt_fifo_push(((simdata_host_t) remote_host->simdata)->
460 mbox[channel], task);
463 if (remote_host->simdata->sleeping[channel]) {
464 DEBUG0("Somebody is listening. Let's wake him up!");
465 SIMIX_cond_signal(remote_host->simdata->sleeping[channel]);
467 SIMIX_mutex_unlock(remote_host->simdata->mutex);
469 process->simdata->put_host = dest;
470 process->simdata->put_channel = channel;
471 SIMIX_mutex_lock(task->simdata->mutex);
472 // DEBUG4("Task sent (%g kB) from %s to %s on channel %d, waiting...", task->simdata->message_size/1000,local_host->name, remote_host->name, channel);
474 process->simdata->waiting_task = task;
475 if (max_duration > 0) {
476 SIMIX_cond_wait_timeout(task->simdata->cond, task->simdata->mutex,
478 /* verify if the timeout happened and the communication didn't started yet */
479 if (task->simdata->comm == NULL) {
480 task->simdata->using--;
481 process->simdata->waiting_task = NULL;
482 xbt_fifo_remove(((simdata_host_t) remote_host->simdata)->
483 mbox[channel], task);
484 if (task->simdata->receiver) {
485 task->simdata->receiver->simdata->waiting_task = NULL;
487 task->simdata->sender = NULL;
488 SIMIX_mutex_unlock(task->simdata->mutex);
489 MSG_RETURN(MSG_TRANSFER_FAILURE);
492 SIMIX_cond_wait(task->simdata->cond, task->simdata->mutex);
495 DEBUG1("Action terminated %s", task->name);
496 task->simdata->using--;
497 process->simdata->waiting_task = NULL;
498 /* the task has already finished and the pointer must be null */
499 if (task->simdata->receiver) {
500 task->simdata->receiver->simdata->waiting_task = NULL;
501 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
502 // task->simdata->comm = NULL;
503 //task->simdata->compute = NULL;
505 task->simdata->sender = NULL;
506 SIMIX_mutex_unlock(task->simdata->mutex);
508 if (SIMIX_action_get_state(task->simdata->comm) == SURF_ACTION_DONE) {
510 } else if (SIMIX_host_get_state(local_host->simdata->s_host) == 0) {
511 MSG_RETURN(MSG_HOST_FAILURE);
513 MSG_RETURN(MSG_TRANSFER_FAILURE);
517 /** \ingroup msg_gos_functions
518 * \brief Put a task on a channel of an host and waits for the end of the
521 * This function is used for describing the behavior of an agent. It
522 * takes three parameter.
523 * \param task a #m_task_t to send on another location. This task
524 will not be usable anymore when the function will return. There is
525 no automatic task duplication and you have to save your parameters
526 before calling this function. Tasks are unique and once it has been
527 sent to another location, you should not access it anymore. You do
528 not need to call MSG_task_destroy() but to avoid using, as an
529 effect of inattention, this task anymore, you definitely should
530 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
531 can be transfered iff it has been correctly created with
533 * \param dest the destination of the message
534 * \param channel the channel on which the agent should put this
535 task. This value has to be >=0 and < than the maximal number of
536 channels fixed with MSG_set_channel_number().
537 * \return #MSG_FATAL if \a task is not properly initialized and
538 * #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
539 * this function was called was shut down. Returns
540 * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
541 * (network failure, dest failure)
543 MSG_error_t MSG_task_put(m_task_t task, m_host_t dest, m_channel_t channel)
545 return MSG_task_put_with_timeout(task, dest, channel, -1.0);
548 /** \ingroup msg_gos_functions
549 * \brief Does exactly the same as MSG_task_put but with a bounded transmition
554 MSG_error_t MSG_task_put_bounded(m_task_t task,
555 m_host_t dest, m_channel_t channel,
558 MSG_error_t res = MSG_OK;
559 task->simdata->rate = max_rate;
560 res = MSG_task_put(task, dest, channel);
564 /** \ingroup msg_gos_functions
565 * \brief Executes a task and waits for its termination.
567 * This function is used for describing the behavior of an agent. It
568 * takes only one parameter.
569 * \param task a #m_task_t to execute on the location on which the
571 * \return #MSG_FATAL if \a task is not properly initialized and
574 MSG_error_t MSG_task_execute(m_task_t task)
576 simdata_task_t simdata = NULL;
577 m_process_t self = MSG_process_self();
580 simdata = task->simdata;
581 xbt_assert0((!simdata->compute) && (task->simdata->using == 1),
582 "This task is executed somewhere else. Go fix your code!");
584 DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
586 SIMIX_mutex_lock(simdata->mutex);
588 SIMIX_action_execute(SIMIX_host_self(), task->name,
589 simdata->computation_amount);
590 SIMIX_action_set_priority(simdata->compute, simdata->priority);
592 self->simdata->waiting_task = task;
593 SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
594 SIMIX_cond_wait(simdata->cond, simdata->mutex);
595 SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
596 self->simdata->waiting_task = NULL;
598 SIMIX_mutex_unlock(simdata->mutex);
601 if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE) {
602 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
603 SIMIX_action_destroy(task->simdata->compute);
604 simdata->computation_amount = 0.0;
605 simdata->comm = NULL;
606 simdata->compute = NULL;
608 } else if (SIMIX_host_get_state(SIMIX_host_self()) == 0) {
609 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
610 SIMIX_action_destroy(task->simdata->compute);
611 simdata->comm = NULL;
612 simdata->compute = NULL;
613 MSG_RETURN(MSG_HOST_FAILURE);
615 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
616 SIMIX_action_destroy(task->simdata->compute);
617 simdata->comm = NULL;
618 simdata->compute = NULL;
619 MSG_RETURN(MSG_TASK_CANCELLED);
624 /** \ingroup m_task_management
625 * \brief Creates a new #m_task_t (a parallel one....).
627 * A constructor for #m_task_t taking six arguments and returning the
628 corresponding object.
629 * \param name a name for the object. It is for user-level information
631 * \param host_nb the number of hosts implied in the parallel task.
632 * \param host_list an array of \p host_nb m_host_t.
633 * \param computation_amount an array of \p host_nb
634 doubles. computation_amount[i] is the total number of operations
635 that have to be performed on host_list[i].
636 * \param communication_amount an array of \p host_nb* \p host_nb doubles.
637 * \param data a pointer to any data may want to attach to the new
638 object. It is for user-level information and can be NULL. It can
639 be retrieved with the function \ref MSG_task_get_data.
641 * \return The new corresponding object.
643 m_task_t MSG_parallel_task_create(const char *name,
645 const m_host_t * host_list,
646 double *computation_amount,
647 double *communication_amount, void *data)
650 simdata_task_t simdata = xbt_new0(s_simdata_task_t, 1);
651 m_task_t task = xbt_new0(s_m_task_t, 1);
652 task->simdata = simdata;
655 task->name = xbt_strdup(name);
659 simdata->computation_amount = 0;
660 simdata->message_size = 0;
661 simdata->cond = SIMIX_cond_init();
662 simdata->mutex = SIMIX_mutex_init();
663 simdata->compute = NULL;
664 simdata->comm = NULL;
665 simdata->rate = -1.0;
667 simdata->sender = NULL;
668 simdata->receiver = NULL;
669 simdata->source = NULL;
671 simdata->host_nb = host_nb;
672 simdata->host_list = xbt_new0(void *, host_nb);
673 simdata->comp_amount = computation_amount;
674 simdata->comm_amount = communication_amount;
676 for (i = 0; i < host_nb; i++)
677 simdata->host_list[i] = host_list[i]->simdata->s_host;
684 MSG_error_t MSG_parallel_task_execute(m_task_t task)
686 simdata_task_t simdata = NULL;
687 m_process_t self = MSG_process_self();
690 simdata = task->simdata;
691 xbt_assert0((!simdata->compute) && (task->simdata->using == 1),
692 "This task is executed somewhere else. Go fix your code!");
694 xbt_assert0(simdata->host_nb,
695 "This is not a parallel task. Go to hell.");
697 DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
699 SIMIX_mutex_lock(simdata->mutex);
701 SIMIX_action_parallel_execute(task->name, simdata->host_nb,
703 simdata->comp_amount,
704 simdata->comm_amount, 1.0, -1.0);
706 self->simdata->waiting_task = task;
707 SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
708 SIMIX_cond_wait(simdata->cond, simdata->mutex);
709 SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
710 self->simdata->waiting_task = NULL;
713 SIMIX_mutex_unlock(simdata->mutex);
716 if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE) {
717 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
718 SIMIX_action_destroy(task->simdata->compute);
719 simdata->computation_amount = 0.0;
720 simdata->comm = NULL;
721 simdata->compute = NULL;
723 } else if (SIMIX_host_get_state(SIMIX_host_self()) == 0) {
724 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
725 SIMIX_action_destroy(task->simdata->compute);
726 simdata->comm = NULL;
727 simdata->compute = NULL;
728 MSG_RETURN(MSG_HOST_FAILURE);
730 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
731 SIMIX_action_destroy(task->simdata->compute);
732 simdata->comm = NULL;
733 simdata->compute = NULL;
734 MSG_RETURN(MSG_TASK_CANCELLED);
740 /** \ingroup msg_gos_functions
741 * \brief Sleep for the specified number of seconds
743 * Makes the current process sleep until \a time seconds have elapsed.
745 * \param nb_sec a number of second
747 MSG_error_t MSG_process_sleep(double nb_sec)
749 smx_action_t act_sleep;
750 m_process_t proc = MSG_process_self();
753 /* create action to sleep */
755 SIMIX_action_sleep(SIMIX_process_get_host(proc->simdata->s_process),
758 mutex = SIMIX_mutex_init();
759 SIMIX_mutex_lock(mutex);
760 /* create conditional and register action to it */
761 cond = SIMIX_cond_init();
763 SIMIX_register_action_to_condition(act_sleep, cond);
764 SIMIX_cond_wait(cond, mutex);
765 SIMIX_unregister_action_to_condition(act_sleep, cond);
766 SIMIX_mutex_unlock(mutex);
768 /* remove variables */
769 SIMIX_cond_destroy(cond);
770 SIMIX_mutex_destroy(mutex);
772 if (SIMIX_action_get_state(act_sleep) == SURF_ACTION_DONE) {
773 if (SIMIX_host_get_state(SIMIX_host_self()) == SURF_CPU_OFF) {
774 SIMIX_action_destroy(act_sleep);
775 MSG_RETURN(MSG_HOST_FAILURE);
778 SIMIX_action_destroy(act_sleep);
779 MSG_RETURN(MSG_HOST_FAILURE);
786 /** \ingroup msg_gos_functions
787 * \brief Return the number of MSG tasks currently running on
788 * the host of the current running process.
790 static int MSG_get_msgload(void)
792 xbt_die("not implemented yet");
796 /** \ingroup msg_gos_functions
798 * \brief Return the last value returned by a MSG function (except
801 MSG_error_t MSG_get_errno(void)
803 return PROCESS_GET_ERRNO();