@@ -292,14 +292,61 @@ static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
292
292
// / counterexample witness
293
293
void graphml_witnesst::operator ()(const goto_tracet &goto_trace)
294
294
{
295
+ unsigned int max_thread_idx = 0 ;
296
+ bool trace_has_violation = false ;
297
+ for (goto_tracet::stepst::const_iterator it = goto_trace.steps .begin ();
298
+ it != goto_trace.steps .end ();
299
+ ++it)
300
+ {
301
+ if (it->thread_nr > max_thread_idx)
302
+ max_thread_idx = it->thread_nr ;
303
+ if (it->is_assert () && !it->cond_value )
304
+ trace_has_violation = true ;
305
+ }
306
+
295
307
graphml.key_values [" sourcecodelang" ]=" C" ;
296
308
297
309
const graphmlt::node_indext sink=graphml.add_node ();
298
310
graphml[sink].node_name =" sink" ;
299
- graphml[sink].thread_nr =0 ;
300
311
graphml[sink].is_violation =false ;
301
312
graphml[sink].has_invariant =false ;
302
313
314
+ if (max_thread_idx > 0 && trace_has_violation)
315
+ {
316
+ std::vector<graphmlt::node_indext> nodes;
317
+
318
+ for (unsigned int i = 0 ; i <= max_thread_idx + 1 ; ++i)
319
+ {
320
+ nodes.push_back (graphml.add_node ());
321
+ graphml[nodes.back ()].node_name = " N" + std::to_string (i);
322
+ graphml[nodes.back ()].is_violation = i == max_thread_idx + 1 ;
323
+ graphml[nodes.back ()].has_invariant = false ;
324
+ }
325
+
326
+ for (auto it = nodes.cbegin (); std::next (it) != nodes.cend (); ++it)
327
+ {
328
+ xmlt edge (" edge" );
329
+ edge.set_attribute (" source" , graphml[*it].node_name );
330
+ edge.set_attribute (" target" , graphml[*std::next (it)].node_name );
331
+ const auto thread_id = std::distance (nodes.cbegin (), it);
332
+ xmlt &data = edge.new_element (" data" );
333
+ data.set_attribute (" key" , " createThread" );
334
+ data.data = std::to_string (thread_id);
335
+ if (thread_id == 0 )
336
+ {
337
+ xmlt &data = edge.new_element (" data" );
338
+ data.set_attribute (" key" , " enterFunction" );
339
+ data.data = " main" ;
340
+ }
341
+ graphml[*std::next (it)].in [*it].xml_node = edge;
342
+ graphml[*it].out [*std::next (it)].xml_node = edge;
343
+ }
344
+
345
+ // we do not provide any further details as CPAchecker does not seem to
346
+ // handle more detailed concurrency witnesses
347
+ return ;
348
+ }
349
+
303
350
// step numbers start at 1
304
351
std::vector<std::size_t > step_to_node (goto_trace.steps .size ()+1 , 0 );
305
352
@@ -338,14 +385,15 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
338
385
std::to_string (it->pc ->location_number )+" ." +std::to_string (it->step_nr );
339
386
graphml[node].file =source_location.get_file ();
340
387
graphml[node].line =source_location.get_line ();
341
- graphml[node].thread_nr =it->thread_nr ;
342
388
graphml[node].is_violation =
343
389
it->type ==goto_trace_stept::typet::ASSERT && !it->cond_value ;
344
390
graphml[node].has_invariant =false ;
345
391
346
392
step_to_node[it->step_nr ]=node;
347
393
}
348
394
395
+ unsigned thread_id = 0 ;
396
+
349
397
// build edges
350
398
for (goto_tracet::stepst::const_iterator
351
399
it=goto_trace.steps .begin ();
@@ -378,6 +426,7 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
378
426
case goto_trace_stept::typet::ASSIGNMENT:
379
427
case goto_trace_stept::typet::ASSERT:
380
428
case goto_trace_stept::typet::GOTO:
429
+ case goto_trace_stept::typet::SPAWN:
381
430
{
382
431
xmlt edge (
383
432
" edge" ,
@@ -393,6 +442,10 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
393
442
xmlt &data_l=edge.new_element (" data" );
394
443
data_l.set_attribute (" key" , " startline" );
395
444
data_l.data =id2string (graphml[from].line );
445
+
446
+ xmlt &data_t =edge.new_element (" data" );
447
+ data_t .set_attribute (" key" , " threadId" );
448
+ data_t .data =std::to_string (it->thread_nr );
396
449
}
397
450
398
451
const auto lhs_object = it->get_lhs_object ();
@@ -401,11 +454,19 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
401
454
lhs_object.has_value ())
402
455
{
403
456
const std::string &lhs_id = id2string (lhs_object->get_identifier ());
404
- if (
457
+ if (lhs_id.find (" pthread_create::thread" ) != std::string::npos)
458
+ {
459
+ xmlt &data_t = edge.new_element (" data" );
460
+ data_t .set_attribute (" key" , " createThread" );
461
+ data_t .data = std::to_string (++thread_id);
462
+ }
463
+ else if (
405
464
!contains_symbol_prefix (
406
465
it->full_lhs_value , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
407
466
!contains_symbol_prefix (
408
467
it->full_lhs , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
468
+ lhs_id.find (" thread" ) == std::string::npos &&
469
+ lhs_id.find (" mutex" ) == std::string::npos &&
409
470
(!it->full_lhs_value .is_constant () ||
410
471
!it->full_lhs_value .has_operands () ||
411
472
!has_prefix (
@@ -448,7 +509,6 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
448
509
case goto_trace_stept::typet::OUTPUT:
449
510
case goto_trace_stept::typet::SHARED_READ:
450
511
case goto_trace_stept::typet::SHARED_WRITE:
451
- case goto_trace_stept::typet::SPAWN:
452
512
case goto_trace_stept::typet::MEMORY_BARRIER:
453
513
case goto_trace_stept::typet::ATOMIC_BEGIN:
454
514
case goto_trace_stept::typet::ATOMIC_END:
@@ -470,7 +530,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
470
530
471
531
const graphmlt::node_indext sink=graphml.add_node ();
472
532
graphml[sink].node_name =" sink" ;
473
- graphml[sink].thread_nr =0 ;
474
533
graphml[sink].is_violation =false ;
475
534
graphml[sink].has_invariant =false ;
476
535
@@ -516,7 +575,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
516
575
std::to_string (step_nr);
517
576
graphml[node].file =source_location.get_file ();
518
577
graphml[node].line =source_location.get_line ();
519
- graphml[node].thread_nr =it->source .thread_nr ;
520
578
graphml[node].is_violation =false ;
521
579
graphml[node].has_invariant =false ;
522
580
@@ -557,6 +615,7 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
557
615
case goto_trace_stept::typet::ASSIGNMENT:
558
616
case goto_trace_stept::typet::ASSERT:
559
617
case goto_trace_stept::typet::GOTO:
618
+ case goto_trace_stept::typet::SPAWN:
560
619
{
561
620
xmlt edge (
562
621
" edge" ,
@@ -601,7 +660,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
601
660
case goto_trace_stept::typet::OUTPUT:
602
661
case goto_trace_stept::typet::SHARED_READ:
603
662
case goto_trace_stept::typet::SHARED_WRITE:
604
- case goto_trace_stept::typet::SPAWN:
605
663
case goto_trace_stept::typet::MEMORY_BARRIER:
606
664
case goto_trace_stept::typet::ATOMIC_BEGIN:
607
665
case goto_trace_stept::typet::ATOMIC_END:
0 commit comments