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_private.h"
9 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
10 "Logging specific to MC (request)");
12 static char *pointer_to_string(void *pointer);
13 static char *buff_size_to_string(size_t size);
15 int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
17 if (mc_reduce_kind == e_mc_reduce_none)
20 if (r1->issuer == r2->issuer)
23 /* Wait with timeout transitions are not considered by the independance theorem, thus we consider them as dependant with all other transitions */
24 if ((r1->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r1) > 0)
25 || (r2->call == SIMCALL_COMM_WAIT
26 && simcall_comm_wait__get__timeout(r2) > 0))
29 if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
32 if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
35 if ((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
36 && r2->call == SIMCALL_COMM_WAIT) {
40 SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) :
41 simcall_comm_irecv__get__rdv(r1);
43 if (rdv != simcall_comm_wait__get__comm(r2)->comm.rdv_cpy
44 && simcall_comm_wait__get__timeout(r2) <= 0)
47 if ((r1->issuer != simcall_comm_wait__get__comm(r2)->comm.src_proc)
48 && (r1->issuer != simcall_comm_wait__get__comm(r2)->comm.dst_proc)
49 && simcall_comm_wait__get__timeout(r2) <= 0)
52 if ((r1->call == SIMCALL_COMM_ISEND)
53 && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND)
54 && (simcall_comm_wait__get__comm(r2)->comm.src_buff !=
55 simcall_comm_isend__get__src_buff(r1))
56 && simcall_comm_wait__get__timeout(r2) <= 0)
59 if ((r1->call == SIMCALL_COMM_IRECV)
60 && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE)
61 && (simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
62 simcall_comm_irecv__get__dst_buff(r1))
63 && simcall_comm_wait__get__timeout(r2) <= 0)
67 if ((r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
68 && r1->call == SIMCALL_COMM_WAIT) {
72 SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) :
73 simcall_comm_irecv__get__rdv(r2);
75 if (rdv != simcall_comm_wait__get__comm(r1)->comm.rdv_cpy
76 && simcall_comm_wait__get__timeout(r1) <= 0)
79 if ((r2->issuer != simcall_comm_wait__get__comm(r1)->comm.src_proc)
80 && (r2->issuer != simcall_comm_wait__get__comm(r1)->comm.dst_proc)
81 && simcall_comm_wait__get__timeout(r1) <= 0)
84 if ((r2->call == SIMCALL_COMM_ISEND)
85 && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND)
86 && (simcall_comm_wait__get__comm(r1)->comm.src_buff !=
87 simcall_comm_isend__get__src_buff(r2))
88 && simcall_comm_wait__get__timeout(r1) <= 0)
91 if ((r2->call == SIMCALL_COMM_IRECV)
92 && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE)
93 && (simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
94 simcall_comm_irecv__get__dst_buff(r2))
95 && simcall_comm_wait__get__timeout(r1) <= 0)
99 /* FIXME: the following rule assumes that the result of the
100 * isend/irecv call is not stored in a buffer used in the
102 /*if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
103 && r2->call == SIMCALL_COMM_TEST)
106 /* FIXME: the following rule assumes that the result of the
107 * isend/irecv call is not stored in a buffer used in the
109 /*if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
110 && r1->call == SIMCALL_COMM_TEST)
113 if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
114 && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
117 if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
118 && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
121 if (r1->call == SIMCALL_COMM_WAIT
122 && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
123 && (simcall_comm_wait__get__comm(r1)->comm.src_proc == NULL
124 || simcall_comm_wait__get__comm(r1)->comm.dst_proc == NULL))
127 if (r2->call == SIMCALL_COMM_WAIT
128 && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
129 && (simcall_comm_wait__get__comm(r2)->comm.src_proc == NULL
130 || simcall_comm_wait__get__comm(r2)->comm.dst_proc == NULL))
133 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
134 && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
135 simcall_comm_wait__get__comm(r2)->comm.src_buff
136 && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
137 simcall_comm_wait__get__comm(r2)->comm.dst_buff)
140 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
141 && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
142 && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
143 && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
144 && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
145 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
146 simcall_comm_wait__get__comm(r2)->comm.src_buff
147 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
148 simcall_comm_wait__get__comm(r2)->comm.dst_buff
149 && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
150 simcall_comm_wait__get__comm(r1)->comm.src_buff)
153 if (r1->call == SIMCALL_COMM_TEST &&
154 (simcall_comm_test__get__comm(r1) == NULL
155 || simcall_comm_test__get__comm(r1)->comm.src_buff == NULL
156 || simcall_comm_test__get__comm(r1)->comm.dst_buff == NULL))
159 if (r2->call == SIMCALL_COMM_TEST &&
160 (simcall_comm_test__get__comm(r2) == NULL
161 || simcall_comm_test__get__comm(r2)->comm.src_buff == NULL
162 || simcall_comm_test__get__comm(r2)->comm.dst_buff == NULL))
165 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
166 && simcall_comm_test__get__comm(r1)->comm.src_buff ==
167 simcall_comm_wait__get__comm(r2)->comm.src_buff
168 && simcall_comm_test__get__comm(r1)->comm.dst_buff ==
169 simcall_comm_wait__get__comm(r2)->comm.dst_buff)
172 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
173 && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
174 simcall_comm_test__get__comm(r2)->comm.src_buff
175 && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
176 simcall_comm_test__get__comm(r2)->comm.dst_buff)
179 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
180 && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
181 && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
182 && simcall_comm_test__get__comm(r2)->comm.src_buff != NULL
183 && simcall_comm_test__get__comm(r2)->comm.dst_buff != NULL
184 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
185 simcall_comm_test__get__comm(r2)->comm.src_buff
186 && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
187 simcall_comm_test__get__comm(r2)->comm.dst_buff
188 && simcall_comm_test__get__comm(r2)->comm.dst_buff !=
189 simcall_comm_wait__get__comm(r1)->comm.src_buff)
192 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
193 && simcall_comm_test__get__comm(r1)->comm.src_buff != NULL
194 && simcall_comm_test__get__comm(r1)->comm.dst_buff != NULL
195 && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
196 && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
197 && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
198 simcall_comm_wait__get__comm(r2)->comm.src_buff
199 && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
200 simcall_comm_wait__get__comm(r2)->comm.dst_buff
201 && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
202 simcall_comm_test__get__comm(r1)->comm.src_buff)
209 static char *pointer_to_string(void *pointer)
212 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
213 return bprintf("%p", pointer);
215 return xbt_strdup("(verbose only)");
218 static char *buff_size_to_string(size_t buff_size)
221 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
222 return bprintf("%zu", buff_size);
224 return xbt_strdup("(verbose only)");
228 char *MC_request_to_string(smx_simcall_t req, int value)
230 char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
231 smx_action_t act = NULL;
235 case SIMCALL_COMM_ISEND:
236 type = xbt_strdup("iSend");
237 p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
238 bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
239 if (req->issuer->smx_host)
241 bprintf("src=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
242 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
246 bprintf("src=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
247 req->issuer->name, p, bs);
249 case SIMCALL_COMM_IRECV:
251 simcall_comm_irecv__get__dst_buff_size(req) ?
252 *simcall_comm_irecv__get__dst_buff_size(req) : 0;
253 type = xbt_strdup("iRecv");
254 p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
255 bs = buff_size_to_string(size);
256 if (req->issuer->smx_host)
258 bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
259 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
263 bprintf("dst=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
264 req->issuer->name, p, bs);
266 case SIMCALL_COMM_WAIT:
267 act = simcall_comm_wait__get__comm(req);
269 type = xbt_strdup("WaitTimeout");
270 p = pointer_to_string(act);
271 args = bprintf("comm=%s", p);
273 type = xbt_strdup("Wait");
274 p = pointer_to_string(act);
275 args = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
276 act->comm.src_proc ? act->comm.src_proc->pid : 0,
277 act->comm.src_proc ? MSG_host_get_name(act->comm.src_proc->
279 act->comm.src_proc ? act->comm.src_proc->name : "",
280 act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
281 act->comm.dst_proc ? MSG_host_get_name(act->comm.dst_proc->
283 act->comm.dst_proc ? act->comm.dst_proc->name : "");
286 case SIMCALL_COMM_TEST:
287 act = simcall_comm_test__get__comm(req);
288 if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
289 type = xbt_strdup("Test FALSE");
290 p = pointer_to_string(act);
291 args = bprintf("comm=%s", p);
293 type = xbt_strdup("Test TRUE");
294 p = pointer_to_string(act);
295 args = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
296 act->comm.src_proc->pid, act->comm.src_proc->name,
297 MSG_host_get_name(act->comm.src_proc->smx_host),
298 act->comm.dst_proc->pid, act->comm.dst_proc->name,
299 MSG_host_get_name(act->comm.dst_proc->smx_host));
303 case SIMCALL_COMM_WAITANY:
304 type = xbt_strdup("WaitAny");
305 if (!xbt_dynar_is_empty(simcall_comm_waitany__get__comms(req))) {
306 p = pointer_to_string(xbt_dynar_get_as
307 (simcall_comm_waitany__get__comms(req), value,
310 bprintf("comm=%s (%d of %lu)", p, value + 1,
311 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
313 args = bprintf("comm at idx %d", value);
317 case SIMCALL_COMM_TESTANY:
319 type = xbt_strdup("TestAny FALSE");
320 args = xbt_strdup("-");
322 type = xbt_strdup("TestAny");
324 bprintf("(%d of %lu)", value + 1,
325 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
329 case SIMCALL_MC_SNAPSHOT:
330 type = xbt_strdup("MC_SNAPSHOT");
334 case SIMCALL_MC_COMPARE_SNAPSHOTS:
335 type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
339 case SIMCALL_MC_RANDOM:
340 type = xbt_strdup("MC_RANDOM");
341 args = bprintf("%d", value);
350 bprintf("[(%lu)%s (%s)] %s(%s)", req->issuer->pid,
351 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
355 bprintf("[(%lu)%s (%s)] %s ", req->issuer->pid,
356 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
367 unsigned int MC_request_testany_fail(smx_simcall_t req)
372 xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action) {
373 if (action->comm.src_proc && action->comm.dst_proc)
380 int MC_request_is_visible(smx_simcall_t req)
382 return req->call == SIMCALL_COMM_ISEND
383 || req->call == SIMCALL_COMM_IRECV
384 || req->call == SIMCALL_COMM_WAIT
385 || req->call == SIMCALL_COMM_WAITANY
386 || req->call == SIMCALL_COMM_TEST
387 || req->call == SIMCALL_COMM_TESTANY
388 || req->call == SIMCALL_MC_RANDOM
389 || req->call == SIMCALL_MC_SNAPSHOT
390 || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS;
393 int MC_request_is_enabled(smx_simcall_t req)
395 unsigned int index = 0;
400 case SIMCALL_COMM_WAIT:
401 /* FIXME: check also that src and dst processes are not suspended */
403 /* If it has a timeout it will be always be enabled, because even if the
404 * communication is not ready, it can timeout and won't block.
405 * On the other hand if it hasn't a timeout, check if the comm is ready.*/
406 if (simcall_comm_wait__get__timeout(req) >= 0) {
407 if (_sg_mc_timeout == 1) {
410 act = simcall_comm_wait__get__comm(req);
411 return (act->comm.src_proc && act->comm.dst_proc);
414 act = simcall_comm_wait__get__comm(req);
415 if (act->comm.detached && act->comm.src_proc == NULL
416 && act->comm.type == SIMIX_COMM_READY)
417 return (act->comm.dst_proc != NULL);
418 return (act->comm.src_proc && act->comm.dst_proc);
422 case SIMCALL_COMM_WAITANY:
423 /* Check if it has at least one communication ready */
424 xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act) {
425 if (act->comm.src_proc && act->comm.dst_proc) {
433 /* The rest of the request are always enabled */
438 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
444 case SIMCALL_COMM_WAIT:
445 /* FIXME: check also that src and dst processes are not suspended */
446 act = simcall_comm_wait__get__comm(req);
447 return (act->comm.src_proc && act->comm.dst_proc);
450 case SIMCALL_COMM_WAITANY:
452 xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx,
454 return (act->comm.src_proc && act->comm.dst_proc);
457 case SIMCALL_COMM_TESTANY:
459 xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx,
461 return (act->comm.src_proc && act->comm.dst_proc);
469 int MC_process_is_enabled(smx_process_t process)
471 if (process->simcall.call != SIMCALL_NONE
472 && MC_request_is_enabled(&process->simcall))
478 char *MC_request_get_dot_output(smx_simcall_t req, int value)
481 char *str = NULL, *label = NULL;
482 smx_action_t act = NULL;
485 case SIMCALL_COMM_ISEND:
486 if (req->issuer->smx_host)
488 bprintf("[(%lu)%s] iSend", req->issuer->pid,
489 MSG_host_get_name(req->issuer->smx_host));
491 label = bprintf("[(%lu)] iSend", req->issuer->pid);
494 case SIMCALL_COMM_IRECV:
495 if (req->issuer->smx_host)
497 bprintf("[(%lu)%s] iRecv", req->issuer->pid,
498 MSG_host_get_name(req->issuer->smx_host));
500 label = bprintf("[(%lu)] iRecv", req->issuer->pid);
503 case SIMCALL_COMM_WAIT:
504 act = simcall_comm_wait__get__comm(req);
506 if (req->issuer->smx_host)
508 bprintf("[(%lu)%s] WaitTimeout", req->issuer->pid,
509 MSG_host_get_name(req->issuer->smx_host));
511 label = bprintf("[(%lu)] WaitTimeout", req->issuer->pid);
513 if (req->issuer->smx_host)
515 bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", req->issuer->pid,
516 MSG_host_get_name(req->issuer->smx_host),
517 act->comm.src_proc ? act->comm.src_proc->pid : 0,
518 act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
521 bprintf("[(%lu)] Wait [(%lu)->(%lu)]", req->issuer->pid,
522 act->comm.src_proc ? act->comm.src_proc->pid : 0,
523 act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
527 case SIMCALL_COMM_TEST:
528 act = simcall_comm_test__get__comm(req);
529 if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
530 if (req->issuer->smx_host)
532 bprintf("[(%lu)%s] Test FALSE", req->issuer->pid,
533 MSG_host_get_name(req->issuer->smx_host));
535 label = bprintf("[(%lu)] Test FALSE", req->issuer->pid);
537 if (req->issuer->smx_host)
539 bprintf("[(%lu)%s] Test TRUE", req->issuer->pid,
540 MSG_host_get_name(req->issuer->smx_host));
542 label = bprintf("[(%lu)] Test TRUE", req->issuer->pid);
546 case SIMCALL_COMM_WAITANY:
547 if (req->issuer->smx_host)
549 bprintf("[(%lu)%s] WaitAny [%d of %lu]", req->issuer->pid,
550 MSG_host_get_name(req->issuer->smx_host), value + 1,
551 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
554 bprintf("[(%lu)] WaitAny [%d of %lu]", req->issuer->pid, value + 1,
555 xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
558 case SIMCALL_COMM_TESTANY:
560 if (req->issuer->smx_host)
562 bprintf("[(%lu)%s] TestAny FALSE", req->issuer->pid,
563 MSG_host_get_name(req->issuer->smx_host));
565 label = bprintf("[(%lu)] TestAny FALSE", req->issuer->pid);
567 if (req->issuer->smx_host)
569 bprintf("[(%lu)%s] TestAny TRUE [%d of %lu]", req->issuer->pid,
570 MSG_host_get_name(req->issuer->smx_host), value + 1,
571 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
574 bprintf("[(%lu)] TestAny TRUE [%d of %lu]", req->issuer->pid,
576 xbt_dynar_length(simcall_comm_testany__get__comms(req)));
580 case SIMCALL_MC_RANDOM:
581 if (req->issuer->smx_host)
583 bprintf("[(%lu)%s] MC_RANDOM (%d)", req->issuer->pid,
584 MSG_host_get_name(req->issuer->smx_host), value);
586 label = bprintf("[(%lu)] MC_RANDOM (%d)", req->issuer->pid, value);
589 case SIMCALL_MC_SNAPSHOT:
590 if (req->issuer->smx_host)
592 bprintf("[(%lu)%s] MC_SNAPSHOT", req->issuer->pid,
593 MSG_host_get_name(req->issuer->smx_host));
595 label = bprintf("[(%lu)] MC_SNAPSHOT", req->issuer->pid);
598 case SIMCALL_MC_COMPARE_SNAPSHOTS:
599 if (req->issuer->smx_host)
601 bprintf("[(%lu)%s] MC_COMPARE_SNAPSHOTS", req->issuer->pid,
602 MSG_host_get_name(req->issuer->smx_host));
604 label = bprintf("[(%lu)] MC_COMPARE_SNAPSHOTS", req->issuer->pid);
612 bprintf("label = \"%s\", color = %s, fontcolor = %s", label,
613 colors[req->issuer->pid - 1], colors[req->issuer->pid - 1]);