Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
539143d711f42f47b9e42e8ca50f504c625587eb
[simgrid.git] / src / mc / mc_request.cpp
1 /* Copyright (c) 2008-2019. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #include "src/mc/mc_request.hpp"
7 #include "src/include/mc/mc.h"
8 #include "src/kernel/activity/CommImpl.hpp"
9 #include "src/kernel/activity/MutexImpl.hpp"
10 #include "src/mc/ModelChecker.hpp"
11 #include "src/mc/mc_smx.hpp"
12
13 using simgrid::mc::remote;
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
16                                 "Logging specific to MC (request)");
17
18 static char *pointer_to_string(void *pointer);
19 static char *buff_size_to_string(size_t size);
20
21 static inline simgrid::kernel::activity::CommImpl* MC_get_comm(smx_simcall_t r)
22 {
23   switch (r->call_) {
24     case SIMCALL_COMM_WAIT:
25       return static_cast<simgrid::kernel::activity::CommImpl*>(simcall_comm_wait__getraw__comm(r));
26     case SIMCALL_COMM_TEST:
27       return static_cast<simgrid::kernel::activity::CommImpl*>(simcall_comm_test__getraw__comm(r));
28     default:
29       return nullptr;
30   }
31 }
32
33 static inline
34 smx_mailbox_t MC_get_mbox(smx_simcall_t r)
35 {
36   switch (r->call_) {
37     case SIMCALL_COMM_ISEND:
38       return simcall_comm_isend__get__mbox(r);
39     case SIMCALL_COMM_IRECV:
40       return simcall_comm_irecv__get__mbox(r);
41     default:
42       return nullptr;
43   }
44 }
45
46 namespace simgrid {
47 namespace mc {
48
49 // Does half the job
50 static inline
51 bool request_depend_asymmetric(smx_simcall_t r1, smx_simcall_t r2)
52 {
53   if (r1->call_ == SIMCALL_COMM_ISEND && r2->call_ == SIMCALL_COMM_IRECV)
54     return false;
55
56   if (r1->call_ == SIMCALL_COMM_IRECV && r2->call_ == SIMCALL_COMM_ISEND)
57     return false;
58
59   // Those are internal requests, we do not need indirection
60   // because those objects are copies:
61   simgrid::kernel::activity::CommImpl* synchro1 = MC_get_comm(r1);
62   simgrid::kernel::activity::CommImpl* synchro2 = MC_get_comm(r2);
63
64   if ((r1->call_ == SIMCALL_COMM_ISEND || r1->call_ == SIMCALL_COMM_IRECV) && r2->call_ == SIMCALL_COMM_WAIT) {
65
66     smx_mailbox_t mbox = MC_get_mbox(r1);
67
68     if (mbox != synchro2->mbox_cpy
69         && simcall_comm_wait__get__timeout(r2) <= 0)
70       return false;
71
72     if ((r1->issuer_ != synchro2->src_actor_.get()) && (r1->issuer_ != synchro2->dst_actor_.get()) &&
73         simcall_comm_wait__get__timeout(r2) <= 0)
74       return false;
75
76     if ((r1->call_ == SIMCALL_COMM_ISEND) && (synchro2->type_ == kernel::activity::CommImpl::Type::SEND) &&
77         (synchro2->src_buff_ != simcall_comm_isend__get__src_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0)
78       return false;
79
80     if ((r1->call_ == SIMCALL_COMM_IRECV) && (synchro2->type_ == kernel::activity::CommImpl::Type::RECEIVE) &&
81         (synchro2->dst_buff_ != simcall_comm_irecv__get__dst_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0)
82       return false;
83   }
84
85   /* FIXME: the following rule assumes that the result of the
86    * isend/irecv call is not stored in a buffer used in the
87    * test call. */
88 #if 0
89   if((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
90      &&  r2->call == SIMCALL_COMM_TEST)
91      return false;
92 #endif
93
94   if (r1->call_ == SIMCALL_COMM_WAIT && (r2->call_ == SIMCALL_COMM_WAIT || r2->call_ == SIMCALL_COMM_TEST) &&
95       (synchro1->src_actor_.get() == nullptr || synchro1->dst_actor_.get() == nullptr))
96     return false;
97
98   if (r1->call_ == SIMCALL_COMM_TEST &&
99       (simcall_comm_test__get__comm(r1) == nullptr || synchro1->src_buff_ == nullptr || synchro1->dst_buff_ == nullptr))
100     return false;
101
102   if (r1->call_ == SIMCALL_COMM_TEST && r2->call_ == SIMCALL_COMM_WAIT && synchro1->src_buff_ == synchro2->src_buff_ &&
103       synchro1->dst_buff_ == synchro2->dst_buff_)
104     return false;
105
106   if (r1->call_ == SIMCALL_COMM_WAIT && r2->call_ == SIMCALL_COMM_TEST && synchro1->src_buff_ != nullptr &&
107       synchro1->dst_buff_ != nullptr && synchro2->src_buff_ != nullptr && synchro2->dst_buff_ != nullptr &&
108       synchro1->dst_buff_ != synchro2->src_buff_ && synchro1->dst_buff_ != synchro2->dst_buff_ &&
109       synchro2->dst_buff_ != synchro1->src_buff_)
110     return false;
111
112   return true;
113 }
114
115 // Those are internal_req
116 bool request_depend(smx_simcall_t req1, smx_simcall_t req2)
117 {
118   if (req1->issuer_ == req2->issuer_)
119     return false;
120
121   /* Wait with timeout transitions are not considered by the independence theorem, thus we consider them as dependent with all other transitions */
122   if ((req1->call_ == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(req1) > 0) ||
123       (req2->call_ == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(req2) > 0))
124     return true;
125
126   if (req1->call_ != req2->call_)
127     return request_depend_asymmetric(req1, req2) && request_depend_asymmetric(req2, req1);
128
129   // Those are internal requests, we do not need indirection
130   // because those objects are copies:
131   simgrid::kernel::activity::CommImpl* synchro1 = MC_get_comm(req1);
132   simgrid::kernel::activity::CommImpl* synchro2 = MC_get_comm(req2);
133
134   switch (req1->call_) {
135     case SIMCALL_COMM_ISEND:
136       return simcall_comm_isend__get__mbox(req1) == simcall_comm_isend__get__mbox(req2);
137     case SIMCALL_COMM_IRECV:
138       return simcall_comm_irecv__get__mbox(req1) == simcall_comm_irecv__get__mbox(req2);
139     case SIMCALL_COMM_WAIT:
140       if (synchro1->src_buff_ == synchro2->src_buff_ && synchro1->dst_buff_ == synchro2->dst_buff_)
141         return false;
142       if (synchro1->src_buff_ != nullptr && synchro1->dst_buff_ != nullptr && synchro2->src_buff_ != nullptr &&
143           synchro2->dst_buff_ != nullptr && synchro1->dst_buff_ != synchro2->src_buff_ &&
144           synchro1->dst_buff_ != synchro2->dst_buff_ && synchro2->dst_buff_ != synchro1->src_buff_)
145         return false;
146       return true;
147     default:
148       return true;
149   }
150 }
151
152 }
153 }
154
155 static char *pointer_to_string(void *pointer)
156 {
157
158   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
159     return bprintf("%p", pointer);
160
161   return xbt_strdup("(verbose only)");
162 }
163
164 static char *buff_size_to_string(size_t buff_size)
165 {
166
167   if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
168     return bprintf("%zu", buff_size);
169
170   return xbt_strdup("(verbose only)");
171 }
172
173
174 std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid::mc::RequestType request_type)
175 {
176   xbt_assert(mc_model_checker != nullptr, "Must be called from MCer");
177
178   if (req->transition_ != nullptr)
179     return req->transition_->to_string();
180
181   bool use_remote_comm = true;
182   switch(request_type) {
183   case simgrid::mc::RequestType::simix:
184     use_remote_comm = true;
185     break;
186   case simgrid::mc::RequestType::executed:
187   case simgrid::mc::RequestType::internal:
188     use_remote_comm = false;
189     break;
190   default:
191     THROW_IMPOSSIBLE;
192   }
193
194   const char* type = nullptr;
195   char *args = nullptr;
196
197   smx_actor_t issuer = MC_smx_simcall_get_issuer(req);
198
199   switch (req->call_) {
200
201     case SIMCALL_COMM_ISEND: {
202       type     = "iSend";
203       char* p  = pointer_to_string(simcall_comm_isend__get__src_buff(req));
204       char* bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
205       if (issuer->get_host())
206         args = bprintf("src=(%ld)%s (%s), buff=%s, size=%s", issuer->get_pid(), MC_smx_actor_get_host_name(issuer),
207                        MC_smx_actor_get_name(issuer), p, bs);
208       else
209         args = bprintf("src=(%ld)%s, buff=%s, size=%s", issuer->get_pid(), MC_smx_actor_get_name(issuer), p, bs);
210       xbt_free(bs);
211       xbt_free(p);
212       break;
213     }
214
215     case SIMCALL_COMM_IRECV: {
216       size_t* remote_size = simcall_comm_irecv__get__dst_buff_size(req);
217       size_t size         = 0;
218       if (remote_size)
219         mc_model_checker->process().read_bytes(&size, sizeof(size), remote(remote_size));
220
221       type     = "iRecv";
222       char* p  = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
223       char* bs = buff_size_to_string(size);
224       if (issuer->get_host())
225         args = bprintf("dst=(%ld)%s (%s), buff=%s, size=%s", issuer->get_pid(), MC_smx_actor_get_host_name(issuer),
226                        MC_smx_actor_get_name(issuer), p, bs);
227       else
228         args = bprintf("dst=(%ld)%s, buff=%s, size=%s", issuer->get_pid(), MC_smx_actor_get_name(issuer), p, bs);
229       xbt_free(bs);
230       xbt_free(p);
231       break;
232     }
233
234     case SIMCALL_COMM_WAIT: {
235       simgrid::kernel::activity::CommImpl* remote_act =
236           static_cast<simgrid::kernel::activity::CommImpl*>(simcall_comm_wait__getraw__comm(req));
237       char* p;
238       if (value == -1) {
239         type = "WaitTimeout";
240         p    = pointer_to_string(remote_act);
241         args = bprintf("comm=%s", p);
242       } else {
243         type = "Wait";
244         p    = pointer_to_string(remote_act);
245
246         simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_synchro;
247         simgrid::kernel::activity::CommImpl* act;
248         if (use_remote_comm) {
249           mc_model_checker->process().read(temp_synchro,
250                                            remote(static_cast<simgrid::kernel::activity::CommImpl*>(remote_act)));
251           act = temp_synchro.get_buffer();
252         } else
253           act = remote_act;
254
255         smx_actor_t src_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(act->src_actor_.get()));
256         smx_actor_t dst_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(act->dst_actor_.get()));
257         args                 = bprintf("comm=%s [(%ld)%s (%s)-> (%ld)%s (%s)]", p, src_proc ? src_proc->get_pid() : 0,
258                        src_proc ? MC_smx_actor_get_host_name(src_proc) : "",
259                        src_proc ? MC_smx_actor_get_name(src_proc) : "", dst_proc ? dst_proc->get_pid() : 0,
260                        dst_proc ? MC_smx_actor_get_host_name(dst_proc) : "",
261                        dst_proc ? MC_smx_actor_get_name(dst_proc) : "");
262       }
263       xbt_free(p);
264       break;
265     }
266
267     case SIMCALL_COMM_TEST: {
268       simgrid::kernel::activity::CommImpl* remote_act =
269           static_cast<simgrid::kernel::activity::CommImpl*>(simcall_comm_test__getraw__comm(req));
270       simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_synchro;
271       simgrid::kernel::activity::CommImpl* act;
272       if (use_remote_comm) {
273         mc_model_checker->process().read(temp_synchro,
274                                          remote(static_cast<simgrid::kernel::activity::CommImpl*>(remote_act)));
275         act = temp_synchro.get_buffer();
276       } else
277         act = remote_act;
278
279       char* p;
280       if (act->src_actor_.get() == nullptr || act->dst_actor_.get() == nullptr) {
281         type = "Test FALSE";
282         p    = pointer_to_string(remote_act);
283         args = bprintf("comm=%s", p);
284       } else {
285         type = "Test TRUE";
286         p    = pointer_to_string(remote_act);
287
288         smx_actor_t src_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(act->src_actor_.get()));
289         smx_actor_t dst_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(act->dst_actor_.get()));
290         args                 = bprintf("comm=%s [(%ld)%s (%s) -> (%ld)%s (%s)]", p, src_proc->get_pid(),
291                        MC_smx_actor_get_name(src_proc), MC_smx_actor_get_host_name(src_proc), dst_proc->get_pid(),
292                        MC_smx_actor_get_name(dst_proc), MC_smx_actor_get_host_name(dst_proc));
293       }
294       xbt_free(p);
295       break;
296     }
297
298     case SIMCALL_COMM_WAITANY: {
299       type         = "WaitAny";
300       size_t count = simcall_comm_waitany__get__count(req);
301       if (count > 0) {
302         simgrid::kernel::activity::CommImpl* remote_sync;
303         remote_sync = mc_model_checker->process().read(remote(simcall_comm_waitany__get__comms(req) + value));
304         char* p     = pointer_to_string(remote_sync);
305         args        = bprintf("comm=%s (%d of %zu)", p, value + 1, count);
306         xbt_free(p);
307       } else
308         args = bprintf("comm at idx %d", value);
309       break;
310     }
311
312     case SIMCALL_COMM_TESTANY:
313       if (value == -1) {
314         type = "TestAny FALSE";
315         args = xbt_strdup("-");
316       } else {
317         type = "TestAny";
318         args = bprintf("(%d of %zu)", value + 1, simcall_comm_testany__get__count(req));
319       }
320       break;
321
322     case SIMCALL_MUTEX_TRYLOCK:
323     case SIMCALL_MUTEX_LOCK: {
324       if (req->call_ == SIMCALL_MUTEX_LOCK)
325         type = "Mutex LOCK";
326       else
327         type = "Mutex TRYLOCK";
328
329       simgrid::mc::Remote<simgrid::kernel::activity::MutexImpl> mutex;
330       mc_model_checker->process().read_bytes(mutex.get_buffer(), sizeof(mutex),
331                                              remote(req->call_ == SIMCALL_MUTEX_LOCK
332                                                         ? simcall_mutex_lock__get__mutex(req)
333                                                         : simcall_mutex_trylock__get__mutex(req)));
334       args = bprintf("locked = %d, owner = %d, sleeping = n/a", mutex.get_buffer()->is_locked(),
335                      mutex.get_buffer()->owner_ != nullptr
336                          ? (int)mc_model_checker->process()
337                                .resolve_actor(simgrid::mc::remote(mutex.get_buffer()->owner_))
338                                ->get_pid()
339                          : -1);
340       break;
341     }
342
343     case SIMCALL_MC_RANDOM:
344       type = "MC_RANDOM";
345       args = bprintf("%d", value);
346       break;
347
348     default:
349       type = SIMIX_simcall_name(req->call_);
350       args = bprintf("??");
351       break;
352   }
353
354   std::string str;
355   if (args != nullptr)
356     str = simgrid::xbt::string_printf("[(%ld)%s (%s)] %s(%s)", issuer->get_pid(), MC_smx_actor_get_host_name(issuer),
357                                       MC_smx_actor_get_name(issuer), type, args);
358   else
359     str = simgrid::xbt::string_printf("[(%ld)%s (%s)] %s ", issuer->get_pid(), MC_smx_actor_get_host_name(issuer),
360                                       MC_smx_actor_get_name(issuer), type);
361   xbt_free(args);
362   return str;
363 }
364
365 namespace simgrid {
366 namespace mc {
367
368 bool request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
369 {
370   simgrid::kernel::activity::CommImpl* remote_act = nullptr;
371   switch (req->call_) {
372
373     case SIMCALL_COMM_WAIT:
374       /* FIXME: check also that src and dst processes are not suspended */
375       remote_act = simcall_comm_wait__getraw__comm(req);
376       break;
377
378     case SIMCALL_COMM_WAITANY:
379       remote_act = mc_model_checker->process().read(remote(simcall_comm_testany__get__comms(req) + idx));
380       break;
381
382     case SIMCALL_COMM_TESTANY:
383       remote_act = mc_model_checker->process().read(remote(simcall_comm_testany__get__comms(req) + idx));
384       break;
385
386     default:
387       return true;
388   }
389
390   simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
391   mc_model_checker->process().read(temp_comm, remote(remote_act));
392   simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
393   return comm->src_actor_.get() && comm->dst_actor_.get();
394 }
395
396
397 static const char* colors[] = {
398   "blue",
399   "red",
400   "green3",
401   "goldenrod",
402   "brown",
403   "purple",
404   "magenta",
405   "turquoise4",
406   "gray25",
407   "forestgreen",
408   "hotpink",
409   "lightblue",
410   "tan",
411 };
412
413 static inline const char* get_color(int id)
414 {
415   return colors[id % (sizeof(colors) / sizeof(colors[0])) ];
416 }
417
418 std::string request_get_dot_output(smx_simcall_t req, int value)
419 {
420   const smx_actor_t issuer = MC_smx_simcall_get_issuer(req);
421   const char* color        = get_color(issuer->get_pid() - 1);
422
423   if (req->transition_ != nullptr)
424     return simgrid::xbt::string_printf("label = \"%s\", color = %s, fontcolor = %s",
425                                        req->transition_->dot_label().c_str(), color, color);
426
427   std::string label;
428
429   switch (req->call_) {
430     case SIMCALL_COMM_ISEND:
431       if (issuer->get_host())
432         label = simgrid::xbt::string_printf("[(%ld)%s] iSend", issuer->get_pid(), MC_smx_actor_get_host_name(issuer));
433       else
434         label = bprintf("[(%ld)] iSend", issuer->get_pid());
435       break;
436
437     case SIMCALL_COMM_IRECV:
438       if (issuer->get_host())
439         label = simgrid::xbt::string_printf("[(%ld)%s] iRecv", issuer->get_pid(), MC_smx_actor_get_host_name(issuer));
440       else
441         label = simgrid::xbt::string_printf("[(%ld)] iRecv", issuer->get_pid());
442       break;
443
444     case SIMCALL_COMM_WAIT:
445       if (value == -1) {
446         if (issuer->get_host())
447           label = simgrid::xbt::string_printf("[(%ld)%s] WaitTimeout", issuer->get_pid(),
448                                               MC_smx_actor_get_host_name(issuer));
449         else
450           label = simgrid::xbt::string_printf("[(%ld)] WaitTimeout", issuer->get_pid());
451       } else {
452         simgrid::kernel::activity::ActivityImpl* remote_act = simcall_comm_wait__getraw__comm(req);
453         simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
454         mc_model_checker->process().read(temp_comm,
455                                          remote(static_cast<simgrid::kernel::activity::CommImpl*>(remote_act)));
456         simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
457
458         smx_actor_t src_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(comm->src_actor_.get()));
459         smx_actor_t dst_proc = mc_model_checker->process().resolve_actor(simgrid::mc::remote(comm->dst_actor_.get()));
460         if (issuer->get_host())
461           label = simgrid::xbt::string_printf("[(%ld)%s] Wait [(%ld)->(%ld)]", issuer->get_pid(),
462                                               MC_smx_actor_get_host_name(issuer), src_proc ? src_proc->get_pid() : 0,
463                                               dst_proc ? dst_proc->get_pid() : 0);
464         else
465           label = simgrid::xbt::string_printf("[(%ld)] Wait [(%ld)->(%ld)]", issuer->get_pid(),
466                                               src_proc ? src_proc->get_pid() : 0, dst_proc ? dst_proc->get_pid() : 0);
467       }
468       break;
469
470     case SIMCALL_COMM_TEST: {
471       simgrid::kernel::activity::ActivityImpl* remote_act = simcall_comm_test__getraw__comm(req);
472       simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
473       mc_model_checker->process().read(temp_comm,
474                                        remote(static_cast<simgrid::kernel::activity::CommImpl*>(remote_act)));
475       simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
476       if (comm->src_actor_.get() == nullptr || comm->dst_actor_.get() == nullptr) {
477         if (issuer->get_host())
478           label = simgrid::xbt::string_printf("[(%ld)%s] Test FALSE", issuer->get_pid(),
479                                               MC_smx_actor_get_host_name(issuer));
480         else
481           label = bprintf("[(%ld)] Test FALSE", issuer->get_pid());
482       } else {
483         if (issuer->get_host())
484           label =
485               simgrid::xbt::string_printf("[(%ld)%s] Test TRUE", issuer->get_pid(), MC_smx_actor_get_host_name(issuer));
486         else
487           label = simgrid::xbt::string_printf("[(%ld)] Test TRUE", issuer->get_pid());
488       }
489       break;
490     }
491
492     case SIMCALL_COMM_WAITANY: {
493       size_t comms_size = simcall_comm_waitany__get__count(req);
494       if (issuer->get_host())
495         label = simgrid::xbt::string_printf("[(%ld)%s] WaitAny [%d of %zu]", issuer->get_pid(),
496                                             MC_smx_actor_get_host_name(issuer), value + 1, comms_size);
497       else
498         label = simgrid::xbt::string_printf("[(%ld)] WaitAny [%d of %zu]", issuer->get_pid(), value + 1, comms_size);
499       break;
500     }
501
502     case SIMCALL_COMM_TESTANY:
503       if (value == -1) {
504         if (issuer->get_host())
505           label = simgrid::xbt::string_printf("[(%ld)%s] TestAny FALSE", issuer->get_pid(),
506                                               MC_smx_actor_get_host_name(issuer));
507         else
508           label = simgrid::xbt::string_printf("[(%ld)] TestAny FALSE", issuer->get_pid());
509       } else {
510         if (issuer->get_host())
511           label = simgrid::xbt::string_printf("[(%ld)%s] TestAny TRUE [%d of %lu]", issuer->get_pid(),
512                                               MC_smx_actor_get_host_name(issuer), value + 1,
513                                               simcall_comm_testany__get__count(req));
514         else
515           label = simgrid::xbt::string_printf("[(%ld)] TestAny TRUE [%d of %lu]", issuer->get_pid(), value + 1,
516                                               simcall_comm_testany__get__count(req));
517       }
518       break;
519
520     case SIMCALL_MUTEX_TRYLOCK:
521       label = simgrid::xbt::string_printf("[(%ld)] Mutex TRYLOCK", issuer->get_pid());
522       break;
523
524     case SIMCALL_MUTEX_LOCK:
525       label = simgrid::xbt::string_printf("[(%ld)] Mutex LOCK", issuer->get_pid());
526       break;
527
528     case SIMCALL_MC_RANDOM:
529       if (issuer->get_host())
530         label = simgrid::xbt::string_printf("[(%ld)%s] MC_RANDOM (%d)", issuer->get_pid(),
531                                             MC_smx_actor_get_host_name(issuer), value);
532       else
533         label = simgrid::xbt::string_printf("[(%ld)] MC_RANDOM (%d)", issuer->get_pid(), value);
534       break;
535
536     default:
537       THROW_UNIMPLEMENTED;
538   }
539
540   return  simgrid::xbt::string_printf(
541         "label = \"%s\", color = %s, fontcolor = %s", label.c_str(),
542         color, color);
543 }
544
545 }
546 }