Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e8d184a7a0851aa4623815452f0919e1efcc1327
[simgrid.git] / src / simix / smx_host.c
1 /* Copyright (c) 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 "private.h"
8 #include "xbt/sysdep.h"
9 #include "xbt/log.h"
10 #include "xbt/dict.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_host, simix,
13                                 "Logging specific to SIMIX (hosts)");
14
15
16 static void SIMIX_execution_finish(smx_action_t action);
17
18 /**
19  * \brief Internal function to create a SIMIX host.
20  * \param name name of the host to create
21  * \param workstation the SURF workstation to encapsulate
22  * \param data some user data (may be NULL)
23  */
24 smx_host_t SIMIX_host_create(const char *name,
25                                void *workstation, void *data)
26 {
27   smx_host_t smx_host = xbt_new0(s_smx_host_t, 1);
28   s_smx_process_t proc;
29
30   /* Host structure */
31   smx_host->name = xbt_strdup(name);
32   smx_host->data = data;
33   smx_host->host = workstation;
34   smx_host->process_list =
35       xbt_swag_new(xbt_swag_offset(proc, host_proc_hookup));
36
37   /* Update global variables */
38   xbt_dict_set(simix_global->host, smx_host->name, smx_host,
39                &SIMIX_host_destroy);
40
41   return smx_host;
42 }
43
44 /**
45  * \brief Internal function to destroy a SIMIX host.
46  *
47  * \param h the host to destroy (a smx_host_t)
48  */
49 void SIMIX_host_destroy(void *h)
50 {
51   smx_host_t host = (smx_host_t) h;
52
53   xbt_assert0((host != NULL), "Invalid parameters");
54
55   /* Clean Simulator data */
56   if (xbt_swag_size(host->process_list) != 0) {
57     char *msg =
58         bprintf("Shutting down host %s, but it's not empty:", host->name);
59     char *tmp;
60     smx_process_t process = NULL;
61
62     xbt_swag_foreach(process, host->process_list) {
63       tmp = bprintf("%s\n\t%s", msg, process->name);
64       free(msg);
65       msg = tmp;
66     }
67     SIMIX_display_process_status();
68     THROW1(arg_error, 0, "%s", msg);
69   }
70
71   xbt_swag_free(host->process_list);
72
73   /* Clean host structure */
74   free(host->name);
75   free(host);
76
77   return;
78 }
79
80 /**
81  * \brief Returns a dict of all hosts.
82  *
83  * \return List of all hosts (as a #xbt_dict_t)
84  */
85 xbt_dict_t SIMIX_host_get_dict(void)
86 {
87   return simix_global->host;
88 }
89
90 smx_host_t SIMIX_host_get_by_name(const char *name)
91 {
92   xbt_assert0(((simix_global != NULL)
93                && (simix_global->host != NULL)),
94               "Environment not set yet");
95
96   return xbt_dict_get_or_null(simix_global->host, name);
97 }
98
99 smx_host_t SIMIX_host_self(void)
100 {
101   smx_process_t process = SIMIX_process_self();
102   return (process == NULL) ? NULL : SIMIX_process_get_host(process);
103 }
104
105 /* needs to be public and without request because it is called
106    by exceptions and logging events */
107 const char* SIMIX_host_self_get_name(void)
108 {
109   smx_host_t host = SIMIX_host_self();
110   if (host == NULL || SIMIX_process_self() == simix_global->maestro_process)
111     return "";
112
113   return SIMIX_host_get_name(host);
114 }
115
116 const char* SIMIX_host_get_name(smx_host_t host)
117 {
118   xbt_assert0((host != NULL), "Invalid parameters");
119
120   return host->name;
121 }
122
123 xbt_dict_t SIMIX_host_get_properties(smx_host_t host)
124 {
125   xbt_assert0((host != NULL), "Invalid parameters (simix host is NULL)");
126
127   return surf_workstation_model->extension.workstation.get_properties(host->host);
128 }
129
130 double SIMIX_host_get_speed(smx_host_t host)
131 {
132   xbt_assert0((host != NULL), "Invalid parameters (simix host is NULL)");
133
134   return surf_workstation_model->extension.workstation.
135       get_speed(host->host, 1.0);
136 }
137
138 double SIMIX_host_get_available_speed(smx_host_t host)
139 {
140   xbt_assert0((host != NULL), "Invalid parameters (simix host is NULL)");
141
142   return surf_workstation_model->extension.workstation.
143       get_available_speed(host->host);
144 }
145
146 int SIMIX_host_get_state(smx_host_t host)
147 {
148   xbt_assert0((host != NULL), "Invalid parameters (simix host is NULL)");
149
150   return surf_workstation_model->extension.workstation.
151       get_state(host->host);
152 }
153
154 void* SIMIX_host_self_get_data(void)
155 {
156   return SIMIX_host_get_data(SIMIX_host_self());
157 }
158
159 void SIMIX_host_self_set_data(void *data)
160 {
161   SIMIX_host_set_data(SIMIX_host_self(), data);
162 }
163
164 void* SIMIX_host_get_data(smx_host_t host)
165 {
166   xbt_assert0((host != NULL), "Invalid parameters (simix host is NULL)");
167
168   return host->data;
169 }
170
171 void SIMIX_host_set_data(smx_host_t host, void *data)
172 {
173   xbt_assert0((host != NULL), "Invalid parameters");
174   xbt_assert0((host->data == NULL), "Data already set");
175
176   host->data = data;
177 }
178
179 smx_action_t SIMIX_host_execute(const char *name, smx_host_t host,
180                                 double computation_amount)
181 {
182   /* alloc structures and initialize */
183   smx_action_t action = xbt_new0(s_smx_action_t, 1);
184   action->type = SIMIX_ACTION_EXECUTE;
185   action->name = xbt_strdup(name);
186   action->request_list = xbt_fifo_new();
187   action->state = SIMIX_RUNNING;
188   action->execution.host = host;
189   
190 #ifdef HAVE_TRACING
191   action->category = NULL;
192 #endif
193
194 #ifdef HAVE_MC
195   /* set surf's action */
196   if(!_surf_do_model_check)
197 #endif
198   {
199   action->execution.surf_exec =
200     surf_workstation_model->extension.workstation.execute(host->host, 
201                                                           computation_amount);
202   surf_workstation_model->action_data_set(action->execution.surf_exec, action);
203   }
204   
205 #ifdef HAVE_TRACING
206   TRACE_smx_host_execute(action);
207   TRACE_surf_action(action->execution.surf_exec, action->category);
208 #endif
209
210   DEBUG1("Create execute action %p", action);
211   
212   return action;
213 }
214
215 smx_action_t SIMIX_host_parallel_execute( const char *name,
216     int host_nb, smx_host_t *host_list,
217     double *computation_amount, double *communication_amount,
218     double amount, double rate)
219 {
220   void **workstation_list = NULL;
221   int i;
222
223   /* alloc structures and initialize */
224   smx_action_t action = xbt_new0(s_smx_action_t, 1);
225   action->type = SIMIX_ACTION_PARALLEL_EXECUTE;
226   action->name = xbt_strdup(name);
227   action->request_list = xbt_fifo_new();
228   action->state = SIMIX_RUNNING;
229   action->execution.host = NULL; /* FIXME: do we need the list of hosts? */
230  
231 #ifdef HAVE_TRACING
232   action->category = NULL;
233 #endif
234
235   /* set surf's action */
236   workstation_list = xbt_new0(void *, host_nb);
237   for (i = 0; i < host_nb; i++)
238     workstation_list[i] = host_list[i]->host;
239
240 #ifdef HAVE_MC
241   /* set surf's action */
242   if(!_surf_do_model_check)
243 #endif  
244   {
245   action->execution.surf_exec = 
246     surf_workstation_model->extension.workstation.
247     execute_parallel_task(host_nb, workstation_list, computation_amount,
248                           communication_amount, amount, rate);
249
250   surf_workstation_model->action_data_set(action->execution.surf_exec, action);
251   }
252   DEBUG1("Create parallel execute action %p", action);
253
254   return action;
255 }
256
257 void SIMIX_host_execution_destroy(smx_action_t action)
258 {
259   DEBUG1("Destroy action %p", action);
260
261   if (action->name)
262     xbt_free(action->name);
263
264   xbt_fifo_free(action->request_list);
265
266   if (action->execution.surf_exec){
267     surf_workstation_model->action_unref(action->execution.surf_exec);
268     action->execution.surf_exec = NULL;
269   }
270   
271 #ifdef HAVE_TRACING
272   TRACE_smx_action_destroy(action);
273 #endif
274   xbt_free(action);
275 }
276
277 void SIMIX_host_execution_cancel(smx_action_t action)
278 {
279   DEBUG1("Cancel action %p", action);
280
281   if(action->execution.surf_exec) 
282     surf_workstation_model->action_cancel(action->execution.surf_exec);
283 }
284
285 double SIMIX_host_execution_get_remains(smx_action_t action)
286 {
287   double result = 0;
288   
289   if(action->state == SIMIX_RUNNING)
290     result = surf_workstation_model->get_remains(action->execution.surf_exec);
291
292   return result;
293 }
294
295 e_smx_state_t SIMIX_host_execution_get_state(smx_action_t action)
296 {
297   return action->state;
298 }
299
300 void SIMIX_host_execution_set_priority(smx_action_t action, double priority)
301 {
302   surf_workstation_model->set_priority(action->execution.surf_exec, priority);
303 }
304
305 void SIMIX_pre_host_execution_wait(smx_req_t req)
306 {
307   smx_action_t action = req->host_execution_wait.execution;
308
309   DEBUG2("Wait for execution of action %p, state %d", action, action->state);
310
311   /* Associate this request to the action */
312   xbt_fifo_push(action->request_list, req);
313   req->issuer->waiting_action = action;
314
315 #ifdef HAVE_MC
316   /* set surf's action */
317   if(_surf_do_model_check){
318     action->state = SIMIX_DONE;
319     SIMIX_execution_finish(action);
320   }
321 #endif  
322     
323   /* If the action is already finished then perform the error handling */
324   if (action->state != SIMIX_RUNNING)
325     SIMIX_execution_finish(action);
326 }
327
328 void SIMIX_host_execution_suspend(smx_action_t action)
329 {
330     surf_workstation_model->suspend(action->execution.surf_exec);
331 }
332
333 void SIMIX_host_execution_resume(smx_action_t action)
334 {
335     surf_workstation_model->suspend(action->execution.surf_exec);
336 }
337
338 void SIMIX_execution_finish(smx_action_t action)
339 {
340   xbt_fifo_item_t item;
341   smx_req_t req;
342
343   xbt_fifo_foreach(action->request_list, item, req, smx_req_t) {
344
345     switch (action->state) {
346
347       case SIMIX_DONE:
348         /* do nothing, action done*/
349         DEBUG0("SIMIX_execution_finished: execution successful");
350         break;
351         
352       case SIMIX_FAILED:
353         TRY {
354           DEBUG1("SIMIX_execution_finished: host '%s' failed", req->issuer->smx_host->name);
355           THROW0(host_error, 0, "Host failed");
356         }
357         CATCH(req->issuer->running_ctx->exception) {
358           req->issuer->doexception = 1;
359         }
360       break;
361         
362       case SIMIX_CANCELED:
363         TRY {
364           DEBUG0("SIMIX_execution_finished: execution canceled");
365           THROW0(cancel_error, 0, "Canceled");
366         }
367         CATCH(req->issuer->running_ctx->exception) {
368           req->issuer->doexception = 1;
369         }
370         break;
371         
372       default:
373         THROW_IMPOSSIBLE;
374     }
375     req->issuer->waiting_action = NULL;
376     SIMIX_request_answer(req);
377   }
378 }
379
380 void SIMIX_post_host_execute(smx_action_t action)
381 {
382   /* FIXME: check if the host running the action failed or not*/
383   /*if(surf_workstation_model->extension.workstation.get_state(action->host->host))*/
384
385   /* If the host running the action didn't fail, then the action was cancelled */
386   if (surf_workstation_model->action_state_get(action->execution.surf_exec) == SURF_ACTION_FAILED)
387      action->state = SIMIX_CANCELED;
388   else
389      action->state = SIMIX_DONE;
390
391   if (action->execution.surf_exec){
392     surf_workstation_model->action_unref(action->execution.surf_exec);
393     action->execution.surf_exec = NULL;
394   }
395   
396   /* If there are requests associated with the action, then answer them */
397   if (xbt_fifo_size(action->request_list))
398     SIMIX_execution_finish(action);
399 }
400