@@ -304,14 +304,61 @@ static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
304
304
// / counterexample witness
305
305
void graphml_witnesst::operator ()(const goto_tracet &goto_trace)
306
306
{
307
+ unsigned int max_thread_idx = 0 ;
308
+ bool trace_has_violation = false ;
309
+ for (goto_tracet::stepst::const_iterator it = goto_trace.steps .begin ();
310
+ it != goto_trace.steps .end ();
311
+ ++it)
312
+ {
313
+ if (it->thread_nr > max_thread_idx)
314
+ max_thread_idx = it->thread_nr ;
315
+ if (it->is_assert () && !it->cond_value )
316
+ trace_has_violation = true ;
317
+ }
318
+
307
319
graphml.key_values [" sourcecodelang" ]=" C" ;
308
320
309
321
const graphmlt::node_indext sink=graphml.add_node ();
310
322
graphml[sink].node_name =" sink" ;
311
- graphml[sink].thread_nr =0 ;
312
323
graphml[sink].is_violation =false ;
313
324
graphml[sink].has_invariant =false ;
314
325
326
+ if (max_thread_idx > 0 && trace_has_violation)
327
+ {
328
+ std::vector<graphmlt::node_indext> nodes;
329
+
330
+ for (unsigned int i = 0 ; i <= max_thread_idx + 1 ; ++i)
331
+ {
332
+ nodes.push_back (graphml.add_node ());
333
+ graphml[nodes.back ()].node_name = " N" + std::to_string (i);
334
+ graphml[nodes.back ()].is_violation = i == max_thread_idx + 1 ;
335
+ graphml[nodes.back ()].has_invariant = false ;
336
+ }
337
+
338
+ for (auto it = nodes.cbegin (); std::next (it) != nodes.cend (); ++it)
339
+ {
340
+ xmlt edge (" edge" );
341
+ edge.set_attribute (" source" , graphml[*it].node_name );
342
+ edge.set_attribute (" target" , graphml[*std::next (it)].node_name );
343
+ const auto thread_id = std::distance (nodes.cbegin (), it);
344
+ xmlt &data = edge.new_element (" data" );
345
+ data.set_attribute (" key" , " createThread" );
346
+ data.data = std::to_string (thread_id);
347
+ if (thread_id == 0 )
348
+ {
349
+ xmlt &data = edge.new_element (" data" );
350
+ data.set_attribute (" key" , " enterFunction" );
351
+ data.data = " main" ;
352
+ }
353
+ graphml[*std::next (it)].in [*it].xml_node = edge;
354
+ graphml[*it].out [*std::next (it)].xml_node = edge;
355
+ }
356
+
357
+ // we do not provide any further details as CPAchecker does not seem to
358
+ // handle more detailed concurrency witnesses
359
+ return ;
360
+ }
361
+
315
362
// step numbers start at 1
316
363
std::vector<std::size_t > step_to_node (goto_trace.steps .size ()+1 , 0 );
317
364
@@ -350,14 +397,15 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
350
397
std::to_string (it->pc ->location_number )+" ." +std::to_string (it->step_nr );
351
398
graphml[node].file =source_location.get_file ();
352
399
graphml[node].line =source_location.get_line ();
353
- graphml[node].thread_nr =it->thread_nr ;
354
400
graphml[node].is_violation =
355
401
it->type ==goto_trace_stept::typet::ASSERT && !it->cond_value ;
356
402
graphml[node].has_invariant =false ;
357
403
358
404
step_to_node[it->step_nr ]=node;
359
405
}
360
406
407
+ unsigned thread_id = 0 ;
408
+
361
409
// build edges
362
410
for (goto_tracet::stepst::const_iterator
363
411
it=goto_trace.steps .begin ();
@@ -390,6 +438,7 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
390
438
case goto_trace_stept::typet::ASSIGNMENT:
391
439
case goto_trace_stept::typet::ASSERT:
392
440
case goto_trace_stept::typet::GOTO:
441
+ case goto_trace_stept::typet::SPAWN:
393
442
{
394
443
xmlt edge (
395
444
" edge" ,
@@ -405,6 +454,10 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
405
454
xmlt &data_l=edge.new_element (" data" );
406
455
data_l.set_attribute (" key" , " startline" );
407
456
data_l.data =id2string (graphml[from].line );
457
+
458
+ xmlt &data_t =edge.new_element (" data" );
459
+ data_t .set_attribute (" key" , " threadId" );
460
+ data_t .data =std::to_string (it->thread_nr );
408
461
}
409
462
410
463
const auto lhs_object = it->get_lhs_object ();
@@ -413,11 +466,19 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
413
466
lhs_object.has_value ())
414
467
{
415
468
const std::string &lhs_id = id2string (lhs_object->get_identifier ());
416
- if (
469
+ if (lhs_id.find (" pthread_create::thread" ) != std::string::npos)
470
+ {
471
+ xmlt &data_t = edge.new_element (" data" );
472
+ data_t .set_attribute (" key" , " createThread" );
473
+ data_t .data = std::to_string (++thread_id);
474
+ }
475
+ else if (
417
476
!contains_symbol_prefix (
418
477
it->full_lhs_value , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
419
478
!contains_symbol_prefix (
420
479
it->full_lhs , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
480
+ lhs_id.find (" thread" ) == std::string::npos &&
481
+ lhs_id.find (" mutex" ) == std::string::npos &&
421
482
(!it->full_lhs_value .is_constant () ||
422
483
!it->full_lhs_value .has_operands () ||
423
484
!has_prefix (
@@ -460,7 +521,6 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
460
521
case goto_trace_stept::typet::OUTPUT:
461
522
case goto_trace_stept::typet::SHARED_READ:
462
523
case goto_trace_stept::typet::SHARED_WRITE:
463
- case goto_trace_stept::typet::SPAWN:
464
524
case goto_trace_stept::typet::MEMORY_BARRIER:
465
525
case goto_trace_stept::typet::ATOMIC_BEGIN:
466
526
case goto_trace_stept::typet::ATOMIC_END:
@@ -482,7 +542,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
482
542
483
543
const graphmlt::node_indext sink=graphml.add_node ();
484
544
graphml[sink].node_name =" sink" ;
485
- graphml[sink].thread_nr =0 ;
486
545
graphml[sink].is_violation =false ;
487
546
graphml[sink].has_invariant =false ;
488
547
@@ -528,7 +587,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
528
587
std::to_string (step_nr);
529
588
graphml[node].file =source_location.get_file ();
530
589
graphml[node].line =source_location.get_line ();
531
- graphml[node].thread_nr =it->source .thread_nr ;
532
590
graphml[node].is_violation =false ;
533
591
graphml[node].has_invariant =false ;
534
592
@@ -569,6 +627,7 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
569
627
case goto_trace_stept::typet::ASSIGNMENT:
570
628
case goto_trace_stept::typet::ASSERT:
571
629
case goto_trace_stept::typet::GOTO:
630
+ case goto_trace_stept::typet::SPAWN:
572
631
{
573
632
xmlt edge (
574
633
" edge" ,
@@ -613,7 +672,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
613
672
case goto_trace_stept::typet::OUTPUT:
614
673
case goto_trace_stept::typet::SHARED_READ:
615
674
case goto_trace_stept::typet::SHARED_WRITE:
616
- case goto_trace_stept::typet::SPAWN:
617
675
case goto_trace_stept::typet::MEMORY_BARRIER:
618
676
case goto_trace_stept::typet::ATOMIC_BEGIN:
619
677
case goto_trace_stept::typet::ATOMIC_END:
0 commit comments