1 /* Copyright (c) 2008-2012 Da SimGrid Team. All rights reserved. */
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. */
6 #include "mc_private.h"
8 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
9 "Logging specific to MC (request)");
11 static char* pointer_to_string(void* pointer);
12 static char* buff_size_to_string(size_t size);
14 int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
16 if(_surf_do_model_check == 2)
20 if (r1->issuer == r2->issuer)
23 if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
26 if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
29 if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
30 && r2->call == SIMCALL_COMM_WAIT){
32 if(r2->comm_wait.comm->comm.rdv == NULL)
35 smx_rdv_t rdv = r1->call == SIMCALL_COMM_ISEND ? r1->comm_isend.rdv : r1->comm_irecv.rdv;
37 if(r2->comm_wait.comm->comm.rdv != rdv)
40 if(r2->comm_wait.comm->comm.type == SIMIX_COMM_SEND && r1->call == SIMCALL_COMM_ISEND)
43 if(r2->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r1->call == SIMCALL_COMM_IRECV)
47 if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
48 && r1->call == SIMCALL_COMM_WAIT){
50 if(r1->comm_wait.comm->comm.rdv != NULL)
53 smx_rdv_t rdv = r2->call == SIMCALL_COMM_ISEND ? r2->comm_isend.rdv : r2->comm_irecv.rdv;
55 if(r1->comm_wait.comm->comm.rdv != rdv)
58 if(r1->comm_wait.comm->comm.type == SIMIX_COMM_SEND && r2->call == SIMCALL_COMM_ISEND)
61 if(r1->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r2->call == SIMCALL_COMM_IRECV)
65 /* FIXME: the following rule assumes that the result of the
66 * isend/irecv call is not stored in a buffer used in the
68 if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
69 && r2->call == SIMCALL_COMM_TEST)
72 /* FIXME: the following rule assumes that the result of the
73 * isend/irecv call is not stored in a buffer used in the
75 if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
76 && r1->call == SIMCALL_COMM_TEST)
79 if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
80 && r1->comm_isend.rdv != r2->comm_isend.rdv)
83 if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
84 && r1->comm_irecv.rdv != r2->comm_irecv.rdv)
87 if(r1->call == SIMCALL_COMM_WAIT && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
88 && (r1->comm_wait.comm->comm.src_proc == NULL
89 || r1->comm_wait.comm->comm.dst_proc == NULL))
92 if(r2->call == SIMCALL_COMM_WAIT && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
93 && (r2->comm_wait.comm->comm.src_proc == NULL
94 || r2->comm_wait.comm->comm.dst_proc == NULL))
97 if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
98 && r1->comm_wait.comm->comm.src_buff == r2->comm_wait.comm->comm.src_buff
99 && r1->comm_wait.comm->comm.dst_buff == r2->comm_wait.comm->comm.dst_buff)
102 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
103 && r1->comm_wait.comm->comm.src_buff != NULL
104 && r1->comm_wait.comm->comm.dst_buff != NULL
105 && r2->comm_wait.comm->comm.src_buff != NULL
106 && r2->comm_wait.comm->comm.dst_buff != NULL
107 && r1->comm_wait.comm->comm.dst_buff != r2->comm_wait.comm->comm.src_buff
108 && r1->comm_wait.comm->comm.dst_buff != r2->comm_wait.comm->comm.dst_buff
109 && r2->comm_wait.comm->comm.dst_buff != r1->comm_wait.comm->comm.src_buff)
112 if(r1->call == SIMCALL_COMM_TEST &&
113 (r1->comm_test.comm == NULL
114 || r1->comm_test.comm->comm.src_buff == NULL
115 || r1->comm_test.comm->comm.dst_buff == NULL))
118 if(r2->call == SIMCALL_COMM_TEST &&
119 (r2->comm_test.comm == NULL
120 || r2->comm_test.comm->comm.src_buff == NULL
121 || r2->comm_test.comm->comm.dst_buff == NULL))
124 if(r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
125 && r1->comm_test.comm->comm.src_buff == r2->comm_wait.comm->comm.src_buff
126 && r1->comm_test.comm->comm.dst_buff == r2->comm_wait.comm->comm.dst_buff)
129 if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
130 && r1->comm_wait.comm->comm.src_buff == r2->comm_test.comm->comm.src_buff
131 && r1->comm_wait.comm->comm.dst_buff == r2->comm_test.comm->comm.dst_buff)
134 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
135 && r1->comm_wait.comm->comm.src_buff != NULL
136 && r1->comm_wait.comm->comm.dst_buff != NULL
137 && r2->comm_test.comm->comm.src_buff != NULL
138 && r2->comm_test.comm->comm.dst_buff != NULL
139 && r1->comm_wait.comm->comm.dst_buff != r2->comm_test.comm->comm.src_buff
140 && r1->comm_wait.comm->comm.dst_buff != r2->comm_test.comm->comm.dst_buff
141 && r2->comm_test.comm->comm.dst_buff != r1->comm_wait.comm->comm.src_buff)
144 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
145 && r1->comm_test.comm->comm.src_buff != NULL
146 && r1->comm_test.comm->comm.dst_buff != NULL
147 && r2->comm_wait.comm->comm.src_buff != NULL
148 && r2->comm_wait.comm->comm.dst_buff != NULL
149 && r1->comm_test.comm->comm.dst_buff != r2->comm_wait.comm->comm.src_buff
150 && r1->comm_test.comm->comm.dst_buff != r2->comm_wait.comm->comm.dst_buff
151 && r2->comm_wait.comm->comm.dst_buff != r1->comm_test.comm->comm.src_buff)
158 static char* pointer_to_string(void* pointer) {
160 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
161 return bprintf("%p", pointer);
163 return xbt_strdup("(verbose only)");
166 static char* buff_size_to_string(size_t buff_size) {
168 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
169 return bprintf("%zu", buff_size);
171 return xbt_strdup("(verbose only)");
175 char *MC_request_to_string(smx_simcall_t req, int value)
177 char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
178 smx_action_t act = NULL;
182 case SIMCALL_COMM_ISEND:
183 type = xbt_strdup("iSend");
184 p = pointer_to_string(req->comm_isend.src_buff);
185 bs = buff_size_to_string(req->comm_isend.src_buff_size);
186 args = bprintf("src=%s, buff=%s, size=%s", req->issuer->name, p, bs);
188 case SIMCALL_COMM_IRECV:
189 size = req->comm_irecv.dst_buff_size ? *req->comm_irecv.dst_buff_size : 0;
190 type = xbt_strdup("iRecv");
191 p = pointer_to_string(req->comm_irecv.dst_buff);
192 bs = buff_size_to_string(size);
193 args = bprintf("dst=%s, buff=%s, size=%s", req->issuer->name, p, bs);
195 case SIMCALL_COMM_WAIT:
196 act = req->comm_wait.comm;
198 type = xbt_strdup("WaitTimeout");
199 p = pointer_to_string(act);
200 args = bprintf("comm=%p", p);
202 type = xbt_strdup("Wait");
203 p = pointer_to_string(act);
204 args = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
205 act->comm.src_proc ? act->comm.src_proc->pid : 0,
206 act->comm.src_proc ? act->comm.src_proc->name : "",
207 act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
208 act->comm.dst_proc ? act->comm.dst_proc->name : "");
211 case SIMCALL_COMM_TEST:
212 act = req->comm_test.comm;
213 if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL){
214 type = xbt_strdup("Test FALSE");
215 p = pointer_to_string(act);
216 args = bprintf("comm=%s", p);
218 type = xbt_strdup("Test TRUE");
219 p = pointer_to_string(act);
220 args = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
221 act->comm.src_proc->pid, act->comm.src_proc->name,
222 act->comm.dst_proc->pid, act->comm.dst_proc->name);
226 case SIMCALL_COMM_WAITANY:
227 type = xbt_strdup("WaitAny");
228 p = pointer_to_string(xbt_dynar_get_as(req->comm_waitany.comms, value, smx_action_t));
229 args = bprintf("comm=%s (%d of %lu)", p,
230 value+1, xbt_dynar_length(req->comm_waitany.comms));
233 case SIMCALL_COMM_TESTANY:
235 type = xbt_strdup("TestAny FALSE");
236 args = xbt_strdup("-");
238 type = xbt_strdup("TestAny");
239 args = bprintf("(%d of %lu)", value+1, xbt_dynar_length(req->comm_testany.comms));
247 str = bprintf("[(%lu)%s] %s (%s)", req->issuer->pid ,req->issuer->name, type, args);
255 unsigned int MC_request_testany_fail(smx_simcall_t req)
260 xbt_dynar_foreach(req->comm_testany.comms, cursor, action){
261 if(action->comm.src_proc && action->comm.dst_proc)
268 int MC_request_is_visible(smx_simcall_t req)
270 return req->call == SIMCALL_COMM_ISEND
271 || req->call == SIMCALL_COMM_IRECV
272 || req->call == SIMCALL_COMM_WAIT
273 || req->call == SIMCALL_COMM_WAITANY
274 || req->call == SIMCALL_COMM_TEST
275 || req->call == SIMCALL_COMM_TESTANY;
278 int MC_request_is_enabled(smx_simcall_t req)
280 unsigned int index = 0;
285 case SIMCALL_COMM_WAIT:
286 /* FIXME: check also that src and dst processes are not suspended */
288 /* If it has a timeout it will be always be enabled, because even if the
289 * communication is not ready, it can timeout and won't block.
290 * On the other hand if it hasn't a timeout, check if the comm is ready.*/
291 if(req->comm_wait.timeout >= 0){
294 act = req->comm_wait.comm;
295 return (act->comm.src_proc && act->comm.dst_proc);
299 case SIMCALL_COMM_WAITANY:
300 /* Check if it has at least one communication ready */
301 xbt_dynar_foreach(req->comm_waitany.comms, index, act) {
302 if (act->comm.src_proc && act->comm.dst_proc){
310 /* The rest of the request are always enabled */
315 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
321 case SIMCALL_COMM_WAIT:
322 /* FIXME: check also that src and dst processes are not suspended */
323 act = req->comm_wait.comm;
324 return (act->comm.src_proc && act->comm.dst_proc);
327 case SIMCALL_COMM_WAITANY:
328 act = xbt_dynar_get_as(req->comm_waitany.comms, idx, smx_action_t);
329 return (act->comm.src_proc && act->comm.dst_proc);
332 case SIMCALL_COMM_TESTANY:
333 act = xbt_dynar_get_as(req->comm_testany.comms, idx, smx_action_t);
334 return (act->comm.src_proc && act->comm.dst_proc);
342 int MC_process_is_enabled(smx_process_t process)
344 if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))