Logo AND Algorithmique Numérique Distribuée

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