Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
merge conflict resolved
[simgrid.git] / src / msg / msg_task.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "msg_private.h"
8 #include "xbt/sysdep.h"
9 #include "xbt/log.h"
10
11 /** \defgroup m_task_management Managing functions of Tasks
12  *  \brief This section describes the task structure of MSG
13  *  (#m_task_t) and the functions for managing it.
14  */
15 /** @addtogroup m_task_management
16  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Tasks" --> \endhtmlonly
17  * 
18  *  Since most scheduling algorithms rely on a concept of task
19  *  that can be either <em>computed</em> locally or
20  *  <em>transferred</em> on another processor, it seems to be the
21  *  right level of abstraction for our purposes. A <em>task</em>
22  *  may then be defined by a <em>computing amount</em>, a
23  *  <em>message size</em> and some <em>private data</em>.
24  */
25
26 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_task, msg,
27                                 "Logging specific to MSG (task)");
28
29 /********************************* Task **************************************/
30 /** \ingroup m_task_management
31  * \brief Creates a new #m_task_t.
32  *
33  * A constructor for #m_task_t taking four arguments and returning the 
34    corresponding object.
35  * \param name a name for the object. It is for user-level information
36    and can be NULL.
37  * \param compute_duration a value of the processing amount (in flop)
38    needed to process this new task. If 0, then it cannot be executed with
39    MSG_task_execute(). This value has to be >=0.
40  * \param message_size a value of the amount of data (in bytes) needed to
41    transfer this new task. If 0, then it cannot be transfered with
42    MSG_task_get() and MSG_task_put(). This value has to be >=0.
43  * \param data a pointer to any data may want to attach to the new
44    object.  It is for user-level information and can be NULL. It can
45    be retrieved with the function \ref MSG_task_get_data.
46  * \see m_task_t
47  * \return The new corresponding object.
48  */
49 m_task_t MSG_task_create(const char *name, double compute_duration,
50                          double message_size, void *data)
51 {
52   m_task_t task = xbt_new(s_m_task_t, 1);
53   simdata_task_t simdata = xbt_new(s_simdata_task_t, 1);
54   task->simdata = simdata;
55   /* Task structure */
56   task->name = xbt_strdup(name);
57   task->data = data;
58
59   /* Simulator Data */
60   simdata->host_nb = 0;
61   simdata->computation_amount = compute_duration;
62   simdata->message_size = message_size;
63   simdata->rate = -1.0;
64   simdata->priority = 1.0;
65   simdata->isused = 0;
66   simdata->sender = NULL;
67   simdata->receiver = NULL;
68   simdata->compute = NULL;
69   simdata->comm = NULL;
70
71   simdata->host_list = NULL;
72   simdata->comp_amount = NULL;
73   simdata->comm_amount = NULL;
74 #ifdef HAVE_TRACING
75   TRACE_msg_task_create(task);
76 #endif
77
78   return task;
79 }
80
81 /** \ingroup m_task_management
82  * \brief Return the user data of a #m_task_t.
83  *
84  * This function checks whether \a task is a valid pointer or not and return
85    the user data associated to \a task if it is possible.
86  */
87 void *MSG_task_get_data(m_task_t task)
88 {
89   xbt_assert((task != NULL), "Invalid parameter");
90
91   return (task->data);
92 }
93
94 /** \ingroup m_task_management
95  * \brief Sets the user data of a #m_task_t.
96  *
97  * This function allows to associate a new pointer to
98    the user data associated of \a task.
99  */
100 void MSG_task_set_data(m_task_t task, void *data)
101 {
102   xbt_assert((task != NULL), "Invalid parameter");
103
104   task->data = data;
105 }
106
107 /** \ingroup m_task_management
108  * \brief Sets a function to be called when a task has just been copied.
109  * \param callback a callback function
110  */
111 void MSG_task_set_copy_callback(void (*callback)
112     (m_task_t task, m_process_t sender, m_process_t receiver)) {
113
114   msg_global->task_copy_callback = callback;
115
116   if (callback) {
117     SIMIX_comm_set_copy_data_callback(MSG_comm_copy_data_from_SIMIX);
118   }
119   else {
120     SIMIX_comm_set_copy_data_callback(SIMIX_comm_copy_pointer_callback);
121   }
122 }
123
124 /** \ingroup m_task_management
125  * \brief Return the sender of a #m_task_t.
126  *
127  * This functions returns the #m_process_t which sent this task
128  */
129 m_process_t MSG_task_get_sender(m_task_t task)
130 {
131   xbt_assert(task, "Invalid parameters");
132   return ((simdata_task_t) task->simdata)->sender;
133 }
134
135 /** \ingroup m_task_management
136  * \brief Return the source of a #m_task_t.
137  *
138  * This functions returns the #m_host_t from which this task was sent
139  */
140 m_host_t MSG_task_get_source(m_task_t task)
141 {
142   xbt_assert(task, "Invalid parameters");
143   return ((simdata_task_t) task->simdata)->source;
144 }
145
146 /** \ingroup m_task_management
147  * \brief Return the name of a #m_task_t.
148  *
149  * This functions returns the name of a #m_task_t as specified on creation
150  */
151 const char *MSG_task_get_name(m_task_t task)
152 {
153   xbt_assert(task, "Invalid parameters");
154   return task->name;
155 }
156
157 /** \ingroup m_task_management
158  * \brief Return the name of a #m_task_t.
159  *
160  * This functions allows to associate a name to a task
161  */
162 void MSG_task_set_name(m_task_t task, const char *name)
163 {
164   xbt_assert(task, "Invalid parameters");
165   task->name = xbt_strdup(name);
166 }
167
168 /** \ingroup m_task_management
169  * \brief Destroy a #m_task_t.
170  *
171  * Destructor for #m_task_t. Note that you should free user data, if any, \b 
172  * before calling this function.
173  *
174  * Only the process that owns the task can destroy it.
175  * The owner changes after a successful send.
176  * If a task is successfully sent, the receiver becomes the owner and is
177  * supposed to destroy it. The sender should not use it anymore.
178  * If the task failed to be sent, the sender remains the owner of the task.
179  */
180 MSG_error_t MSG_task_destroy(m_task_t task)
181 {
182   smx_action_t action = NULL;
183   xbt_assert((task != NULL), "Invalid parameter");
184
185   if (task->simdata->isused) {
186     /* the task is being sent or executed: cancel it first */
187     MSG_task_cancel(task);
188   }
189 #ifdef HAVE_TRACING
190   TRACE_msg_task_destroy(task);
191 #endif
192
193   xbt_free(task->name);
194
195   action = task->simdata->compute;
196   if (action)
197     simcall_host_execution_destroy(action);
198
199   /* parallel tasks only */
200   xbt_free(task->simdata->host_list);
201
202   /* free main structures */
203   xbt_free(task->simdata);
204   xbt_free(task);
205
206   return MSG_OK;
207 }
208
209
210 /** \ingroup m_task_management
211  * \brief Cancel a #m_task_t.
212  * \param task the task to cancel. If it was executed or transfered, it
213           stops the process that were working on it.
214  */
215 MSG_error_t MSG_task_cancel(m_task_t task)
216 {
217   xbt_assert((task != NULL), "Invalid parameter");
218
219   if (task->simdata->compute) {
220     simcall_host_execution_cancel(task->simdata->compute);
221   }
222   else if (task->simdata->comm) {
223     simcall_comm_cancel(task->simdata->comm);
224     task->simdata->isused = 0;
225   }
226   return MSG_OK;
227 }
228
229 /** \ingroup m_task_management
230  * \brief Returns the computation amount needed to process a task #m_task_t.
231  *        Once a task has been processed, this amount is thus set to 0...
232  */
233 double MSG_task_get_compute_duration(m_task_t task)
234 {
235   xbt_assert((task != NULL)
236               && (task->simdata != NULL), "Invalid parameter");
237
238   return task->simdata->computation_amount;
239 }
240
241
242 /** \ingroup m_task_management
243  * \brief set the computation amount needed to process a task #m_task_t.
244  */
245
246 void MSG_task_set_compute_duration(m_task_t task,
247                                    double computation_amount)
248 {
249   xbt_assert(task, "Invalid parameter");
250   task->simdata->computation_amount = computation_amount;
251
252 }
253
254 /** \ingroup m_task_management
255  * \brief Returns the remaining computation amount of a task #m_task_t.
256  *
257  */
258 double MSG_task_get_remaining_computation(m_task_t task)
259 {
260   xbt_assert((task != NULL)
261               && (task->simdata != NULL), "Invalid parameter");
262
263   if (task->simdata->compute) {
264     return simcall_host_execution_get_remains(task->simdata->compute);
265   } else {
266     return task->simdata->computation_amount;
267   }
268 }
269
270 /** \ingroup m_task_management
271  * \brief Returns the total amount received by a task #m_task_t.
272  *        If the communication does not exist it will return 0.
273  *        So, if the communication has FINISHED or FAILED it returns
274  *        zero.
275  */
276 double MSG_task_get_remaining_communication(m_task_t task)
277 {
278   xbt_assert((task != NULL)
279               && (task->simdata != NULL), "Invalid parameter");
280   XBT_DEBUG("calling simcall_communication_get_remains(%p)",
281          task->simdata->comm);
282   return simcall_comm_get_remains(task->simdata->comm);
283 }
284
285 #ifdef HAVE_LATENCY_BOUND_TRACKING
286 /** \ingroup m_task_management
287  * \brief Return 1 if communication task is limited by latency, 0 otherwise
288  *
289  */
290 int MSG_task_is_latency_bounded(m_task_t task)
291 {
292   xbt_assert((task != NULL)
293               && (task->simdata != NULL), "Invalid parameter");
294   XBT_DEBUG("calling simcall_communication_is_latency_bounded(%p)",
295          task->simdata->comm);
296   return simcall_comm_is_latency_bounded(task->simdata->comm);
297 }
298 #endif
299
300 /** \ingroup m_task_management
301  * \brief Returns the size of the data attached to a task #m_task_t.
302  *
303  */
304 double MSG_task_get_data_size(m_task_t task)
305 {
306   xbt_assert((task != NULL)
307               && (task->simdata != NULL), "Invalid parameter");
308
309   return task->simdata->message_size;
310 }
311
312
313
314 /** \ingroup m_task_management
315  * \brief Changes the priority of a computation task. This priority doesn't affect 
316  *        the transfer rate. A priority of 2 will make a task receive two times more
317  *        cpu power than the other ones.
318  *
319  */
320 void MSG_task_set_priority(m_task_t task, double priority)
321 {
322   xbt_assert((task != NULL)
323               && (task->simdata != NULL), "Invalid parameter");
324
325   task->simdata->priority = 1 / priority;
326   if (task->simdata->compute)
327     simcall_host_execution_set_priority(task->simdata->compute,
328                                       task->simdata->priority);
329 }