Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
67db7d9d9141036324d5d8b1069ff9c666c2ac2c
[simgrid.git] / src / mc / mc_request.c
1 /* Copyright (c) 2008-2013 Da SimGrid Team. All rights reserved.            */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "mc_private.h"
7
8 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
9                                 "Logging specific to MC (request)");
10
11 static char* pointer_to_string(void* pointer);
12 static char* buff_size_to_string(size_t size);
13
14 int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2) {
15   if(mc_reduce_kind == e_mc_reduce_none)
16     return TRUE;
17
18   if (r1->issuer == r2->issuer)
19       return FALSE;
20
21   if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
22     return FALSE;
23
24   if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
25     return FALSE;
26
27   if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
28         &&  r2->call == SIMCALL_COMM_WAIT){
29
30     if(simcall_comm_wait__get__comm(r2)->comm.rdv == NULL)
31       return FALSE;
32
33     smx_rdv_t rdv = r1->call == SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) : simcall_comm_irecv__get__rdv(r1);
34
35     if((simcall_comm_wait__get__comm(r2)->comm.rdv != rdv) && (simcall_comm_wait__get__timeout(r2) <= 0))
36       return FALSE;
37
38     if((simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND) && (r1->call == SIMCALL_COMM_ISEND) && (simcall_comm_wait__get__timeout(r2) <= 0))
39       return FALSE;
40
41     if((simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE) && (r1->call == SIMCALL_COMM_IRECV) && (simcall_comm_wait__get__timeout(r2) <= 0))
42       return FALSE;
43   }
44
45   if(   (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
46         &&  r1->call == SIMCALL_COMM_WAIT){
47
48     if(simcall_comm_wait__get__comm(r1)->comm.rdv != NULL)
49       return FALSE;
50
51     smx_rdv_t rdv = r2->call == SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) : simcall_comm_irecv__get__rdv(r2);
52
53     if((simcall_comm_wait__get__comm(r1)->comm.rdv != rdv) && (simcall_comm_wait__get__timeout(r1) <= 0))
54       return FALSE;
55
56     if((simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND) && (r2->call == SIMCALL_COMM_ISEND) && (simcall_comm_wait__get__timeout(r1) <= 0))
57       return FALSE;
58
59     if((simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE) && (r2->call == SIMCALL_COMM_IRECV) && (simcall_comm_wait__get__timeout(r1) <= 0))
60       return FALSE;
61   }
62
63   /* FIXME: the following rule assumes that the result of the
64    * isend/irecv call is not stored in a buffer used in the
65    * test call. */
66   /*if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
67         &&  r2->call == SIMCALL_COMM_TEST)
68         return FALSE;*/
69
70   /* FIXME: the following rule assumes that the result of the
71    * isend/irecv call is not stored in a buffer used in the
72    * test call.*/
73   /*if(   (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
74         && r1->call == SIMCALL_COMM_TEST)
75         return FALSE;*/
76
77   if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
78      && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
79     return FALSE;
80
81   if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
82      && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
83     return FALSE;
84
85   if(r1->call == SIMCALL_COMM_WAIT && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
86      && (simcall_comm_wait__get__comm(r1)->comm.src_proc == NULL
87          || simcall_comm_wait__get__comm(r1)->comm.dst_proc == NULL))
88     return FALSE;
89
90   if(r2->call == SIMCALL_COMM_WAIT && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
91      && (simcall_comm_wait__get__comm(r2)->comm.src_proc == NULL
92          || simcall_comm_wait__get__comm(r2)->comm.dst_proc == NULL))
93     return FALSE;
94
95   if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
96      && simcall_comm_wait__get__comm(r1)->comm.src_buff == simcall_comm_wait__get__comm(r2)->comm.src_buff
97      && simcall_comm_wait__get__comm(r1)->comm.dst_buff == simcall_comm_wait__get__comm(r2)->comm.dst_buff)
98     return FALSE;
99
100   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
101       && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
102       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
103       && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
104       && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
105       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != simcall_comm_wait__get__comm(r2)->comm.src_buff
106       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != simcall_comm_wait__get__comm(r2)->comm.dst_buff
107       && simcall_comm_wait__get__comm(r2)->comm.dst_buff != simcall_comm_wait__get__comm(r1)->comm.src_buff)
108     return FALSE;
109
110   if(r1->call == SIMCALL_COMM_TEST &&
111      (simcall_comm_test__get__comm(r1) == NULL
112       || simcall_comm_test__get__comm(r1)->comm.src_buff == NULL
113       || simcall_comm_test__get__comm(r1)->comm.dst_buff == NULL))
114     return FALSE;
115
116   if(r2->call == SIMCALL_COMM_TEST &&
117      (simcall_comm_test__get__comm(r2) == NULL
118       || simcall_comm_test__get__comm(r2)->comm.src_buff == NULL
119       || simcall_comm_test__get__comm(r2)->comm.dst_buff == NULL))
120     return FALSE;
121
122   if(r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
123      && simcall_comm_test__get__comm(r1)->comm.src_buff == simcall_comm_wait__get__comm(r2)->comm.src_buff
124      && simcall_comm_test__get__comm(r1)->comm.dst_buff == simcall_comm_wait__get__comm(r2)->comm.dst_buff)
125     return FALSE;
126
127   if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
128      && simcall_comm_wait__get__comm(r1)->comm.src_buff == simcall_comm_test__get__comm(r2)->comm.src_buff
129      && simcall_comm_wait__get__comm(r1)->comm.dst_buff == simcall_comm_test__get__comm(r2)->comm.dst_buff)
130     return FALSE;
131
132   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
133       && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
134       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
135       && simcall_comm_test__get__comm(r2)->comm.src_buff != NULL
136       && simcall_comm_test__get__comm(r2)->comm.dst_buff != NULL
137       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != simcall_comm_test__get__comm(r2)->comm.src_buff
138       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != simcall_comm_test__get__comm(r2)->comm.dst_buff
139       && simcall_comm_test__get__comm(r2)->comm.dst_buff != simcall_comm_wait__get__comm(r1)->comm.src_buff)
140     return FALSE;
141
142   if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
143       && simcall_comm_test__get__comm(r1)->comm.src_buff != NULL
144       && simcall_comm_test__get__comm(r1)->comm.dst_buff != NULL
145       && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
146       && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
147       && simcall_comm_test__get__comm(r1)->comm.dst_buff != simcall_comm_wait__get__comm(r2)->comm.src_buff
148       && simcall_comm_test__get__comm(r1)->comm.dst_buff != simcall_comm_wait__get__comm(r2)->comm.dst_buff
149       && simcall_comm_wait__get__comm(r2)->comm.dst_buff != simcall_comm_test__get__comm(r1)->comm.src_buff)
150     return FALSE;
151
152
153   return TRUE;
154 }
155
156 static char* pointer_to_string(void* pointer) {
157
158   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
159     return bprintf("%p", pointer);
160
161   return xbt_strdup("(verbose only)");
162 }
163
164 static char* buff_size_to_string(size_t buff_size) {
165
166   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
167     return bprintf("%zu", buff_size);
168
169   return xbt_strdup("(verbose only)");
170 }
171
172
173 char *MC_request_to_string(smx_simcall_t req, int value)
174 {
175   char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
176   smx_action_t act = NULL;
177   size_t size = 0;
178
179   switch(req->call){
180     case SIMCALL_COMM_ISEND:
181     type = xbt_strdup("iSend");
182     p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
183     bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
184     args = bprintf("src=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid, MSG_host_get_name(req->issuer->smx_host), req->issuer->name, p, bs);
185     break;
186   case SIMCALL_COMM_IRECV:
187     size = simcall_comm_irecv__get__dst_buff_size(req) ? *simcall_comm_irecv__get__dst_buff_size(req) : 0;
188     type = xbt_strdup("iRecv");
189     p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req)); 
190     bs = buff_size_to_string(size);
191     args = bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid, MSG_host_get_name(req->issuer->smx_host), req->issuer->name, p, bs);
192     break;
193   case SIMCALL_COMM_WAIT:
194     act = simcall_comm_wait__get__comm(req);
195     if(value == -1){
196       type = xbt_strdup("WaitTimeout");
197       p = pointer_to_string(act);
198       args = bprintf("comm=%s", p);
199     }else{
200       type = xbt_strdup("Wait");
201       p = pointer_to_string(act);
202       args  = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
203                       act->comm.src_proc ? act->comm.src_proc->pid : 0,
204                       act->comm.src_proc ? MSG_host_get_name(act->comm.src_proc->smx_host) : "",
205                       act->comm.src_proc ? act->comm.src_proc->name : "",
206                       act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
207                       act->comm.dst_proc ? MSG_host_get_name(act->comm.dst_proc->smx_host) : "",
208                       act->comm.dst_proc ? act->comm.dst_proc->name : "");
209     }
210     break;
211   case SIMCALL_COMM_TEST:
212     act = simcall_comm_test__get__comm(req);
213     if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL){
214       type = xbt_strdup("Test FALSE");
215       p = pointer_to_string(act);
216       args = bprintf("comm=%s", p);
217     }else{
218       type = xbt_strdup("Test TRUE");
219       p = pointer_to_string(act);
220       args  = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
221                       act->comm.src_proc->pid, act->comm.src_proc->name, MSG_host_get_name(act->comm.src_proc->smx_host),
222                       act->comm.dst_proc->pid, act->comm.dst_proc->name, MSG_host_get_name(act->comm.dst_proc->smx_host));
223     }
224     break;
225
226   case SIMCALL_COMM_WAITANY:
227     type = xbt_strdup("WaitAny");
228     p = pointer_to_string(xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value, smx_action_t));
229     args = bprintf("comm=%s (%d of %lu)", p,
230                    value+1, xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
231     break;
232
233   case SIMCALL_COMM_TESTANY:
234     if(value == -1){
235       type = xbt_strdup("TestAny FALSE");
236       args = xbt_strdup("-");
237     }else{
238       type = xbt_strdup("TestAny");
239       args = bprintf("(%d of %lu)", value+1, xbt_dynar_length(simcall_comm_testany__get__comms(req)));
240     }
241     break;
242
243   case SIMCALL_MC_SNAPSHOT:
244     type = xbt_strdup("MC_SNAPSHOT");
245     args = '\0';
246     break;
247
248   case SIMCALL_MC_COMPARE_SNAPSHOTS:
249     type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
250     args = '\0';
251     break;
252
253   case SIMCALL_MC_RANDOM:
254     type = xbt_strdup("MC_RANDOM");
255     args = bprintf("%d", value);
256     break;
257
258   default:
259     THROW_UNIMPLEMENTED;
260   }
261
262   if(args != NULL){
263     str = bprintf("[(%lu)%s (%s)] %s (%s)", req->issuer->pid , MSG_host_get_name(req->issuer->smx_host), req->issuer->name, type, args);
264     xbt_free(args);
265   }else{
266     str = bprintf("[(%lu)%s] %s ", req->issuer->pid ,req->issuer->name, type);
267   }
268   xbt_free(type);
269   xbt_free(p);
270   xbt_free(bs);
271   return str;
272 }
273
274 unsigned int MC_request_testany_fail(smx_simcall_t req)
275 {
276   unsigned int cursor;
277   smx_action_t action;
278
279   xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action){
280     if(action->comm.src_proc && action->comm.dst_proc)
281       return FALSE;
282   }
283
284   return TRUE;
285 }
286
287 int MC_request_is_visible(smx_simcall_t req)
288 {
289   return req->call == SIMCALL_COMM_ISEND
290     || req->call == SIMCALL_COMM_IRECV
291     || req->call == SIMCALL_COMM_WAIT
292     || req->call == SIMCALL_COMM_WAITANY
293     || req->call == SIMCALL_COMM_TEST
294     || req->call == SIMCALL_COMM_TESTANY
295     || req->call == SIMCALL_MC_RANDOM
296     || req->call == SIMCALL_MC_SNAPSHOT
297     || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS;
298 }
299
300 int MC_request_is_enabled(smx_simcall_t req)
301 {
302   unsigned int index = 0;
303   smx_action_t act;
304
305   switch (req->call) {
306
307   case SIMCALL_COMM_WAIT:
308     /* FIXME: check also that src and dst processes are not suspended */
309
310     /* If it has a timeout it will be always be enabled, because even if the
311      * communication is not ready, it can timeout and won't block.
312      * On the other hand if it hasn't a timeout, check if the comm is ready.*/
313     if(simcall_comm_wait__get__timeout(req) >= 0){
314       if(_sg_mc_timeout == 1){
315         return TRUE;
316       }else{
317         act = simcall_comm_wait__get__comm(req);
318         return (act->comm.src_proc && act->comm.dst_proc);
319       }
320     }else{
321       act = simcall_comm_wait__get__comm(req);
322       return (act->comm.src_proc && act->comm.dst_proc);
323     }
324     break;
325
326   case SIMCALL_COMM_WAITANY:
327     /* Check if it has at least one communication ready */
328     xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act) {
329       if (act->comm.src_proc && act->comm.dst_proc){
330         return TRUE;
331       }
332     }
333     return FALSE;
334     break;
335
336   default:
337     /* The rest of the request are always enabled */
338     return TRUE;
339   }
340 }
341
342 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
343 {
344   smx_action_t act;
345
346   switch (req->call) {
347
348   case SIMCALL_COMM_WAIT:
349     /* FIXME: check also that src and dst processes are not suspended */
350     act = simcall_comm_wait__get__comm(req);
351     return (act->comm.src_proc && act->comm.dst_proc);
352     break;
353
354   case SIMCALL_COMM_WAITANY:
355     act = xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx, smx_action_t);
356     return (act->comm.src_proc && act->comm.dst_proc);
357     break;
358
359   case SIMCALL_COMM_TESTANY:
360     act = xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx, smx_action_t);
361     return (act->comm.src_proc && act->comm.dst_proc);
362     break;
363
364   default:
365     return TRUE;
366   }
367 }
368
369 int MC_process_is_enabled(smx_process_t process)
370 {
371   if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))
372     return TRUE;
373
374   return FALSE;
375 }
376
377 char *MC_request_get_dot_output(smx_simcall_t req, int value){
378
379   char *str = NULL, *label = NULL;
380   smx_action_t act = NULL;
381   const char *host_name = MSG_host_get_name(MSG_process_get_host(req->issuer));
382
383   switch(req->call){
384   case SIMCALL_COMM_ISEND:
385     label = bprintf("[(%lu)%s] iSend", req->issuer->pid, host_name);
386     break;
387     
388   case SIMCALL_COMM_IRECV:
389     label = bprintf("[(%lu)%s] iRecv", req->issuer->pid, host_name);
390     break;
391  
392  case SIMCALL_COMM_WAIT:
393    act = simcall_comm_wait__get__comm(req);
394    if(value == -1)
395      label = bprintf("[(%lu)%s] WaitTimeout", req->issuer->pid, host_name);
396     else
397       label = bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", req->issuer->pid, host_name, act->comm.src_proc ? act->comm.src_proc->pid : 0, act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
398     break;
399
400   case SIMCALL_COMM_TEST:
401     act = simcall_comm_test__get__comm(req);
402     if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL)
403       label = bprintf("[(%lu)%s] Test FALSE", req->issuer->pid, host_name);
404     else
405       label = bprintf("[(%lu)%s] Test TRUE", req->issuer->pid, host_name);
406     break;
407
408   case SIMCALL_MC_RANDOM:
409     if(value == 0)
410       label = bprintf("[(%lu)%s] MC_RANDOM (0)", req->issuer->pid, host_name);
411     else
412       label = bprintf("[(%lu)%s] MC_RANDOM (1)", req->issuer->pid, host_name);
413     break;
414
415   case SIMCALL_MC_SNAPSHOT:
416     label = bprintf("[(%lu)%s] MC_SNAPSHOT", req->issuer->pid, host_name);
417     break;
418
419   case SIMCALL_MC_COMPARE_SNAPSHOTS:
420     label = bprintf("((%lu)%s) MC_COMPARE_SNAPSHOTS", req->issuer->pid, host_name);
421     break;
422
423   default:
424     THROW_UNIMPLEMENTED;
425   }
426
427   str = bprintf("label = \"%s\", color = %s, fontcolor = %s", label, colors[req->issuer->pid-1], colors[req->issuer->pid-1]);
428   xbt_free(label);
429   return str;
430
431 }