Logo AND Algorithmique Numérique Distribuée

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