Logo AND Algorithmique Numérique Distribuée

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