Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : mutex owner may be NULL after UNLOCK
[simgrid.git] / src / mc / mc_request.c
1 /* Copyright (c) 2008-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include "mc_request.h"
8 #include "mc_safety.h"
9 #include "mc_private.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
12                                 "Logging specific to MC (request)");
13
14 static char *pointer_to_string(void *pointer);
15 static char *buff_size_to_string(size_t size);
16
17 int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
18 {
19   if (mc_reduce_kind == e_mc_reduce_none)
20     return TRUE;
21
22   if (r1->issuer == r2->issuer)
23     return FALSE;
24
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))
29     return TRUE;
30
31   if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
32     return FALSE;
33
34   if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
35     return FALSE;
36
37   if ((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
38       && r2->call == SIMCALL_COMM_WAIT) {
39
40     smx_rdv_t rdv =
41         r1->call ==
42         SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) :
43         simcall_comm_irecv__get__rdv(r1);
44
45     if (rdv != simcall_comm_wait__get__comm(r2)->comm.rdv_cpy
46         && simcall_comm_wait__get__timeout(r2) <= 0)
47       return FALSE;
48
49     if ((r1->issuer != simcall_comm_wait__get__comm(r2)->comm.src_proc)
50         && (r1->issuer != simcall_comm_wait__get__comm(r2)->comm.dst_proc)
51         && simcall_comm_wait__get__timeout(r2) <= 0)
52       return FALSE;
53
54     if ((r1->call == SIMCALL_COMM_ISEND)
55         && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND)
56         && (simcall_comm_wait__get__comm(r2)->comm.src_buff !=
57             simcall_comm_isend__get__src_buff(r1))
58         && simcall_comm_wait__get__timeout(r2) <= 0)
59       return FALSE;
60
61     if ((r1->call == SIMCALL_COMM_IRECV)
62         && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE)
63         && (simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
64             simcall_comm_irecv__get__dst_buff(r1))
65         && simcall_comm_wait__get__timeout(r2) <= 0)
66       return FALSE;
67   }
68
69   if ((r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
70       && r1->call == SIMCALL_COMM_WAIT) {
71
72     smx_rdv_t rdv =
73         r2->call ==
74         SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) :
75         simcall_comm_irecv__get__rdv(r2);
76
77     if (rdv != simcall_comm_wait__get__comm(r1)->comm.rdv_cpy
78         && simcall_comm_wait__get__timeout(r1) <= 0)
79       return FALSE;
80
81     if ((r2->issuer != simcall_comm_wait__get__comm(r1)->comm.src_proc)
82         && (r2->issuer != simcall_comm_wait__get__comm(r1)->comm.dst_proc)
83         && simcall_comm_wait__get__timeout(r1) <= 0)
84       return FALSE;
85
86     if ((r2->call == SIMCALL_COMM_ISEND)
87         && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND)
88         && (simcall_comm_wait__get__comm(r1)->comm.src_buff !=
89             simcall_comm_isend__get__src_buff(r2))
90         && simcall_comm_wait__get__timeout(r1) <= 0)
91       return FALSE;
92
93     if ((r2->call == SIMCALL_COMM_IRECV)
94         && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE)
95         && (simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
96             simcall_comm_irecv__get__dst_buff(r2))
97         && simcall_comm_wait__get__timeout(r1) <= 0)
98       return FALSE;
99   }
100
101   /* FIXME: the following rule assumes that the result of the
102    * isend/irecv call is not stored in a buffer used in the
103    * test call. */
104   /*if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
105      &&  r2->call == SIMCALL_COMM_TEST)
106      return FALSE; */
107
108   /* FIXME: the following rule assumes that the result of the
109    * isend/irecv call is not stored in a buffer used in the
110    * test call.*/
111   /*if(   (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
112      && r1->call == SIMCALL_COMM_TEST)
113      return FALSE; */
114
115   if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
116       && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
117     return FALSE;
118
119   if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
120       && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
121     return FALSE;
122
123   if (r1->call == SIMCALL_COMM_WAIT
124       && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
125       && (simcall_comm_wait__get__comm(r1)->comm.src_proc == NULL
126           || simcall_comm_wait__get__comm(r1)->comm.dst_proc == NULL))
127     return FALSE;
128
129   if (r2->call == SIMCALL_COMM_WAIT
130       && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
131       && (simcall_comm_wait__get__comm(r2)->comm.src_proc == NULL
132           || simcall_comm_wait__get__comm(r2)->comm.dst_proc == NULL))
133     return FALSE;
134
135   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
136       && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
137       simcall_comm_wait__get__comm(r2)->comm.src_buff
138       && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
139       simcall_comm_wait__get__comm(r2)->comm.dst_buff)
140     return FALSE;
141
142   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
143       && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
144       && simcall_comm_wait__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_wait__get__comm(r1)->comm.dst_buff !=
148       simcall_comm_wait__get__comm(r2)->comm.src_buff
149       && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
150       simcall_comm_wait__get__comm(r2)->comm.dst_buff
151       && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
152       simcall_comm_wait__get__comm(r1)->comm.src_buff)
153     return FALSE;
154
155   if (r1->call == SIMCALL_COMM_TEST &&
156       (simcall_comm_test__get__comm(r1) == NULL
157        || simcall_comm_test__get__comm(r1)->comm.src_buff == NULL
158        || simcall_comm_test__get__comm(r1)->comm.dst_buff == NULL))
159     return FALSE;
160
161   if (r2->call == SIMCALL_COMM_TEST &&
162       (simcall_comm_test__get__comm(r2) == NULL
163        || simcall_comm_test__get__comm(r2)->comm.src_buff == NULL
164        || simcall_comm_test__get__comm(r2)->comm.dst_buff == NULL))
165     return FALSE;
166
167   if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
168       && simcall_comm_test__get__comm(r1)->comm.src_buff ==
169       simcall_comm_wait__get__comm(r2)->comm.src_buff
170       && simcall_comm_test__get__comm(r1)->comm.dst_buff ==
171       simcall_comm_wait__get__comm(r2)->comm.dst_buff)
172     return FALSE;
173
174   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
175       && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
176       simcall_comm_test__get__comm(r2)->comm.src_buff
177       && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
178       simcall_comm_test__get__comm(r2)->comm.dst_buff)
179     return FALSE;
180
181   if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
182       && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
183       && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
184       && simcall_comm_test__get__comm(r2)->comm.src_buff != NULL
185       && simcall_comm_test__get__comm(r2)->comm.dst_buff != NULL
186       && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
187       simcall_comm_test__get__comm(r2)->comm.src_buff
188       && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
189       simcall_comm_test__get__comm(r2)->comm.dst_buff
190       && simcall_comm_test__get__comm(r2)->comm.dst_buff !=
191       simcall_comm_wait__get__comm(r1)->comm.src_buff)
192     return FALSE;
193
194   if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
195       && simcall_comm_test__get__comm(r1)->comm.src_buff != NULL
196       && simcall_comm_test__get__comm(r1)->comm.dst_buff != NULL
197       && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
198       && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
199       && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
200       simcall_comm_wait__get__comm(r2)->comm.src_buff
201       && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
202       simcall_comm_wait__get__comm(r2)->comm.dst_buff
203       && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
204       simcall_comm_test__get__comm(r1)->comm.src_buff)
205     return FALSE;
206
207
208   return TRUE;
209 }
210
211 static char *pointer_to_string(void *pointer)
212 {
213
214   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
215     return bprintf("%p", pointer);
216
217   return xbt_strdup("(verbose only)");
218 }
219
220 static char *buff_size_to_string(size_t buff_size)
221 {
222
223   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
224     return bprintf("%zu", buff_size);
225
226   return xbt_strdup("(verbose only)");
227 }
228
229
230 char *MC_request_to_string(smx_simcall_t req, int value)
231 {
232   char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
233   smx_synchro_t act = NULL;
234   smx_mutex_t mutex = NULL;
235   size_t size = 0;
236
237   switch (req->call) {
238   case SIMCALL_COMM_ISEND:
239     type = xbt_strdup("iSend");
240     p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
241     bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
242     if (req->issuer->smx_host)
243       args =
244           bprintf("src=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
245                   MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
246                   p, bs);
247     else
248       args =
249           bprintf("src=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
250                   req->issuer->name, p, bs);
251     break;
252   case SIMCALL_COMM_IRECV:
253     size =
254         simcall_comm_irecv__get__dst_buff_size(req) ?
255         *simcall_comm_irecv__get__dst_buff_size(req) : 0;
256     type = xbt_strdup("iRecv");
257     p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
258     bs = buff_size_to_string(size);
259     if (req->issuer->smx_host)
260       args =
261           bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
262                   MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
263                   p, bs);
264     else
265       args =
266           bprintf("dst=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
267                   req->issuer->name, p, bs);
268     break;
269   case SIMCALL_COMM_WAIT:
270     act = simcall_comm_wait__get__comm(req);
271     if (value == -1) {
272       type = xbt_strdup("WaitTimeout");
273       p = pointer_to_string(act);
274       args = bprintf("comm=%s", p);
275     } else {
276       type = xbt_strdup("Wait");
277       p = pointer_to_string(act);
278       args = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
279                      act->comm.src_proc ? act->comm.src_proc->pid : 0,
280                      act->comm.src_proc ? MSG_host_get_name(act->comm.src_proc->
281                                                             smx_host) : "",
282                      act->comm.src_proc ? act->comm.src_proc->name : "",
283                      act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
284                      act->comm.dst_proc ? MSG_host_get_name(act->comm.dst_proc->
285                                                             smx_host) : "",
286                      act->comm.dst_proc ? act->comm.dst_proc->name : "");
287     }
288     break;
289   case SIMCALL_COMM_TEST:
290     act = simcall_comm_test__get__comm(req);
291     if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
292       type = xbt_strdup("Test FALSE");
293       p = pointer_to_string(act);
294       args = bprintf("comm=%s", p);
295     } else {
296       type = xbt_strdup("Test TRUE");
297       p = pointer_to_string(act);
298       args = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
299                      act->comm.src_proc->pid, act->comm.src_proc->name,
300                      MSG_host_get_name(act->comm.src_proc->smx_host),
301                      act->comm.dst_proc->pid, act->comm.dst_proc->name,
302                      MSG_host_get_name(act->comm.dst_proc->smx_host));
303     }
304     break;
305
306   case SIMCALL_COMM_WAITANY:
307     type = xbt_strdup("WaitAny");
308     if (!xbt_dynar_is_empty(simcall_comm_waitany__get__comms(req))) {
309       p = pointer_to_string(xbt_dynar_get_as
310                             (simcall_comm_waitany__get__comms(req), value,
311                              smx_synchro_t));
312       args =
313           bprintf("comm=%s (%d of %lu)", p, value + 1,
314                   xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
315     } else {
316       args = bprintf("comm at idx %d", value);
317     }
318     break;
319
320   case SIMCALL_COMM_TESTANY:
321     if (value == -1) {
322       type = xbt_strdup("TestAny FALSE");
323       args = xbt_strdup("-");
324     } else {
325       type = xbt_strdup("TestAny");
326       args =
327           bprintf("(%d of %lu)", value + 1,
328                   xbt_dynar_length(simcall_comm_testany__get__comms(req)));
329     }
330     break;
331
332   case SIMCALL_MUTEX_LOCK:
333     mutex = simcall_mutex_lock__get__mutex(req);
334     type = xbt_strdup("Mutex LOCK");
335     args = bprintf("locked = %d, owner = %d, sleeping = %d", mutex->locked, mutex->owner != NULL ? (int)mutex->owner->pid : -1, xbt_swag_size(mutex->sleeping));
336     break;
337
338   case SIMCALL_MUTEX_UNLOCK:
339     type = xbt_strdup("Mutex UNLOCK");
340     mutex = simcall_mutex_unlock__get__mutex(req);
341     args = bprintf("locked = %d, owner = %d, sleeping = %d", mutex->locked, mutex->owner != NULL ? (int)mutex->owner->pid : -1, xbt_swag_size(mutex->sleeping));
342     break;
343
344   case SIMCALL_MC_SNAPSHOT:
345     type = xbt_strdup("MC_SNAPSHOT");
346     args = NULL;
347     break;
348
349   case SIMCALL_MC_COMPARE_SNAPSHOTS:
350     type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
351     args = NULL;
352     break;
353
354   case SIMCALL_MC_RANDOM:
355     type = xbt_strdup("MC_RANDOM");
356     args = bprintf("%d", value);
357     break;
358
359   default:
360     THROW_UNIMPLEMENTED;
361   }
362
363   if (args != NULL) {
364     str =
365         bprintf("[(%lu)%s (%s)] %s(%s)", req->issuer->pid,
366                 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
367                 type, args);
368   } else {
369     str =
370         bprintf("[(%lu)%s (%s)] %s ", req->issuer->pid,
371                 MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
372                 type);
373   }
374
375   xbt_free(args);
376   xbt_free(type);
377   xbt_free(p);
378   xbt_free(bs);
379   return str;
380 }
381
382 unsigned int MC_request_testany_fail(smx_simcall_t req)
383 {
384   unsigned int cursor;
385   smx_synchro_t action;
386
387   xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action) {
388     if (action->comm.src_proc && action->comm.dst_proc)
389       return FALSE;
390   }
391
392   return TRUE;
393 }
394
395 int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
396 {
397   smx_synchro_t act;
398
399   switch (req->call) {
400
401   case SIMCALL_COMM_WAIT:
402     /* FIXME: check also that src and dst processes are not suspended */
403     act = simcall_comm_wait__get__comm(req);
404     return (act->comm.src_proc && act->comm.dst_proc);
405     break;
406
407   case SIMCALL_COMM_WAITANY:
408     act =
409         xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx,
410                          smx_synchro_t);
411     return (act->comm.src_proc && act->comm.dst_proc);
412     break;
413
414   case SIMCALL_COMM_TESTANY:
415     act =
416         xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx,
417                          smx_synchro_t);
418     return (act->comm.src_proc && act->comm.dst_proc);
419     break;
420
421   default:
422     return TRUE;
423   }
424 }
425
426 int MC_process_is_enabled(smx_process_t process)
427 {
428   return MC_request_is_enabled(&process->simcall);
429 }
430
431 char *MC_request_get_dot_output(smx_simcall_t req, int value)
432 {
433
434   char *str = NULL, *label = NULL;
435   smx_synchro_t act = NULL;
436   
437   switch (req->call) {
438   case SIMCALL_COMM_ISEND:
439     if (req->issuer->smx_host)
440       label =
441           bprintf("[(%lu)%s] iSend", req->issuer->pid,
442                   MSG_host_get_name(req->issuer->smx_host));
443     else
444       label = bprintf("[(%lu)] iSend", req->issuer->pid);
445     break;
446
447   case SIMCALL_COMM_IRECV:
448     if (req->issuer->smx_host)
449       label =
450           bprintf("[(%lu)%s] iRecv", req->issuer->pid,
451                   MSG_host_get_name(req->issuer->smx_host));
452     else
453       label = bprintf("[(%lu)] iRecv", req->issuer->pid);
454     break;
455
456   case SIMCALL_COMM_WAIT:
457     act = simcall_comm_wait__get__comm(req);
458     if (value == -1) {
459       if (req->issuer->smx_host)
460         label =
461             bprintf("[(%lu)%s] WaitTimeout", req->issuer->pid,
462                     MSG_host_get_name(req->issuer->smx_host));
463       else
464         label = bprintf("[(%lu)] WaitTimeout", req->issuer->pid);
465     } else {
466       if (req->issuer->smx_host)
467         label =
468             bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", req->issuer->pid,
469                     MSG_host_get_name(req->issuer->smx_host),
470                     act->comm.src_proc ? act->comm.src_proc->pid : 0,
471                     act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
472       else
473         label =
474             bprintf("[(%lu)] Wait [(%lu)->(%lu)]", req->issuer->pid,
475                     act->comm.src_proc ? act->comm.src_proc->pid : 0,
476                     act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
477     }
478     break;
479
480   case SIMCALL_COMM_TEST:
481     act = simcall_comm_test__get__comm(req);
482     if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
483       if (req->issuer->smx_host)
484         label =
485             bprintf("[(%lu)%s] Test FALSE", req->issuer->pid,
486                     MSG_host_get_name(req->issuer->smx_host));
487       else
488         label = bprintf("[(%lu)] Test FALSE", req->issuer->pid);
489     } else {
490       if (req->issuer->smx_host)
491         label =
492             bprintf("[(%lu)%s] Test TRUE", req->issuer->pid,
493                     MSG_host_get_name(req->issuer->smx_host));
494       else
495         label = bprintf("[(%lu)] Test TRUE", req->issuer->pid);
496     }
497     break;
498
499   case SIMCALL_COMM_WAITANY:
500     if (req->issuer->smx_host)
501       label =
502           bprintf("[(%lu)%s] WaitAny [%d of %lu]", req->issuer->pid,
503                   MSG_host_get_name(req->issuer->smx_host), value + 1,
504                   xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
505     else
506       label =
507           bprintf("[(%lu)] WaitAny [%d of %lu]", req->issuer->pid, value + 1,
508                   xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
509     break;
510
511   case SIMCALL_COMM_TESTANY:
512     if (value == -1) {
513       if (req->issuer->smx_host)
514         label =
515             bprintf("[(%lu)%s] TestAny FALSE", req->issuer->pid,
516                     MSG_host_get_name(req->issuer->smx_host));
517       else
518         label = bprintf("[(%lu)] TestAny FALSE", req->issuer->pid);
519     } else {
520       if (req->issuer->smx_host)
521         label =
522             bprintf("[(%lu)%s] TestAny TRUE [%d of %lu]", req->issuer->pid,
523                     MSG_host_get_name(req->issuer->smx_host), value + 1,
524                     xbt_dynar_length(simcall_comm_testany__get__comms(req)));
525       else
526         label =
527             bprintf("[(%lu)] TestAny TRUE [%d of %lu]", req->issuer->pid,
528                     value + 1,
529                     xbt_dynar_length(simcall_comm_testany__get__comms(req)));
530     }
531     break;
532
533   case SIMCALL_MUTEX_LOCK:
534     label = bprintf("[(%lu)] Mutex LOCK", req->issuer->pid);
535     break;
536     
537   case SIMCALL_MUTEX_UNLOCK:
538     label = bprintf("[(%lu)] Mutex UNLOCK", req->issuer->pid);
539     break;
540
541   case SIMCALL_MC_RANDOM:
542     if (req->issuer->smx_host)
543       label =
544           bprintf("[(%lu)%s] MC_RANDOM (%d)", req->issuer->pid,
545                   MSG_host_get_name(req->issuer->smx_host), value);
546     else
547       label = bprintf("[(%lu)] MC_RANDOM (%d)", req->issuer->pid, value);
548     break;
549
550   case SIMCALL_MC_SNAPSHOT:
551     if (req->issuer->smx_host)
552       label =
553           bprintf("[(%lu)%s] MC_SNAPSHOT", req->issuer->pid,
554                   MSG_host_get_name(req->issuer->smx_host));
555     else
556       label = bprintf("[(%lu)] MC_SNAPSHOT", req->issuer->pid);
557     break;
558
559   case SIMCALL_MC_COMPARE_SNAPSHOTS:
560     if (req->issuer->smx_host)
561       label =
562           bprintf("[(%lu)%s] MC_COMPARE_SNAPSHOTS", req->issuer->pid,
563                   MSG_host_get_name(req->issuer->smx_host));
564     else
565       label = bprintf("[(%lu)] MC_COMPARE_SNAPSHOTS", req->issuer->pid);
566     break;
567
568   default:
569     THROW_UNIMPLEMENTED;
570   }
571
572   str =
573       bprintf("label = \"%s\", color = %s, fontcolor = %s", label,
574               colors[req->issuer->pid - 1], colors[req->issuer->pid - 1]);
575   xbt_free(label);
576   return str;
577
578 }