Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new tracing options to reduce the size of the traces
[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)
36       return FALSE;
37
38     if(simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND && r1->call == SIMCALL_COMM_ISEND)
39       return FALSE;
40
41     if(simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE && r1->call == SIMCALL_COMM_IRECV)
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)
54       return FALSE;
55
56     if(simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND && r2->call == SIMCALL_COMM_ISEND)
57       return FALSE;
58
59     if(simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE && r2->call == SIMCALL_COMM_IRECV)
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=%s, buff=%s, size=%s", 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=%s, buff=%s, size=%s", 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=%p", p);
199     }else{
200       type = xbt_strdup("Wait");
201       p = pointer_to_string(act);
202       args  = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
203                       act->comm.src_proc ? act->comm.src_proc->pid : 0,
204                       act->comm.src_proc ? act->comm.src_proc->name : "",
205                       act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
206                       act->comm.dst_proc ? act->comm.dst_proc->name : "");
207     }
208     break;
209   case SIMCALL_COMM_TEST:
210     act = simcall_comm_test__get__comm(req);
211     if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL){
212       type = xbt_strdup("Test FALSE");
213       p = pointer_to_string(act);
214       args = bprintf("comm=%s", p);
215     }else{
216       type = xbt_strdup("Test TRUE");
217       p = pointer_to_string(act);
218       args  = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
219                       act->comm.src_proc->pid, act->comm.src_proc->name,
220                       act->comm.dst_proc->pid, act->comm.dst_proc->name);
221     }
222     break;
223
224   case SIMCALL_COMM_WAITANY:
225     type = xbt_strdup("WaitAny");
226     p = pointer_to_string(xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value, smx_action_t));
227     args = bprintf("comm=%s (%d of %lu)", p,
228                    value+1, xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
229     break;
230
231   case SIMCALL_COMM_TESTANY:
232     if(value == -1){
233       type = xbt_strdup("TestAny FALSE");
234       args = xbt_strdup("-");
235     }else{
236       type = xbt_strdup("TestAny");
237       args = bprintf("(%d of %lu)", value+1, xbt_dynar_length(simcall_comm_testany__get__comms(req)));
238     }
239     break;
240
241   case SIMCALL_MC_SNAPSHOT:
242     type = xbt_strdup("MC_SNAPSHOT");
243     args = '\0';
244     break;
245
246   case SIMCALL_MC_COMPARE_SNAPSHOTS:
247     type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
248     args = '\0';
249     break;
250
251   case SIMCALL_MC_RANDOM:
252     type = xbt_strdup("MC_RANDOM");
253     args = bprintf("%d", value);
254     break;
255
256   default:
257     THROW_UNIMPLEMENTED;
258   }
259
260   if(args != NULL){
261     str = bprintf("[(%lu)%s] %s (%s)", req->issuer->pid ,req->issuer->name, type, args);
262     xbt_free(args);
263   }else{
264     str = bprintf("[(%lu)%s] %s ", req->issuer->pid ,req->issuer->name, type);
265   }
266   xbt_free(type);
267   xbt_free(p);
268   xbt_free(bs);
269   return str;
270 }
271
272 unsigned int MC_request_testany_fail(smx_simcall_t req)
273 {
274   unsigned int cursor;
275   smx_action_t action;
276
277   xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action){
278     if(action->comm.src_proc && action->comm.dst_proc)
279       return FALSE;
280   }
281
282   return TRUE;
283 }
284
285 int MC_request_is_visible(smx_simcall_t req)
286 {
287   return req->call == SIMCALL_COMM_ISEND
288     || req->call == SIMCALL_COMM_IRECV
289     || req->call == SIMCALL_COMM_WAIT
290     || req->call == SIMCALL_COMM_WAITANY
291     || req->call == SIMCALL_COMM_TEST
292     || req->call == SIMCALL_COMM_TESTANY
293     || req->call == SIMCALL_MC_RANDOM
294     || req->call == SIMCALL_MC_SNAPSHOT
295     || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS;
296 }
297
298 int MC_request_is_enabled(smx_simcall_t req)
299 {
300   unsigned int index = 0;
301   smx_action_t act;
302
303   switch (req->call) {
304
305   case SIMCALL_COMM_WAIT:
306     /* FIXME: check also that src and dst processes are not suspended */
307
308     /* If it has a timeout it will be always be enabled, because even if the
309      * communication is not ready, it can timeout and won't block.
310      * On the other hand if it hasn't a timeout, check if the comm is ready.*/
311     if(simcall_comm_wait__get__timeout(req) >= 0){
312       if(_sg_mc_timeout == 1){
313         return TRUE;
314       }else{
315         act = simcall_comm_wait__get__comm(req);
316         return (act->comm.src_proc && act->comm.dst_proc);
317       }
318     }else{
319       act = simcall_comm_wait__get__comm(req);
320       return (act->comm.src_proc && act->comm.dst_proc);
321     }
322     break;
323
324   case SIMCALL_COMM_WAITANY:
325     /* Check if it has at least one communication ready */
326     xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act) {
327       if (act->comm.src_proc && act->comm.dst_proc){
328         return TRUE;
329       }
330     }
331     return FALSE;
332     break;
333
334   default:
335     /* The rest of the request are always enabled */
336     return TRUE;
337   }
338 }
339
340 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
341 {
342   smx_action_t act;
343
344   switch (req->call) {
345
346   case SIMCALL_COMM_WAIT:
347     /* FIXME: check also that src and dst processes are not suspended */
348     act = simcall_comm_wait__get__comm(req);
349     return (act->comm.src_proc && act->comm.dst_proc);
350     break;
351
352   case SIMCALL_COMM_WAITANY:
353     act = xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx, smx_action_t);
354     return (act->comm.src_proc && act->comm.dst_proc);
355     break;
356
357   case SIMCALL_COMM_TESTANY:
358     act = xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx, smx_action_t);
359     return (act->comm.src_proc && act->comm.dst_proc);
360     break;
361
362   default:
363     return TRUE;
364   }
365 }
366
367 int MC_process_is_enabled(smx_process_t process)
368 {
369   if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))
370     return TRUE;
371
372   return FALSE;
373 }
374
375 char *MC_request_get_dot_output(smx_simcall_t req, int value){
376
377   char *str = NULL, *label = NULL;
378   smx_action_t act = NULL;
379
380   switch(req->call){
381   case SIMCALL_COMM_ISEND:
382     label = xbt_strdup("iSend");
383     break;
384     
385   case SIMCALL_COMM_IRECV:
386     label = xbt_strdup("iRecv");
387     break;
388  
389  case SIMCALL_COMM_WAIT:
390     if(value == -1)
391       label = xbt_strdup("WaitTimeout");
392     else
393       label = xbt_strdup("Wait");
394     break;
395
396   case SIMCALL_COMM_TEST:
397     act = simcall_comm_test__get__comm(req);
398     if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL)
399       label = xbt_strdup("Test FALSE");
400     else
401       label = xbt_strdup("Test TRUE");
402     break;
403
404   case SIMCALL_MC_RANDOM:
405     if(value == 0)
406       label = xbt_strdup("MC_RANDOM (0)");
407     else
408       label = xbt_strdup("MC_RANDOM (1)");
409     break;
410
411   case SIMCALL_MC_SNAPSHOT:
412     label = xbt_strdup("MC_SNAPSHOT");
413     break;
414
415   case SIMCALL_MC_COMPARE_SNAPSHOTS:
416     label = xbt_strdup("MC_COMPARE_SNAPSHOTS");
417     break;
418
419   default:
420     THROW_UNIMPLEMENTED;
421   }
422
423   str = bprintf("label = \"%s\", color = %s", label, colors[req->issuer->pid-1]);
424   xbt_free(label);
425   return str;
426
427 }