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