Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into vmtrace
[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_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   default:
252     THROW_UNIMPLEMENTED;
253   }
254
255   str = bprintf("[(%lu)%s] %s (%s)", req->issuer->pid ,req->issuer->name, type, args);
256   xbt_free(type);
257   xbt_free(args);
258   xbt_free(p);
259   xbt_free(bs);
260   return str;
261 }
262
263 unsigned int MC_request_testany_fail(smx_simcall_t req)
264 {
265   unsigned int cursor;
266   smx_action_t action;
267
268   xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action){
269     if(action->comm.src_proc && action->comm.dst_proc)
270       return FALSE;
271   }
272
273   return TRUE;
274 }
275
276 int MC_request_is_visible(smx_simcall_t req)
277 {
278   return req->call == SIMCALL_COMM_ISEND
279     || req->call == SIMCALL_COMM_IRECV
280     || req->call == SIMCALL_COMM_WAIT
281     || req->call == SIMCALL_COMM_WAITANY
282     || req->call == SIMCALL_COMM_TEST
283     || req->call == SIMCALL_COMM_TESTANY
284     || req->call == SIMCALL_MC_SNAPSHOT
285     || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS;
286 }
287
288 int MC_request_is_enabled(smx_simcall_t req)
289 {
290   unsigned int index = 0;
291   smx_action_t act;
292
293   switch (req->call) {
294
295   case SIMCALL_COMM_WAIT:
296     /* FIXME: check also that src and dst processes are not suspended */
297
298     /* If it has a timeout it will be always be enabled, because even if the
299      * communication is not ready, it can timeout and won't block.
300      * On the other hand if it hasn't a timeout, check if the comm is ready.*/
301     if(simcall_comm_wait__get__timeout(req) >= 0){
302       if(_sg_mc_timeout == 1){
303         return TRUE;
304       }else{
305         act = simcall_comm_wait__get__comm(req);
306         return (act->comm.src_proc && act->comm.dst_proc);
307       }
308     }else{
309       act = simcall_comm_wait__get__comm(req);
310       return (act->comm.src_proc && act->comm.dst_proc);
311     }
312     break;
313
314   case SIMCALL_COMM_WAITANY:
315     /* Check if it has at least one communication ready */
316     xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act) {
317       if (act->comm.src_proc && act->comm.dst_proc){
318         return TRUE;
319       }
320     }
321     return FALSE;
322     break;
323
324   default:
325     /* The rest of the request are always enabled */
326     return TRUE;
327   }
328 }
329
330 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
331 {
332   smx_action_t act;
333
334   switch (req->call) {
335
336   case SIMCALL_COMM_WAIT:
337     /* FIXME: check also that src and dst processes are not suspended */
338     act = simcall_comm_wait__get__comm(req);
339     return (act->comm.src_proc && act->comm.dst_proc);
340     break;
341
342   case SIMCALL_COMM_WAITANY:
343     act = xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx, smx_action_t);
344     return (act->comm.src_proc && act->comm.dst_proc);
345     break;
346
347   case SIMCALL_COMM_TESTANY:
348     act = xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx, smx_action_t);
349     return (act->comm.src_proc && act->comm.dst_proc);
350     break;
351
352   default:
353     return TRUE;
354   }
355 }
356
357 int MC_process_is_enabled(smx_process_t process)
358 {
359   if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))
360     return TRUE;
361
362   return FALSE;
363 }