Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
mv src/mc/private.h src/mc/mc_private.h
[simgrid.git] / src / mc / mc_request.c
1 #include "mc_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_simcall_t r1, smx_simcall_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 == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
19     return FALSE;
20
21   if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
22     return FALSE;
23
24   if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
25        &&  r2->call == SIMCALL_COMM_WAIT){
26
27     if(r2->comm_wait.comm->comm.rdv == NULL)
28       return FALSE;
29
30     smx_rdv_t rdv = r1->call == SIMCALL_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 == SIMCALL_COMM_ISEND)
36       return FALSE;
37
38     if(r2->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r1->call == SIMCALL_COMM_IRECV)
39       return FALSE;
40   }
41
42   if(   (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
43        &&  r1->call == SIMCALL_COMM_WAIT){
44
45     if(r1->comm_wait.comm->comm.rdv != NULL)
46       return FALSE;
47
48     smx_rdv_t rdv = r2->call == SIMCALL_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 == SIMCALL_COMM_ISEND)
54       return FALSE;
55
56     if(r1->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r2->call == SIMCALL_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 == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
64      &&  r2->call == SIMCALL_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 == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
71      && r1->call == SIMCALL_COMM_TEST)
72     return FALSE;
73
74   if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
75       && r1->comm_isend.rdv != r2->comm_isend.rdv)
76     return FALSE;
77
78   if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
79       && r1->comm_irecv.rdv != r2->comm_irecv.rdv)
80     return FALSE;
81
82   if(r1->call == SIMCALL_COMM_WAIT && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_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 == SIMCALL_COMM_WAIT && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_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 == SIMCALL_COMM_WAIT && r2->call == SIMCALL_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 == SIMCALL_COMM_WAIT && r2->call == SIMCALL_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 == SIMCALL_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 == SIMCALL_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 == SIMCALL_COMM_TEST && r2->call == SIMCALL_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 == SIMCALL_COMM_WAIT && r2->call == SIMCALL_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 == SIMCALL_COMM_WAIT && r2->call == SIMCALL_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 == SIMCALL_COMM_TEST && r2->call == SIMCALL_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_simcall_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 SIMCALL_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 SIMCALL_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 SIMCALL_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 SIMCALL_COMM_TEST:
207       act = req->comm_test.comm;
208       if(act->comm.src_proc == NULL || act->comm.dst_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->pid, act->comm.src_proc->name,
217                         act->comm.dst_proc->pid, act->comm.dst_proc->name);
218       }
219       break;
220
221     case SIMCALL_COMM_WAITANY:
222       type = xbt_strdup("WaitAny");
223       p = pointer_to_string(xbt_dynar_get_as(req->comm_waitany.comms, value, smx_action_t));
224       args = bprintf("comm=%s (%d of %lu)", p,
225                      value+1, xbt_dynar_length(req->comm_waitany.comms));
226       break;
227
228     case SIMCALL_COMM_TESTANY:
229       if(value == -1){
230         type = xbt_strdup("TestAny FALSE");
231         args = xbt_strdup("-");
232       }else{
233         type = xbt_strdup("TestAny");
234         args = bprintf("(%d of %lu)", value+1, xbt_dynar_length(req->comm_testany.comms));
235       }
236       break;
237
238     default:
239       THROW_UNIMPLEMENTED;
240   }
241
242   str = bprintf("[(%lu)%s] %s (%s)", req->issuer->pid ,req->issuer->name, type, args);
243   xbt_free(type);
244   xbt_free(args);
245   xbt_free(p);
246   xbt_free(bs);
247   return str;
248 }
249
250 unsigned int MC_request_testany_fail(smx_simcall_t req)
251 {
252   unsigned int cursor;
253   smx_action_t action;
254
255   xbt_dynar_foreach(req->comm_testany.comms, cursor, action){
256     if(action->comm.src_proc && action->comm.dst_proc)
257       return FALSE;
258   }
259
260   return TRUE;
261 }
262
263 int MC_request_is_visible(smx_simcall_t req)
264 {
265   return req->call == SIMCALL_COMM_ISEND
266      || req->call == SIMCALL_COMM_IRECV
267      || req->call == SIMCALL_COMM_WAIT
268      || req->call == SIMCALL_COMM_WAITANY
269      || req->call == SIMCALL_COMM_TEST
270      || req->call == SIMCALL_COMM_TESTANY;
271 }
272
273 int MC_request_is_enabled(smx_simcall_t req)
274 {
275   unsigned int index = 0;
276   smx_action_t act;
277
278   switch (req->call) {
279
280     case SIMCALL_COMM_WAIT:
281       /* FIXME: check also that src and dst processes are not suspended */
282
283       /* If it has a timeout it will be always be enabled, because even if the
284        * communication is not ready, it can timeout and won't block.
285        * On the other hand if it hasn't a timeout, check if the comm is ready.*/
286       if(req->comm_wait.timeout >= 0){
287         return TRUE;
288       }else{
289         act = req->comm_wait.comm;
290         return (act->comm.src_proc && act->comm.dst_proc);
291       }
292       break;
293
294     case SIMCALL_COMM_WAITANY:
295       /* Check if it has at least one communication ready */
296       xbt_dynar_foreach(req->comm_waitany.comms, index, act) {
297         if (act->comm.src_proc && act->comm.dst_proc){
298           return TRUE;
299         }
300       }
301       return FALSE;
302       break;
303
304     default:
305       /* The rest of the request are always enabled */
306       return TRUE;
307   }
308 }
309
310 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
311 {
312   smx_action_t act;
313
314   switch (req->call) {
315
316     case SIMCALL_COMM_WAIT:
317       /* FIXME: check also that src and dst processes are not suspended */
318       act = req->comm_wait.comm;
319       return (act->comm.src_proc && act->comm.dst_proc);
320       break;
321
322     case SIMCALL_COMM_WAITANY:
323       act = xbt_dynar_get_as(req->comm_waitany.comms, idx, smx_action_t);
324       return (act->comm.src_proc && act->comm.dst_proc);
325       break;
326
327     case SIMCALL_COMM_TESTANY:
328       act = xbt_dynar_get_as(req->comm_testany.comms, idx, smx_action_t);
329       return (act->comm.src_proc && act->comm.dst_proc);
330       break;
331
332     default:
333       return TRUE;
334   }
335 }
336
337 int MC_process_is_enabled(smx_process_t process)
338 {
339   if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))
340     return TRUE;
341
342   return FALSE;
343 }