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) {
15 if(mc_reduce_kind == e_mc_reduce_none)
19 if (r1->issuer == r2->issuer)
22 if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
25 if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
28 if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
29 && r2->call == SIMCALL_COMM_WAIT){
31 if(r2->comm_wait.comm->comm.rdv == NULL)
34 smx_rdv_t rdv = r1->call == SIMCALL_COMM_ISEND ? r1->comm_isend.rdv : r1->comm_irecv.rdv;
36 if(r2->comm_wait.comm->comm.rdv != rdv)
39 if(r2->comm_wait.comm->comm.type == SIMIX_COMM_SEND && r1->call == SIMCALL_COMM_ISEND)
42 if(r2->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r1->call == SIMCALL_COMM_IRECV)
46 if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
47 && r1->call == SIMCALL_COMM_WAIT){
49 if(r1->comm_wait.comm->comm.rdv != NULL)
52 smx_rdv_t rdv = r2->call == SIMCALL_COMM_ISEND ? r2->comm_isend.rdv : r2->comm_irecv.rdv;
54 if(r1->comm_wait.comm->comm.rdv != rdv)
57 if(r1->comm_wait.comm->comm.type == SIMIX_COMM_SEND && r2->call == SIMCALL_COMM_ISEND)
60 if(r1->comm_wait.comm->comm.type == SIMIX_COMM_RECEIVE && r2->call == SIMCALL_COMM_IRECV)
64 /* FIXME: the following rule assumes that the result of the
65 * isend/irecv call is not stored in a buffer used in the
67 if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
68 && r2->call == SIMCALL_COMM_TEST)
71 /* FIXME: the following rule assumes that the result of the
72 * isend/irecv call is not stored in a buffer used in the
74 if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
75 && r1->call == SIMCALL_COMM_TEST)
78 if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
79 && r1->comm_isend.rdv != r2->comm_isend.rdv)
82 if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
83 && r1->comm_irecv.rdv != r2->comm_irecv.rdv)
86 if(r1->call == SIMCALL_COMM_WAIT && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
87 && (r1->comm_wait.comm->comm.src_proc == NULL
88 || r1->comm_wait.comm->comm.dst_proc == NULL))
91 if(r2->call == SIMCALL_COMM_WAIT && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
92 && (r2->comm_wait.comm->comm.src_proc == NULL
93 || r2->comm_wait.comm->comm.dst_proc == NULL))
96 if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
97 && r1->comm_wait.comm->comm.src_buff == r2->comm_wait.comm->comm.src_buff
98 && r1->comm_wait.comm->comm.dst_buff == r2->comm_wait.comm->comm.dst_buff)
101 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
102 && r1->comm_wait.comm->comm.src_buff != NULL
103 && r1->comm_wait.comm->comm.dst_buff != NULL
104 && r2->comm_wait.comm->comm.src_buff != NULL
105 && r2->comm_wait.comm->comm.dst_buff != NULL
106 && r1->comm_wait.comm->comm.dst_buff != r2->comm_wait.comm->comm.src_buff
107 && r1->comm_wait.comm->comm.dst_buff != r2->comm_wait.comm->comm.dst_buff
108 && r2->comm_wait.comm->comm.dst_buff != r1->comm_wait.comm->comm.src_buff)
111 if(r1->call == SIMCALL_COMM_TEST &&
112 (r1->comm_test.comm == NULL
113 || r1->comm_test.comm->comm.src_buff == NULL
114 || r1->comm_test.comm->comm.dst_buff == NULL))
117 if(r2->call == SIMCALL_COMM_TEST &&
118 (r2->comm_test.comm == NULL
119 || r2->comm_test.comm->comm.src_buff == NULL
120 || r2->comm_test.comm->comm.dst_buff == NULL))
123 if(r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
124 && r1->comm_test.comm->comm.src_buff == r2->comm_wait.comm->comm.src_buff
125 && r1->comm_test.comm->comm.dst_buff == r2->comm_wait.comm->comm.dst_buff)
128 if(r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
129 && r1->comm_wait.comm->comm.src_buff == r2->comm_test.comm->comm.src_buff
130 && r1->comm_wait.comm->comm.dst_buff == r2->comm_test.comm->comm.dst_buff)
133 if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
134 && r1->comm_wait.comm->comm.src_buff != NULL
135 && r1->comm_wait.comm->comm.dst_buff != NULL
136 && r2->comm_test.comm->comm.src_buff != NULL
137 && r2->comm_test.comm->comm.dst_buff != NULL
138 && r1->comm_wait.comm->comm.dst_buff != r2->comm_test.comm->comm.src_buff
139 && r1->comm_wait.comm->comm.dst_buff != r2->comm_test.comm->comm.dst_buff
140 && r2->comm_test.comm->comm.dst_buff != r1->comm_wait.comm->comm.src_buff)
143 if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
144 && r1->comm_test.comm->comm.src_buff != NULL
145 && r1->comm_test.comm->comm.dst_buff != NULL
146 && r2->comm_wait.comm->comm.src_buff != NULL
147 && r2->comm_wait.comm->comm.dst_buff != NULL
148 && r1->comm_test.comm->comm.dst_buff != r2->comm_wait.comm->comm.src_buff
149 && r1->comm_test.comm->comm.dst_buff != r2->comm_wait.comm->comm.dst_buff
150 && r2->comm_wait.comm->comm.dst_buff != r1->comm_test.comm->comm.src_buff)
157 static char* pointer_to_string(void* pointer) {
159 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
160 return bprintf("%p", pointer);
162 return xbt_strdup("(verbose only)");
165 static char* buff_size_to_string(size_t buff_size) {
167 if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
168 return bprintf("%zu", buff_size);
170 return xbt_strdup("(verbose only)");
174 char *MC_request_to_string(smx_simcall_t req, int value)
176 char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
177 smx_action_t act = NULL;
181 case SIMCALL_COMM_ISEND:
182 type = xbt_strdup("iSend");
183 p = pointer_to_string(req->comm_isend.src_buff);
184 bs = buff_size_to_string(req->comm_isend.src_buff_size);
185 args = bprintf("src=%s, buff=%s, size=%s", req->issuer->name, p, bs);
187 case SIMCALL_COMM_IRECV:
188 size = req->comm_irecv.dst_buff_size ? *req->comm_irecv.dst_buff_size : 0;
189 type = xbt_strdup("iRecv");
190 p = pointer_to_string(req->comm_irecv.dst_buff);
191 bs = buff_size_to_string(size);
192 args = bprintf("dst=%s, buff=%s, size=%s", req->issuer->name, p, bs);
194 case SIMCALL_COMM_WAIT:
195 act = req->comm_wait.comm;
197 type = xbt_strdup("WaitTimeout");
198 p = pointer_to_string(act);
199 args = bprintf("comm=%p", p);
201 type = xbt_strdup("Wait");
202 p = pointer_to_string(act);
203 args = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
204 act->comm.src_proc ? act->comm.src_proc->pid : 0,
205 act->comm.src_proc ? act->comm.src_proc->name : "",
206 act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
207 act->comm.dst_proc ? act->comm.dst_proc->name : "");
210 case SIMCALL_COMM_TEST:
211 act = req->comm_test.comm;
212 if(act->comm.src_proc == NULL || act->comm.dst_proc == NULL){
213 type = xbt_strdup("Test FALSE");
214 p = pointer_to_string(act);
215 args = bprintf("comm=%s", p);
217 type = xbt_strdup("Test TRUE");
218 p = pointer_to_string(act);
219 args = bprintf("comm=%s [(%lu)%s -> (%lu)%s]", p,
220 act->comm.src_proc->pid, act->comm.src_proc->name,
221 act->comm.dst_proc->pid, act->comm.dst_proc->name);
225 case SIMCALL_COMM_WAITANY:
226 type = xbt_strdup("WaitAny");
227 p = pointer_to_string(xbt_dynar_get_as(req->comm_waitany.comms, value, smx_action_t));
228 args = bprintf("comm=%s (%d of %lu)", p,
229 value+1, xbt_dynar_length(req->comm_waitany.comms));
232 case SIMCALL_COMM_TESTANY:
234 type = xbt_strdup("TestAny FALSE");
235 args = xbt_strdup("-");
237 type = xbt_strdup("TestAny");
238 args = bprintf("(%d of %lu)", value+1, xbt_dynar_length(req->comm_testany.comms));
246 str = bprintf("[(%lu)%s] %s (%s)", req->issuer->pid ,req->issuer->name, type, args);
254 unsigned int MC_request_testany_fail(smx_simcall_t req)
259 xbt_dynar_foreach(req->comm_testany.comms, cursor, action){
260 if(action->comm.src_proc && action->comm.dst_proc)
267 int MC_request_is_visible(smx_simcall_t req)
269 return req->call == SIMCALL_COMM_ISEND
270 || req->call == SIMCALL_COMM_IRECV
271 || req->call == SIMCALL_COMM_WAIT
272 || req->call == SIMCALL_COMM_WAITANY
273 || req->call == SIMCALL_COMM_TEST
274 || req->call == SIMCALL_COMM_TESTANY;
277 int MC_request_is_enabled(smx_simcall_t req)
279 unsigned int index = 0;
284 case SIMCALL_COMM_WAIT:
285 /* FIXME: check also that src and dst processes are not suspended */
287 /* If it has a timeout it will be always be enabled, because even if the
288 * communication is not ready, it can timeout and won't block.
289 * On the other hand if it hasn't a timeout, check if the comm is ready.*/
290 if(req->comm_wait.timeout >= 0){
293 act = req->comm_wait.comm;
294 return (act->comm.src_proc && act->comm.dst_proc);
298 case SIMCALL_COMM_WAITANY:
299 /* Check if it has at least one communication ready */
300 xbt_dynar_foreach(req->comm_waitany.comms, index, act) {
301 if (act->comm.src_proc && act->comm.dst_proc){
309 /* The rest of the request are always enabled */
314 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
320 case SIMCALL_COMM_WAIT:
321 /* FIXME: check also that src and dst processes are not suspended */
322 act = req->comm_wait.comm;
323 return (act->comm.src_proc && act->comm.dst_proc);
326 case SIMCALL_COMM_WAITANY:
327 act = xbt_dynar_get_as(req->comm_waitany.comms, idx, smx_action_t);
328 return (act->comm.src_proc && act->comm.dst_proc);
331 case SIMCALL_COMM_TESTANY:
332 act = xbt_dynar_get_as(req->comm_testany.comms, idx, smx_action_t);
333 return (act->comm.src_proc && act->comm.dst_proc);
341 int MC_process_is_enabled(smx_process_t process)
343 if (process->simcall.call != SIMCALL_NONE && MC_request_is_enabled(&process->simcall))