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 MSG_error_t MSG_task_get_ext(m_task_t * task,
28 m_process_t process = MSG_process_self();
31 simdata_task_t t_simdata = NULL;
32 simdata_host_t h_simdata = NULL;
34 xbt_fifo_item_t item = NULL;
36 smx_cond_t cond = NULL; //conditional wait if the task isn't on the channel yet
39 xbt_assert1((channel >= 0)
40 && (channel < msg_global->max_channel), "Invalid channel %d",
43 xbt_assert0(task, "Null pointer for the task storage");
47 ("MSG_task_get() was asked to write in a non empty task struct.");
51 h_simdata = h->simdata;
53 DEBUG2("Waiting for a task on channel %d (%s)", channel, h->name);
55 SIMIX_mutex_lock(h->simdata->mutex);
57 if (xbt_fifo_size(h_simdata->mbox[channel]) > 0) {
59 t = xbt_fifo_shift(h_simdata->mbox[channel]);
62 xbt_fifo_foreach(h->simdata->mbox[channel], item, t, m_task_t) {
63 if (t->simdata->source == host)
67 xbt_fifo_remove_item(h->simdata->mbox[channel], item);
73 if (max_duration > 0) {
75 SIMIX_mutex_unlock(h->simdata->mutex);
76 h_simdata->sleeping[channel] = NULL;
77 SIMIX_cond_destroy(cond);
78 MSG_RETURN(MSG_TRANSFER_FAILURE);
81 xbt_assert1(!(h_simdata->sleeping[channel]),
82 "A process is already blocked on channel %d", channel);
84 cond = SIMIX_cond_init();
85 h_simdata->sleeping[channel] = cond;
87 SIMIX_cond_wait_timeout(cond, h->simdata->mutex, max_duration);
89 SIMIX_cond_wait(h_simdata->sleeping[channel], h->simdata->mutex);
91 if (SIMIX_host_get_state(h_simdata->smx_host) == 0)
92 MSG_RETURN(MSG_HOST_FAILURE);
96 SIMIX_mutex_unlock(h->simdata->mutex);
98 DEBUG1("OK, got a task (%s)", t->name);
99 /* clean conditional */
101 SIMIX_cond_destroy(cond);
102 h_simdata->sleeping[channel] = NULL;
105 t_simdata = t->simdata;
106 t_simdata->receiver = process;
109 SIMIX_mutex_lock(t_simdata->mutex);
112 /* create SIMIX action to the communication */
114 SIMIX_action_communicate(t_simdata->sender->simdata->m_host->
116 process->simdata->m_host->simdata->smx_host,
117 t->name, t_simdata->message_size,
119 /* if the process is suspend, create the action but stop its execution, it will be restart when the sender process resume */
120 if (MSG_process_is_suspended(t_simdata->sender)) {
121 DEBUG1("Process sender (%s) suspended", t_simdata->sender->name);
122 SIMIX_action_set_priority(t_simdata->comm, 0);
124 process->simdata->waiting_task = t;
125 SIMIX_register_action_to_condition(t_simdata->comm, t_simdata->cond);
127 SIMIX_cond_wait(t_simdata->cond, t_simdata->mutex);
128 if (SIMIX_action_get_state(t_simdata->comm) != SURF_ACTION_RUNNING)
131 SIMIX_unregister_action_to_condition(t_simdata->comm, t_simdata->cond);
132 process->simdata->waiting_task = NULL;
134 /* the task has already finished and the pointer must be null */
135 if (t->simdata->sender) {
136 t->simdata->sender->simdata->waiting_task = NULL;
137 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
138 //t->simdata->comm = NULL;
139 //t->simdata->compute = NULL;
141 /* for this process, don't need to change in get function */
142 t->simdata->receiver = NULL;
143 SIMIX_mutex_unlock(t_simdata->mutex);
146 if (SIMIX_action_get_state(t_simdata->comm) == SURF_ACTION_DONE) {
147 //t_simdata->comm = NULL;
148 SIMIX_action_destroy(t_simdata->comm);
149 t_simdata->comm = NULL;
152 } else if (SIMIX_host_get_state(h_simdata->smx_host) == 0) {
153 //t_simdata->comm = NULL;
154 SIMIX_action_destroy(t_simdata->comm);
155 t_simdata->comm = NULL;
157 MSG_RETURN(MSG_HOST_FAILURE);
159 //t_simdata->comm = NULL;
160 SIMIX_action_destroy(t_simdata->comm);
161 t_simdata->comm = NULL;
163 MSG_RETURN(MSG_TRANSFER_FAILURE);
168 /** \ingroup msg_gos_functions
169 * \brief Listen on a channel and wait for receiving a task.
171 * It takes two parameters.
172 * \param task a memory location for storing a #m_task_t. It will
173 hold a task when this function will return. Thus \a task should not
174 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
175 those two condition does not hold, there will be a warning message.
176 * \param channel the channel on which the agent should be
177 listening. This value has to be >=0 and < than the maximal
178 number of channels fixed with MSG_set_channel_number().
179 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
180 * if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
182 MSG_error_t MSG_task_get(m_task_t * task, m_channel_t channel)
184 return MSG_task_get_with_time_out(task, channel, -1);
187 /** \ingroup msg_gos_functions
188 * \brief Listen on a channel and wait for receiving a task with a timeout.
190 * It takes three parameters.
191 * \param task a memory location for storing a #m_task_t. It will
192 hold a task when this function will return. Thus \a task should not
193 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
194 those two condition does not hold, there will be a warning message.
195 * \param channel the channel on which the agent should be
196 listening. This value has to be >=0 and < than the maximal
197 number of channels fixed with MSG_set_channel_number().
198 * \param max_duration the maximum time to wait for a task before giving
199 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
200 will not be modified and will still be
201 equal to \c NULL when returning.
202 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
203 if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
205 MSG_error_t MSG_task_get_with_time_out(m_task_t * task,
209 return MSG_task_get_ext(task, channel, max_duration, NULL);
212 /** \ingroup msg_gos_functions
213 * \brief Listen on \a channel and waits for receiving a task from \a host.
215 * It takes three parameters.
216 * \param task a memory location for storing a #m_task_t. It will
217 hold a task when this function will return. Thus \a task should not
218 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
219 those two condition does not hold, there will be a warning message.
220 * \param channel the channel on which the agent should be
221 listening. This value has to be >=0 and < than the maximal
222 number of channels fixed with MSG_set_channel_number().
223 * \param host the host that is to be watched.
224 * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
225 if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
227 MSG_error_t MSG_task_get_from_host(m_task_t * task, int channel,
230 return MSG_task_get_ext(task, channel, -1, host);
233 /** \ingroup msg_gos_functions
234 * \brief Test whether there is a pending communication on a channel.
236 * It takes one parameter.
237 * \param channel the channel on which the agent should be
238 listening. This value has to be >=0 and < than the maximal
239 number of channels fixed with MSG_set_channel_number().
240 * \return 1 if there is a pending communication and 0 otherwise
242 int MSG_task_Iprobe(m_channel_t channel)
246 xbt_assert1((channel >= 0)
247 && (channel < msg_global->max_channel), "Invalid channel %d",
251 DEBUG2("Probing on channel %d (%s)", channel, h->name);
254 return (xbt_fifo_get_first_item(h->simdata->mbox[channel]) != NULL);
257 /** \ingroup msg_gos_functions
258 * \brief Test whether there is a pending communication on a channel, and who sent it.
260 * It takes one parameter.
261 * \param channel the channel on which the agent should be
262 listening. This value has to be >=0 and < than the maximal
263 number of channels fixed with MSG_set_channel_number().
264 * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
266 int MSG_task_probe_from(m_channel_t channel)
269 xbt_fifo_item_t item;
272 xbt_assert1((channel >= 0)
273 && (channel < msg_global->max_channel), "Invalid channel %d",
279 DEBUG2("Probing on channel %d (%s)", channel, h->name);
281 item = xbt_fifo_get_first_item(h->simdata->mbox[channel]);
282 if ((!item) || (!(t = xbt_fifo_get_item_content(item))))
285 return MSG_process_get_PID(t->simdata->sender);
288 /** \ingroup msg_gos_functions
289 * \brief Wait for at most \a max_duration second for a task reception
292 * \a PID is updated with the PID of the first process that triggered this event if any.
294 * It takes three parameters:
295 * \param channel the channel on which the agent should be
296 listening. This value has to be >=0 and < than the maximal.
297 number of channels fixed with MSG_set_channel_number().
298 * \param PID a memory location for storing an int.
299 * \param max_duration the maximum time to wait for a task before
300 giving up. In the case of a reception, *\a PID will be updated
301 with the PID of the first process to send a task.
302 * \return #MSG_HOST_FAILURE if the host is shut down in the meantime
303 and #MSG_OK otherwise.
305 MSG_error_t MSG_channel_select_from(m_channel_t channel,
306 double max_duration, int *PID)
309 simdata_host_t h_simdata = NULL;
310 xbt_fifo_item_t item;
315 xbt_assert1((channel >= 0)
316 && (channel < msg_global->max_channel), "Invalid channel %d",
322 if (max_duration == 0.0) {
323 *PID = MSG_task_probe_from(channel);
328 h_simdata = h->simdata;
330 DEBUG2("Probing on channel %d (%s)", channel, h->name);
331 while (!(item = xbt_fifo_get_first_item(h->simdata->mbox[channel]))) {
332 if (max_duration > 0) {
337 SIMIX_mutex_lock(h_simdata->mutex);
338 xbt_assert1(!(h_simdata->sleeping[channel]),
339 "A process is already blocked on this channel %d",
341 cond = SIMIX_cond_init();
342 h_simdata->sleeping[channel] = cond; /* I'm waiting. Wake me up when you're ready */
343 if (max_duration > 0) {
344 SIMIX_cond_wait_timeout(cond, h_simdata->mutex, max_duration);
346 SIMIX_cond_wait(cond, h_simdata->mutex);
348 SIMIX_cond_destroy(cond);
349 SIMIX_mutex_unlock(h_simdata->mutex);
350 if (SIMIX_host_get_state(h_simdata->smx_host) == 0) {
351 MSG_RETURN(MSG_HOST_FAILURE);
353 h_simdata->sleeping[channel] = NULL;
356 if (!item || !(t = xbt_fifo_get_item_content(item))) {
360 *PID = MSG_process_get_PID(t->simdata->sender);
367 /** \ingroup msg_gos_functions
369 * \brief Return the number of tasks waiting to be received on a \a
370 channel and sent by \a host.
372 * It takes two parameters.
373 * \param channel the channel on which the agent should be
374 listening. This value has to be >=0 and < than the maximal
375 number of channels fixed with MSG_set_channel_number().
376 * \param host the host that is to be watched.
377 * \return the number of tasks waiting to be received on \a channel
380 int MSG_task_probe_from_host(int channel, m_host_t host)
382 xbt_fifo_item_t item;
387 xbt_assert1((channel >= 0)
388 && (channel < msg_global->max_channel), "Invalid channel %d",
393 DEBUG2("Probing on channel %d (%s)", channel, h->name);
395 xbt_fifo_foreach(h->simdata->mbox[channel], item, t, m_task_t) {
396 if (t->simdata->source == host)
403 /** \ingroup msg_gos_functions \brief Put a task on a channel of an
404 * host (with a timeout on the waiting of the destination host) and
405 * waits for the end of the transmission.
407 * This function is used for describing the behavior of an agent. It
408 * takes four parameter.
409 * \param task a #m_task_t to send on another location. This task
410 will not be usable anymore when the function will return. There is
411 no automatic task duplication and you have to save your parameters
412 before calling this function. Tasks are unique and once it has been
413 sent to another location, you should not access it anymore. You do
414 not need to call MSG_task_destroy() but to avoid using, as an
415 effect of inattention, this task anymore, you definitely should
416 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
417 can be transfered iff it has been correctly created with
419 * \param dest the destination of the message
420 * \param channel the channel on which the agent should put this
421 task. This value has to be >=0 and < than the maximal number of
422 channels fixed with MSG_set_channel_number().
423 * \param max_duration the maximum time to wait for a task before giving
424 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
426 * \return #MSG_FATAL if \a task is not properly initialized and
427 #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
428 this function was called was shut down. Returns
429 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
430 (network failure, dest failure, timeout...)
432 MSG_error_t MSG_task_put_with_timeout(m_task_t task, m_host_t dest,
438 m_process_t process = MSG_process_self();
439 simdata_task_t task_simdata = NULL;
440 m_host_t local_host = NULL;
441 m_host_t remote_host = NULL;
444 xbt_assert1((channel >= 0)
445 && (channel < msg_global->max_channel), "Invalid channel %d",
448 task_simdata = task->simdata;
449 task_simdata->sender = process;
450 task_simdata->source = MSG_process_get_host(process);
451 xbt_assert0(task_simdata->using == 1,
452 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
453 task_simdata->comm = NULL;
455 task_simdata->using++;
456 local_host = ((simdata_process_t) process->simdata)->m_host;
459 DEBUG4("Trying to send a task (%g kB) from %s to %s on channel %d",
460 task->simdata->message_size / 1000, local_host->name,
461 remote_host->name, channel);
463 SIMIX_mutex_lock(remote_host->simdata->mutex);
464 xbt_fifo_push(((simdata_host_t) remote_host->simdata)->
465 mbox[channel], task);
468 if (remote_host->simdata->sleeping[channel]) {
469 DEBUG0("Somebody is listening. Let's wake him up!");
470 SIMIX_cond_signal(remote_host->simdata->sleeping[channel]);
472 SIMIX_mutex_unlock(remote_host->simdata->mutex);
474 process->simdata->put_host = dest;
475 process->simdata->put_channel = channel;
476 SIMIX_mutex_lock(task->simdata->mutex);
477 // 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);
479 process->simdata->waiting_task = task;
480 if (max_duration > 0) {
484 time = SIMIX_get_clock();
486 /*verify if the action that ends is the correct. Call the wait_timeout with the new time. If the timeout occurs, an exception is raised */
488 time_elapsed = SIMIX_get_clock() - time;
489 SIMIX_cond_wait_timeout(task->simdata->cond, task->simdata->mutex,
490 max_duration-time_elapsed);
491 if ((task->simdata->comm != NULL) &&
492 (SIMIX_action_get_state(task->simdata->comm) != SURF_ACTION_RUNNING))
496 if(e.category==timeout_error) {
498 /* verify if the timeout happened and the communication didn't started yet */
499 if (task->simdata->comm == NULL) {
500 process->simdata->waiting_task = NULL;
501 xbt_fifo_remove(((simdata_host_t) remote_host->simdata)->
502 mbox[channel], task);
503 if (task->simdata->receiver) {
504 task->simdata->receiver->simdata->waiting_task = NULL;
506 task->simdata->sender = NULL;
507 SIMIX_mutex_unlock(task->simdata->mutex);
508 MSG_RETURN(MSG_TRANSFER_FAILURE);
516 SIMIX_cond_wait(task->simdata->cond, task->simdata->mutex);
517 if (SIMIX_action_get_state(task->simdata->comm) != SURF_ACTION_RUNNING)
522 DEBUG1("Action terminated %s", task->name);
523 process->simdata->waiting_task = NULL;
524 /* the task has already finished and the pointer must be null */
525 if (task->simdata->receiver) {
526 task->simdata->receiver->simdata->waiting_task = NULL;
527 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
528 // task->simdata->comm = NULL;
529 //task->simdata->compute = NULL;
531 task->simdata->sender = NULL;
532 SIMIX_mutex_unlock(task->simdata->mutex);
534 if (SIMIX_action_get_state(task->simdata->comm) == SURF_ACTION_DONE) {
536 } else if (SIMIX_host_get_state(local_host->simdata->smx_host) == 0) {
537 MSG_RETURN(MSG_HOST_FAILURE);
539 MSG_RETURN(MSG_TRANSFER_FAILURE);
543 /** \ingroup msg_gos_functions
544 * \brief Put a task on a channel of an host and waits for the end of the
547 * This function is used for describing the behavior of an agent. It
548 * takes three parameter.
549 * \param task a #m_task_t to send on another location. This task
550 will not be usable anymore when the function will return. There is
551 no automatic task duplication and you have to save your parameters
552 before calling this function. Tasks are unique and once it has been
553 sent to another location, you should not access it anymore. You do
554 not need to call MSG_task_destroy() but to avoid using, as an
555 effect of inattention, this task anymore, you definitely should
556 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
557 can be transfered iff it has been correctly created with
559 * \param dest the destination of the message
560 * \param channel the channel on which the agent should put this
561 task. This value has to be >=0 and < than the maximal number of
562 channels fixed with MSG_set_channel_number().
563 * \return #MSG_FATAL if \a task is not properly initialized and
564 * #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
565 * this function was called was shut down. Returns
566 * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
567 * (network failure, dest failure)
569 MSG_error_t MSG_task_put(m_task_t task, m_host_t dest, m_channel_t channel)
571 return MSG_task_put_with_timeout(task, dest, channel, -1.0);
574 /** \ingroup msg_gos_functions
575 * \brief Does exactly the same as MSG_task_put but with a bounded transmition
580 MSG_error_t MSG_task_put_bounded(m_task_t task,
581 m_host_t dest, m_channel_t channel,
584 MSG_error_t res = MSG_OK;
585 task->simdata->rate = max_rate;
586 res = MSG_task_put(task, dest, channel);
590 /** \ingroup msg_gos_functions
591 * \brief Executes a task and waits for its termination.
593 * This function is used for describing the behavior of an agent. It
594 * takes only one parameter.
595 * \param task a #m_task_t to execute on the location on which the
597 * \return #MSG_FATAL if \a task is not properly initialized and
600 MSG_error_t MSG_task_execute(m_task_t task)
602 simdata_task_t simdata = NULL;
603 m_process_t self = MSG_process_self();
606 simdata = task->simdata;
607 xbt_assert0((!simdata->compute) && (task->simdata->using == 1),
608 "This task is executed somewhere else. Go fix your code!");
610 DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
612 SIMIX_mutex_lock(simdata->mutex);
614 SIMIX_action_execute(SIMIX_host_self(), task->name,
615 simdata->computation_amount);
616 SIMIX_action_set_priority(simdata->compute, simdata->priority);
618 self->simdata->waiting_task = task;
619 SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
620 SIMIX_cond_wait(simdata->cond, simdata->mutex);
621 SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
622 self->simdata->waiting_task = NULL;
624 SIMIX_mutex_unlock(simdata->mutex);
627 if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE) {
628 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
629 SIMIX_action_destroy(task->simdata->compute);
630 simdata->computation_amount = 0.0;
631 simdata->comm = NULL;
632 simdata->compute = NULL;
634 } else if (SIMIX_host_get_state(SIMIX_host_self()) == 0) {
635 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
636 SIMIX_action_destroy(task->simdata->compute);
637 simdata->comm = NULL;
638 simdata->compute = NULL;
639 MSG_RETURN(MSG_HOST_FAILURE);
641 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
642 SIMIX_action_destroy(task->simdata->compute);
643 simdata->comm = NULL;
644 simdata->compute = NULL;
645 MSG_RETURN(MSG_TASK_CANCELLED);
650 /** \ingroup m_task_management
651 * \brief Creates a new #m_task_t (a parallel one....).
653 * A constructor for #m_task_t taking six arguments and returning the
654 corresponding object.
655 * \param name a name for the object. It is for user-level information
657 * \param host_nb the number of hosts implied in the parallel task.
658 * \param host_list an array of \p host_nb m_host_t.
659 * \param computation_amount an array of \p host_nb
660 doubles. computation_amount[i] is the total number of operations
661 that have to be performed on host_list[i].
662 * \param communication_amount an array of \p host_nb* \p host_nb doubles.
663 * \param data a pointer to any data may want to attach to the new
664 object. It is for user-level information and can be NULL. It can
665 be retrieved with the function \ref MSG_task_get_data.
667 * \return The new corresponding object.
669 m_task_t MSG_parallel_task_create(const char *name,
671 const m_host_t * host_list,
672 double *computation_amount,
673 double *communication_amount, void *data)
676 simdata_task_t simdata = xbt_new0(s_simdata_task_t, 1);
677 m_task_t task = xbt_new0(s_m_task_t, 1);
678 task->simdata = simdata;
681 task->name = xbt_strdup(name);
685 simdata->computation_amount = 0;
686 simdata->message_size = 0;
687 simdata->cond = SIMIX_cond_init();
688 simdata->mutex = SIMIX_mutex_init();
689 simdata->compute = NULL;
690 simdata->comm = NULL;
691 simdata->rate = -1.0;
693 simdata->sender = NULL;
694 simdata->receiver = NULL;
695 simdata->source = NULL;
697 simdata->host_nb = host_nb;
698 simdata->host_list = xbt_new0(smx_host_t, host_nb);
699 simdata->comp_amount = computation_amount;
700 simdata->comm_amount = communication_amount;
702 for (i = 0; i < host_nb; i++)
703 simdata->host_list[i] = host_list[i]->simdata->smx_host;
710 MSG_error_t MSG_parallel_task_execute(m_task_t task)
712 simdata_task_t simdata = NULL;
713 m_process_t self = MSG_process_self();
716 simdata = task->simdata;
717 xbt_assert0((!simdata->compute) && (task->simdata->using == 1),
718 "This task is executed somewhere else. Go fix your code!");
720 xbt_assert0(simdata->host_nb,
721 "This is not a parallel task. Go to hell.");
723 DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
725 SIMIX_mutex_lock(simdata->mutex);
727 SIMIX_action_parallel_execute(task->name, simdata->host_nb,
729 simdata->comp_amount,
730 simdata->comm_amount, 1.0, -1.0);
732 self->simdata->waiting_task = task;
733 SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
734 SIMIX_cond_wait(simdata->cond, simdata->mutex);
735 SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
736 self->simdata->waiting_task = NULL;
739 SIMIX_mutex_unlock(simdata->mutex);
742 if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE) {
743 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
744 SIMIX_action_destroy(task->simdata->compute);
745 simdata->computation_amount = 0.0;
746 simdata->comm = NULL;
747 simdata->compute = NULL;
749 } else if (SIMIX_host_get_state(SIMIX_host_self()) == 0) {
750 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
751 SIMIX_action_destroy(task->simdata->compute);
752 simdata->comm = NULL;
753 simdata->compute = NULL;
754 MSG_RETURN(MSG_HOST_FAILURE);
756 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
757 SIMIX_action_destroy(task->simdata->compute);
758 simdata->comm = NULL;
759 simdata->compute = NULL;
760 MSG_RETURN(MSG_TASK_CANCELLED);
766 /** \ingroup msg_gos_functions
767 * \brief Sleep for the specified number of seconds
769 * Makes the current process sleep until \a time seconds have elapsed.
771 * \param nb_sec a number of second
773 MSG_error_t MSG_process_sleep(double nb_sec)
775 smx_action_t act_sleep;
776 m_process_t proc = MSG_process_self();
779 /* create action to sleep */
781 SIMIX_action_sleep(SIMIX_process_get_host(proc->simdata->s_process),
784 mutex = SIMIX_mutex_init();
785 SIMIX_mutex_lock(mutex);
786 /* create conditional and register action to it */
787 cond = SIMIX_cond_init();
789 SIMIX_register_action_to_condition(act_sleep, cond);
790 SIMIX_cond_wait(cond, mutex);
791 SIMIX_unregister_action_to_condition(act_sleep, cond);
792 SIMIX_mutex_unlock(mutex);
794 /* remove variables */
795 SIMIX_cond_destroy(cond);
796 SIMIX_mutex_destroy(mutex);
798 if (SIMIX_action_get_state(act_sleep) == SURF_ACTION_DONE) {
799 if (SIMIX_host_get_state(SIMIX_host_self()) == SURF_CPU_OFF) {
800 SIMIX_action_destroy(act_sleep);
801 MSG_RETURN(MSG_HOST_FAILURE);
804 SIMIX_action_destroy(act_sleep);
805 MSG_RETURN(MSG_HOST_FAILURE);
812 /** \ingroup msg_gos_functions
813 * \brief Return the number of MSG tasks currently running on
814 * the host of the current running process.
816 static int MSG_get_msgload(void)
818 xbt_die("not implemented yet");
822 /** \ingroup msg_gos_functions
824 * \brief Return the last value returned by a MSG function (except
827 MSG_error_t MSG_get_errno(void)
829 return PROCESS_GET_ERRNO();