Logo AND Algorithmique Numérique Distribuée

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