Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add MSG_task_has_data function
[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 /********************************* 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->computation_amount = compute_duration;
61   simdata->message_size = message_size;
62   simdata->rate = -1.0;
63   simdata->priority = 1.0;
64   simdata->refcount = 1;
65   simdata->sender = NULL;
66   simdata->receiver = NULL;
67   simdata->cond = SIMIX_cond_init();
68   simdata->mutex = SIMIX_mutex_init();
69   simdata->compute = NULL;
70   simdata->comm = NULL;
71
72   simdata->host_list = NULL;
73   simdata->comp_amount = NULL;
74   simdata->comm_amount = NULL;
75
76   return task;
77 }
78
79 /** prevent the task from being destroyed too quickly (but also prevent it from being sent). Mainly useful in bindings */
80 void MSG_task_ref(m_task_t t) {
81   t->simdata->refcount++;
82 }
83
84 /** \ingroup m_task_management
85  * \brief Return the user data of a #m_task_t.
86  *
87  * This function checks whether \a task is a valid pointer or not and return
88    the user data associated to \a task if it is possible.
89  */
90 void *MSG_task_get_data(m_task_t task)
91 {
92   xbt_assert0((task != NULL), "Invalid parameter");
93
94   return (task->data);
95 }
96
97 /** \ingroup m_task_management
98  * \brief Sets the user data of a #m_task_t.
99  *
100  * This function allows to associate a new pointer to
101    the user data associated of \a task.
102  */
103 void MSG_task_set_data(m_task_t task,void *data)
104 {
105   xbt_assert0((task != NULL), "Invalid parameter");
106
107   task->data = data;
108 }
109
110 /** \ingroup m_task_management
111  * \brief Return the sender of a #m_task_t.
112  *
113  * This functions returns the #m_process_t which sent this task
114  */
115 m_process_t MSG_task_get_sender(m_task_t task)
116 {
117   xbt_assert0(task, "Invalid parameters");
118   return ((simdata_task_t) task->simdata)->sender;
119 }
120
121 /** \ingroup m_task_management
122  * \brief Return the source of a #m_task_t.
123  *
124  * This functions returns the #m_host_t from which this task was sent
125  */
126 m_host_t MSG_task_get_source(m_task_t task)
127 {
128   xbt_assert0(task, "Invalid parameters");
129   return ((simdata_task_t) task->simdata)->source;
130 }
131
132 /** \ingroup m_task_management
133  * \brief Return the name of a #m_task_t.
134  *
135  * This functions returns the name of a #m_task_t as specified on creation
136  */
137 const char *MSG_task_get_name(m_task_t task)
138 {
139   xbt_assert0(task, "Invalid parameters");
140   return task->name;
141 }
142
143
144 /** \ingroup m_task_management
145  * \brief Destroy a #m_task_t.
146  *
147  * Destructor for #m_task_t. Note that you should free user data, if any, \b 
148    before calling this function.
149  */
150 MSG_error_t MSG_task_destroy(m_task_t task)
151 {
152   smx_action_t action = NULL;
153   xbt_assert0((task != NULL), "Invalid parameter");
154
155   /* 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? */
156   task->simdata->refcount--;
157   if (task->simdata->refcount > 0)
158     return MSG_OK;
159
160   if (task->name)
161     free(task->name);
162
163   SIMIX_cond_destroy(task->simdata->cond);
164   SIMIX_mutex_destroy(task->simdata->mutex);
165
166   action = task->simdata->compute;
167   if (action)
168     SIMIX_action_destroy(action);
169   
170   /* parallel tasks only */
171   if (task->simdata->host_list)
172     xbt_free(task->simdata->host_list);
173
174   /* free main structures */
175   xbt_free(task->simdata);
176   xbt_free(task);
177
178   return MSG_OK;
179 }
180
181
182 /** \ingroup m_task_management
183  * \brief Cancel a #m_task_t.
184  * \param task the taskt to cancel. If it was executed or transfered, it 
185           stops the process that were working on it.
186  */
187 MSG_error_t MSG_task_cancel(m_task_t task)
188 {
189   xbt_assert0((task != NULL), "Invalid parameter");
190
191   if (task->simdata->compute) {
192     SIMIX_action_cancel(task->simdata->compute);
193     return MSG_OK;
194   }
195   if (task->simdata->comm) {
196     SIMIX_communication_cancel(task->simdata->comm);
197     return MSG_OK;
198   }
199   THROW_IMPOSSIBLE;
200 }
201
202 /** \ingroup m_task_management
203  * \brief Returns the computation amount needed to process a task #m_task_t.
204  *        Once a task has been processed, this amount is thus set to 0...
205  */
206 double MSG_task_get_compute_duration(m_task_t task)
207 {
208   xbt_assert0((task != NULL)
209               && (task->simdata != NULL), "Invalid parameter");
210
211   return task->simdata->computation_amount;
212 }
213
214 /** \ingroup m_task_management
215  * \brief Returns the remaining computation amount of a task #m_task_t.
216  *
217  */
218 double MSG_task_get_remaining_computation(m_task_t task)
219 {
220   xbt_assert0((task != NULL)
221               && (task->simdata != NULL), "Invalid parameter");
222
223   if (task->simdata->compute) {
224     return SIMIX_action_get_remains(task->simdata->compute);
225   } else {
226     return task->simdata->computation_amount;
227   }
228 }
229
230
231
232 /** \ingroup m_task_management
233  * \brief Returns the total amount received by a task #m_task_t.
234  *
235  */
236 double MSG_task_get_remaining_communication(m_task_t task)
237 {
238   xbt_assert0((task != NULL)
239               && (task->simdata != NULL), "Invalid parameter");
240
241   return SIMIX_communication_get_remains(task->simdata->comm);
242 }
243
244 /** \ingroup m_task_management
245  * \brief Returns the size of the data attached to a task #m_task_t.
246  *
247  */
248 double MSG_task_get_data_size(m_task_t task)
249 {
250   xbt_assert0((task != NULL)
251               && (task->simdata != NULL), "Invalid parameter");
252
253   return task->simdata->message_size;
254 }
255
256
257
258 /** \ingroup m_task_management
259  * \brief Changes the priority of a computation task. This priority doesn't affect 
260  *        the transfer rate. A priority of 2 will make a task receive two times more
261  *        cpu power than the other ones.
262  *
263  */
264 void MSG_task_set_priority(m_task_t task, double priority)
265 {
266   xbt_assert0((task != NULL)
267               && (task->simdata != NULL), "Invalid parameter");
268
269   task->simdata->priority = 1 / priority;
270   if (task->simdata->compute)
271     SIMIX_action_set_priority(task->simdata->compute,
272                               task->simdata->priority);
273 }
274
275
276 /** \ingroup m_task_management
277  * \brief Sets the user data of a #m_task_t.
278  *
279  * This function allows to test if a task contains a not_null data
280  * return 1 (if true)
281  */
282 int MSG_task_has_data(m_task_t task)
283 {
284
285  return (task->data != NULL);
286
287 }
288