Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bummer: I increased the amount of displayed info to track down an issue in ruby,...
[simgrid.git] / src / msg / task.c
1 /*     $Id$      */
2
3 /* Copyright (c) 2002-2007 Arnaud Legrand.                                  */
4 /* Copyright (c) 2007 Bruno Donassolo.                                      */
5 /* All rights reserved.                                                     */
6
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. */
9
10 #include "msg/private.h"
11 #include "xbt/sysdep.h"
12 #include "xbt/log.h"
13
14 /** \defgroup m_task_management Managing functions of Tasks
15  *  \brief This section describes the task structure of MSG
16  *  (#m_task_t) and the functions for managing it.
17  */
18 /** @addtogroup m_task_management
19  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Tasks" --> \endhtmlonly
20  * 
21  *  Since most scheduling algorithms rely on a concept of task
22  *  that can be either <em>computed</em> locally or
23  *  <em>transferred</em> on another processor, it seems to be the
24  *  right level of abstraction for our purposes. A <em>task</em>
25  *  may then be defined by a <em>computing amount</em>, a
26  *  <em>message size</em> and some <em>private data</em>.
27  */
28
29 #ifdef HAVE_RUBY /* FIXME: KILLME */
30 XBT_LOG_EXTERNAL_CATEGORY(ruby);
31 #endif
32
33 /********************************* Task **************************************/
34 /** \ingroup m_task_management
35  * \brief Creates a new #m_task_t.
36  *
37  * A constructor for #m_task_t taking four arguments and returning the 
38    corresponding object.
39  * \param name a name for the object. It is for user-level information
40    and can be NULL.
41  * \param compute_duration a value of the processing amount (in flop)
42    needed to process this new task. If 0, then it cannot be executed with
43    MSG_task_execute(). This value has to be >=0.
44  * \param message_size a value of the amount of data (in bytes) needed to
45    transfer this new task. If 0, then it cannot be transfered with
46    MSG_task_get() and MSG_task_put(). This value has to be >=0.
47  * \param data a pointer to any data may want to attach to the new
48    object.  It is for user-level information and can be NULL. It can
49    be retrieved with the function \ref MSG_task_get_data.
50  * \see m_task_t
51  * \return The new corresponding object.
52  */
53 m_task_t MSG_task_create(const char *name, double compute_duration,
54                          double message_size, void *data)
55 {
56   m_task_t task = xbt_new(s_m_task_t, 1);
57   simdata_task_t simdata = xbt_new(s_simdata_task_t, 1);
58   task->simdata = simdata;
59   /* Task structure */
60   task->name = xbt_strdup(name);
61   task->data = data;
62
63   /* Simulator Data */
64   simdata->computation_amount = compute_duration;
65   simdata->message_size = message_size;
66   simdata->rate = -1.0;
67   simdata->priority = 1.0;
68   simdata->refcount = 1;
69   simdata->sender = NULL;
70   simdata->receiver = NULL;
71   simdata->cond = SIMIX_cond_init();
72   simdata->mutex = SIMIX_mutex_init();
73   simdata->compute = NULL;
74   simdata->comm = NULL;
75
76   simdata->host_list = NULL;
77   simdata->comp_amount = NULL;
78   simdata->comm_amount = NULL;
79
80 #ifdef HAVE_RUBY /* FIXME: KILLME */
81   CINFO2(ruby,"Created task %p: %s",task,name);
82 #endif
83
84   return task;
85 }
86
87 /** \ingroup m_task_management
88  * \brief Return the user data of a #m_task_t.
89  *
90  * This functions checks whether \a task is a valid pointer or not and return
91    the user data associated to \a task if it is possible.
92  */
93 void *MSG_task_get_data(m_task_t task)
94 {
95   xbt_assert0((task != NULL), "Invalid parameter");
96
97   return (task->data);
98 }
99
100 /** \ingroup m_task_management
101  * \brief Return the sender of a #m_task_t.
102  *
103  * This functions returns the #m_process_t which sent this task
104  */
105 m_process_t MSG_task_get_sender(m_task_t task)
106 {
107   xbt_assert0(task, "Invalid parameters");
108   return ((simdata_task_t) task->simdata)->sender;
109 }
110
111 /** \ingroup m_task_management
112  * \brief Return the source of a #m_task_t.
113  *
114  * This functions returns the #m_host_t from which this task was sent
115  */
116 m_host_t MSG_task_get_source(m_task_t task)
117 {
118   xbt_assert0(task, "Invalid parameters");
119   return ((simdata_task_t) task->simdata)->source;
120 }
121
122 /** \ingroup m_task_management
123  * \brief Return the name of a #m_task_t.
124  *
125  * This functions returns the name of a #m_task_t as specified on creation
126  */
127 const char *MSG_task_get_name(m_task_t task)
128 {
129   xbt_assert0(task, "Invalid parameters");
130   return task->name;
131 }
132
133
134 /** \ingroup m_task_management
135  * \brief Destroy a #m_task_t.
136  *
137  * Destructor for #m_task_t. Note that you should free user data, if any, \b 
138    before calling this function.
139  */
140 MSG_error_t MSG_task_destroy(m_task_t task)
141 {
142   smx_action_t action = NULL;
143   xbt_assert0((task != NULL), "Invalid parameter");
144
145   /* why? if somebody is using, then you can't free! ok... but will return MSG_OK? when this task will be destroyed? isn't the user code wrong? */
146   task->simdata->refcount--;
147   if (task->simdata->refcount > 0)
148     return MSG_OK;
149
150   if (task->name)
151     free(task->name);
152
153   SIMIX_cond_destroy(task->simdata->cond);
154   SIMIX_mutex_destroy(task->simdata->mutex);
155
156   action = task->simdata->compute;
157   if (action)
158     SIMIX_action_destroy(action);
159   
160   /* parallel tasks only */
161   if (task->simdata->host_list)
162     xbt_free(task->simdata->host_list);
163
164   /* free main structures */
165   xbt_free(task->simdata);
166   xbt_free(task);
167
168   return MSG_OK;
169 }
170
171
172 /** \ingroup m_task_management
173  * \brief Cancel a #m_task_t.
174  * \param task the taskt to cancel. If it was executed or transfered, it 
175           stops the process that were working on it.
176  */
177 MSG_error_t MSG_task_cancel(m_task_t task)
178 {
179   xbt_assert0((task != NULL), "Invalid parameter");
180
181   if (task->simdata->compute) {
182     SIMIX_action_cancel(task->simdata->compute);
183     return MSG_OK;
184   }
185   if (task->simdata->comm) {
186     SIMIX_communication_cancel(task->simdata->comm);
187     return MSG_OK;
188   }
189
190   return MSG_FATAL;
191 }
192
193 /** \ingroup m_task_management
194  * \brief Returns the computation amount needed to process a task #m_task_t.
195  *        Once a task has been processed, this amount is thus set to 0...
196  */
197 double MSG_task_get_compute_duration(m_task_t task)
198 {
199   xbt_assert0((task != NULL)
200               && (task->simdata != NULL), "Invalid parameter");
201
202   return task->simdata->computation_amount;
203 }
204
205 /** \ingroup m_task_management
206  * \brief Returns the remaining computation amount of a task #m_task_t.
207  *
208  */
209 double MSG_task_get_remaining_computation(m_task_t task)
210 {
211   xbt_assert0((task != NULL)
212               && (task->simdata != NULL), "Invalid parameter");
213
214   if (task->simdata->compute) {
215     return SIMIX_action_get_remains(task->simdata->compute);
216   } else {
217     return task->simdata->computation_amount;
218   }
219 }
220
221
222
223 /** \ingroup m_task_management
224  * \brief Returns the total amount received by a task #m_task_t.
225  *
226  */
227 double MSG_task_get_remaining_communication(m_task_t task)
228 {
229   xbt_assert0((task != NULL)
230               && (task->simdata != NULL), "Invalid parameter");
231
232   return SIMIX_communication_get_remains(task->simdata->comm);
233 }
234
235 /** \ingroup m_task_management
236  * \brief Returns the size of the data attached to a task #m_task_t.
237  *
238  */
239 double MSG_task_get_data_size(m_task_t task)
240 {
241   xbt_assert0((task != NULL)
242               && (task->simdata != NULL), "Invalid parameter");
243
244   return task->simdata->message_size;
245 }
246
247
248
249 /** \ingroup m_task_management
250  * \brief Changes the priority of a computation task. This priority doesn't affect 
251  *        the transfer rate. A priority of 2 will make a task receive two times more
252  *        cpu power than the other ones.
253  *
254  */
255 void MSG_task_set_priority(m_task_t task, double priority)
256 {
257   xbt_assert0((task != NULL)
258               && (task->simdata != NULL), "Invalid parameter");
259
260   task->simdata->priority = 1 / priority;
261   if (task->simdata->compute)
262     SIMIX_action_set_priority(task->simdata->compute,
263                               task->simdata->priority);
264 }