1 /* Copyright (c) 2008-2014. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "mc_request.h"
9 #include "mc_private.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
12 "Logging specific to MC (request)");
14 static char *pointer_to_string(void *pointer);
15 static char *buff_size_to_string(size_t size);
17 int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
19 if (mc_reduce_kind == e_mc_reduce_none)
22 if (r1->issuer == r2->issuer)
25 /* Wait with timeout transitions are not considered by the independance theorem, thus we consider them as dependant with all other transitions */
26 if ((r1->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r1) > 0)
27 || (r2->call == SIMCALL_COMM_WAIT
28 && simcall_comm_wait__get__timeout(r2) > 0))
31 if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
34 if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
37 if ((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
38 && r2->call == SIMCALL_COMM_WAIT) {
42 SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) :
43 simcall_comm_irecv__get__rdv(r1);
45 // FIXME, remote access to comm object
47 if (rdv != simcall_comm_wait__get__comm(r2)->comm.rdv_cpy
48 && simcall_comm_wait__get__timeout(r2) <= 0)
51 if ((r1->issuer != simcall_comm_wait__get__comm(r2)->comm.src_proc)
52 && (r1->issuer != simcall_comm_wait__get__comm(r2)->comm.dst_proc)
53 && simcall_comm_wait__get__timeout(r2) <= 0)
56 if ((r1->call == SIMCALL_COMM_ISEND)
57 && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND)
58 && (simcall_comm_wait__get__comm(r2)->comm.src_buff !=
59 simcall_comm_isend__get__src_buff(r1))
60 && simcall_comm_wait__get__timeout(r2) <= 0)
63 if ((r1->call == SIMCALL_COMM_IRECV)
64 && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE)
65 && (simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
66 simcall_comm_irecv__get__dst_buff(r1))
67 && simcall_comm_wait__get__timeout(r2) <= 0)
71 if ((r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
72 && r1->call == SIMCALL_COMM_WAIT) {
76 SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) :
77 simcall_comm_irecv__get__rdv(r2);
79 if (rdv != simcall_comm_wait__get__comm(r1)->comm.rdv_cpy
80 && simcall_comm_wait__get__timeout(r1) <= 0)
83 if ((r2->issuer != simcall_comm_wait__get__comm(r1)->comm.src_proc)
84 && (r2->issuer != simcall_comm_wait__get__comm(r1)->comm.dst_proc)
85 && simcall_comm_wait__get__timeout(r1) <= 0)
88 if ((r2->call == SIMCALL_COMM_ISEND)
89 && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND)
90 && (simcall_comm_wait__get__comm(r1)->comm.src_buff !=
91 simcall_comm_isend__get__src_buff(r2))
92 && simcall_comm_wait__get__timeout(r1) <= 0)
95 if ((r2->call == SIMCALL_COMM_IRECV)
96 && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE)
97 && (simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
98 simcall_comm_irecv__get__dst_buff(r2))
99 && simcall_comm_wait__get__timeout(r1) <= 0)
103 /* FIXME: the following rule assumes that the result of the
104 * isend/irecv call is not stored in a buffer used in the
106 /*if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
107 && r2->call == SIMCALL_COMM_TEST)
110 /* FIXME: the following rule assumes that the result of the
111 * isend/irecv call is not stored in a buffer used in the
113 /*if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
114 && r1->call == SIMCALL_COMM_TEST)
117 if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
118 && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
121 if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
122 && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
125 if (r1->call == SIMCALL_COMM_WAIT
126 && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
127 && (simcall_comm_wait__get__comm(r1)->comm.src_proc == NULL
128 || simcall_comm_wait__get__comm(r1)->comm.dst_proc == NULL))
131 if (r2->call == SIMCALL_COMM_WAIT
132 && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
133 && (simcall_comm_wait__get__comm(r2)->comm.src_proc == NULL
134 || simcall_comm_wait__get__comm(r2)->comm.dst_proc == NULL))
137 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
138 && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
139 simcall_comm_wait__get__comm(r2)->comm.src_buff
140 && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
141 simcall_comm_wait__get__comm(r2)->comm.dst_buff)
144 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
145 && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
146 && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
147 && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
148 && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
149 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
150 simcall_comm_wait__get__comm(r2)->comm.src_buff
151 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
152 simcall_comm_wait__get__comm(r2)->comm.dst_buff
153 && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
154 simcall_comm_wait__get__comm(r1)->comm.src_buff)
157 if (r1->call == SIMCALL_COMM_TEST &&
158 (simcall_comm_test__get__comm(r1) == NULL
159 || simcall_comm_test__get__comm(r1)->comm.src_buff == NULL
160 || simcall_comm_test__get__comm(r1)->comm.dst_buff == NULL))
163 if (r2->call == SIMCALL_COMM_TEST &&
164 (simcall_comm_test__get__comm(r2) == NULL
165 || simcall_comm_test__get__comm(r2)->comm.src_buff == NULL
166 || simcall_comm_test__get__comm(r2)->comm.dst_buff == NULL))
169 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
170 && simcall_comm_test__get__comm(r1)->comm.src_buff ==
171 simcall_comm_wait__get__comm(r2)->comm.src_buff
172 && simcall_comm_test__get__comm(r1)->comm.dst_buff ==
173 simcall_comm_wait__get__comm(r2)->comm.dst_buff)
176 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
177 && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
178 simcall_comm_test__get__comm(r2)->comm.src_buff
179 && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
180 simcall_comm_test__get__comm(r2)->comm.dst_buff)
183 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
184 && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
185 && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
186 && simcall_comm_test__get__comm(r2)->comm.src_buff != NULL
187 && simcall_comm_test__get__comm(r2)->comm.dst_buff != NULL
188 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
189 simcall_comm_test__get__comm(r2)->comm.src_buff
190 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
191 simcall_comm_test__get__comm(r2)->comm.dst_buff
192 && simcall_comm_test__get__comm(r2)->comm.dst_buff !=
193 simcall_comm_wait__get__comm(r1)->comm.src_buff)
196 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
197 && simcall_comm_test__get__comm(r1)->comm.src_buff != NULL
198 && simcall_comm_test__get__comm(r1)->comm.dst_buff != NULL
199 && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
200 && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
201 && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
202 simcall_comm_wait__get__comm(r2)->comm.src_buff
203 && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
204 simcall_comm_wait__get__comm(r2)->comm.dst_buff
205 && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
206 simcall_comm_test__get__comm(r1)->comm.src_buff)
213 static char *pointer_to_string(void *pointer)
216 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
217 return bprintf("%p", pointer);
219 return xbt_strdup("(verbose only)");
222 static char *buff_size_to_string(size_t buff_size)
225 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
226 return bprintf("%zu", buff_size);
228 return xbt_strdup("(verbose only)");
232 char *MC_request_to_string(smx_simcall_t req, int value)
234 char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
235 smx_synchro_t act = NULL;
238 // FIXME, host_get_name
239 // FIXME, buffer access (issuer->name, issuer->smx_host)
241 smx_process_t issuer = MC_process_get_issuer(&mc_model_checker->process, req);
244 case SIMCALL_COMM_ISEND:
245 type = xbt_strdup("iSend");
246 p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
247 bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
248 if (issuer->smx_host)
250 bprintf("src=(%lu)%s (%s), buff=%s, size=%s", issuer->pid,
251 MSG_host_get_name(issuer->smx_host), issuer->name,
255 bprintf("src=(%lu)%s, buff=%s, size=%s", issuer->pid,
256 issuer->name, p, bs);
258 case SIMCALL_COMM_IRECV:
260 simcall_comm_irecv__get__dst_buff_size(req) ?
261 *simcall_comm_irecv__get__dst_buff_size(req) : 0;
262 type = xbt_strdup("iRecv");
263 p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
264 bs = buff_size_to_string(size);
265 if (issuer->smx_host)
267 bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", issuer->pid,
268 MSG_host_get_name(issuer->smx_host), issuer->name,
272 bprintf("dst=(%lu)%s, buff=%s, size=%s", issuer->pid,
273 issuer->name, p, bs);
275 case SIMCALL_COMM_WAIT:
276 act = simcall_comm_wait__get__comm(req);
278 type = xbt_strdup("WaitTimeout");
279 p = pointer_to_string(act);
280 args = bprintf("comm=%s", p);
282 type = xbt_strdup("Wait");
283 p = pointer_to_string(act);
284 args = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
285 act->comm.src_proc ? act->comm.src_proc->pid : 0,
286 act->comm.src_proc ? MSG_host_get_name(act->comm.src_proc->
288 act->comm.src_proc ? act->comm.src_proc->name : "",
289 act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
290 act->comm.dst_proc ? MSG_host_get_name(act->comm.dst_proc->
292 act->comm.dst_proc ? act->comm.dst_proc->name : "");
295 case SIMCALL_COMM_TEST:
296 act = simcall_comm_test__get__comm(req);
297 if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
298 type = xbt_strdup("Test FALSE");
299 p = pointer_to_string(act);
300 args = bprintf("comm=%s", p);
302 type = xbt_strdup("Test TRUE");
303 p = pointer_to_string(act);
304 args = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
305 act->comm.src_proc->pid, act->comm.src_proc->name,
306 MSG_host_get_name(act->comm.src_proc->smx_host),
307 act->comm.dst_proc->pid, act->comm.dst_proc->name,
308 MSG_host_get_name(act->comm.dst_proc->smx_host));
312 case SIMCALL_COMM_WAITANY:
313 type = xbt_strdup("WaitAny");
314 if (!xbt_dynar_is_empty(simcall_comm_waitany__get__comms(req))) {
315 p = pointer_to_string(xbt_dynar_get_as
316 (simcall_comm_waitany__get__comms(req), value,
319 bprintf("comm=%s (%d of %lu)", p, value + 1,
320 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
322 args = bprintf("comm at idx %d", value);
326 case SIMCALL_COMM_TESTANY:
328 type = xbt_strdup("TestAny FALSE");
329 args = xbt_strdup("-");
331 type = xbt_strdup("TestAny");
333 bprintf("(%d of %lu)", value + 1,
334 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
338 case SIMCALL_MC_SNAPSHOT:
339 type = xbt_strdup("MC_SNAPSHOT");
343 case SIMCALL_MC_COMPARE_SNAPSHOTS:
344 type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
348 case SIMCALL_MC_RANDOM:
349 type = xbt_strdup("MC_RANDOM");
350 args = bprintf("%d", value);
359 bprintf("[(%lu)%s (%s)] %s(%s)", issuer->pid,
360 MSG_host_get_name(issuer->smx_host), issuer->name,
364 bprintf("[(%lu)%s (%s)] %s ", issuer->pid,
365 MSG_host_get_name(issuer->smx_host), issuer->name,
376 unsigned int MC_request_testany_fail(smx_simcall_t req)
379 smx_synchro_t action;
381 xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action) {
382 if (action->comm.src_proc && action->comm.dst_proc)
389 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
395 case SIMCALL_COMM_WAIT:
396 /* FIXME: check also that src and dst processes are not suspended */
397 act = simcall_comm_wait__get__comm(req);
398 return (act->comm.src_proc && act->comm.dst_proc);
401 case SIMCALL_COMM_WAITANY:
403 xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx,
405 return (act->comm.src_proc && act->comm.dst_proc);
408 case SIMCALL_COMM_TESTANY:
410 xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx,
412 return (act->comm.src_proc && act->comm.dst_proc);
420 int MC_process_is_enabled(smx_process_t process)
422 return MC_request_is_enabled(&process->simcall);
425 char *MC_request_get_dot_output(smx_simcall_t req, int value)
427 // TODO, remote access to MSG_host_get_name(issuer->smx_host)
429 char *str = NULL, *label = NULL;
430 smx_synchro_t act = NULL;
432 const smx_process_t issuer = MC_process_get_issuer(&mc_model_checker->process, req);
435 case SIMCALL_COMM_ISEND:
436 if (issuer->smx_host)
438 bprintf("[(%lu)%s] iSend", issuer->pid,
439 MSG_host_get_name(issuer->smx_host));
441 label = bprintf("[(%lu)] iSend", issuer->pid);
444 case SIMCALL_COMM_IRECV:
445 if (issuer->smx_host)
447 bprintf("[(%lu)%s] iRecv", issuer->pid,
448 MSG_host_get_name(issuer->smx_host));
450 label = bprintf("[(%lu)] iRecv", issuer->pid);
453 case SIMCALL_COMM_WAIT:
454 act = simcall_comm_wait__get__comm(req);
456 if (issuer->smx_host)
458 bprintf("[(%lu)%s] WaitTimeout", issuer->pid,
459 MSG_host_get_name(issuer->smx_host));
461 label = bprintf("[(%lu)] WaitTimeout", issuer->pid);
463 if (issuer->smx_host)
465 bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", issuer->pid,
466 MSG_host_get_name(issuer->smx_host),
467 act->comm.src_proc ? act->comm.src_proc->pid : 0,
468 act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
471 bprintf("[(%lu)] Wait [(%lu)->(%lu)]", issuer->pid,
472 act->comm.src_proc ? act->comm.src_proc->pid : 0,
473 act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
477 case SIMCALL_COMM_TEST:
478 act = simcall_comm_test__get__comm(req);
479 if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
480 if (issuer->smx_host)
482 bprintf("[(%lu)%s] Test FALSE", issuer->pid,
483 MSG_host_get_name(issuer->smx_host));
485 label = bprintf("[(%lu)] Test FALSE", issuer->pid);
487 if (issuer->smx_host)
489 bprintf("[(%lu)%s] Test TRUE", issuer->pid,
490 MSG_host_get_name(issuer->smx_host));
492 label = bprintf("[(%lu)] Test TRUE", issuer->pid);
496 case SIMCALL_COMM_WAITANY:
497 if (issuer->smx_host)
499 bprintf("[(%lu)%s] WaitAny [%d of %lu]", issuer->pid,
500 MSG_host_get_name(issuer->smx_host), value + 1,
501 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
504 bprintf("[(%lu)] WaitAny [%d of %lu]", issuer->pid, value + 1,
505 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
508 case SIMCALL_COMM_TESTANY:
510 if (issuer->smx_host)
512 bprintf("[(%lu)%s] TestAny FALSE", issuer->pid,
513 MSG_host_get_name(issuer->smx_host));
515 label = bprintf("[(%lu)] TestAny FALSE", issuer->pid);
517 if (issuer->smx_host)
519 bprintf("[(%lu)%s] TestAny TRUE [%d of %lu]", issuer->pid,
520 MSG_host_get_name(issuer->smx_host), value + 1,
521 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
524 bprintf("[(%lu)] TestAny TRUE [%d of %lu]", issuer->pid,
526 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
530 case SIMCALL_MC_RANDOM:
531 if (issuer->smx_host)
533 bprintf("[(%lu)%s] MC_RANDOM (%d)", issuer->pid,
534 MSG_host_get_name(issuer->smx_host), value);
536 label = bprintf("[(%lu)] MC_RANDOM (%d)", issuer->pid, value);
539 case SIMCALL_MC_SNAPSHOT:
540 if (issuer->smx_host)
542 bprintf("[(%lu)%s] MC_SNAPSHOT", issuer->pid,
543 MSG_host_get_name(issuer->smx_host));
545 label = bprintf("[(%lu)] MC_SNAPSHOT", issuer->pid);
548 case SIMCALL_MC_COMPARE_SNAPSHOTS:
549 if (issuer->smx_host)
551 bprintf("[(%lu)%s] MC_COMPARE_SNAPSHOTS", issuer->pid,
552 MSG_host_get_name(issuer->smx_host));
554 label = bprintf("[(%lu)] MC_COMPARE_SNAPSHOTS", issuer->pid);
562 bprintf("label = \"%s\", color = %s, fontcolor = %s", label,
563 colors[issuer->pid - 1], colors[issuer->pid - 1]);