@@ -278,14 +278,61 @@ static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
278
278
// / counterexample witness
279
279
void graphml_witnesst::operator ()(const goto_tracet &goto_trace)
280
280
{
281
+ unsigned int max_thread_idx = 0 ;
282
+ bool trace_has_violation = false ;
283
+ for (goto_tracet::stepst::const_iterator it = goto_trace.steps .begin ();
284
+ it != goto_trace.steps .end ();
285
+ ++it)
286
+ {
287
+ if (it->thread_nr > max_thread_idx)
288
+ max_thread_idx = it->thread_nr ;
289
+ if (it->is_assert () && !it->cond_value )
290
+ trace_has_violation = true ;
291
+ }
292
+
281
293
graphml.key_values [" sourcecodelang" ]=" C" ;
282
294
283
295
const graphmlt::node_indext sink=graphml.add_node ();
284
296
graphml[sink].node_name =" sink" ;
285
- graphml[sink].thread_nr =0 ;
286
297
graphml[sink].is_violation =false ;
287
298
graphml[sink].has_invariant =false ;
288
299
300
+ if (max_thread_idx > 0 && trace_has_violation)
301
+ {
302
+ std::vector<graphmlt::node_indext> nodes;
303
+
304
+ for (unsigned int i = 0 ; i <= max_thread_idx + 1 ; ++i)
305
+ {
306
+ nodes.push_back (graphml.add_node ());
307
+ graphml[nodes.back ()].node_name = " N" + std::to_string (i);
308
+ graphml[nodes.back ()].is_violation = i == max_thread_idx + 1 ;
309
+ graphml[nodes.back ()].has_invariant = false ;
310
+ }
311
+
312
+ for (auto it = nodes.cbegin (); std::next (it) != nodes.cend (); ++it)
313
+ {
314
+ xmlt edge (" edge" );
315
+ edge.set_attribute (" source" , graphml[*it].node_name );
316
+ edge.set_attribute (" target" , graphml[*std::next (it)].node_name );
317
+ const auto thread_id = std::distance (nodes.cbegin (), it);
318
+ xmlt &data = edge.new_element (" data" );
319
+ data.set_attribute (" key" , " createThread" );
320
+ data.data = std::to_string (thread_id);
321
+ if (thread_id == 0 )
322
+ {
323
+ xmlt &data = edge.new_element (" data" );
324
+ data.set_attribute (" key" , " enterFunction" );
325
+ data.data = " main" ;
326
+ }
327
+ graphml[*std::next (it)].in [*it].xml_node = edge;
328
+ graphml[*it].out [*std::next (it)].xml_node = edge;
329
+ }
330
+
331
+ // we do not provide any further details as CPAchecker does not seem to
332
+ // handle more detailed concurrency witnesses
333
+ return ;
334
+ }
335
+
289
336
// step numbers start at 1
290
337
std::vector<std::size_t > step_to_node (goto_trace.steps .size ()+1 , 0 );
291
338
@@ -324,14 +371,15 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
324
371
std::to_string (it->pc ->location_number )+" ." +std::to_string (it->step_nr );
325
372
graphml[node].file =source_location.get_file ();
326
373
graphml[node].line =source_location.get_line ();
327
- graphml[node].thread_nr =it->thread_nr ;
328
374
graphml[node].is_violation =
329
375
it->type ==goto_trace_stept::typet::ASSERT && !it->cond_value ;
330
376
graphml[node].has_invariant =false ;
331
377
332
378
step_to_node[it->step_nr ]=node;
333
379
}
334
380
381
+ unsigned thread_id = 0 ;
382
+
335
383
// build edges
336
384
for (goto_tracet::stepst::const_iterator
337
385
it=goto_trace.steps .begin ();
@@ -364,6 +412,7 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
364
412
case goto_trace_stept::typet::ASSIGNMENT:
365
413
case goto_trace_stept::typet::ASSERT:
366
414
case goto_trace_stept::typet::GOTO:
415
+ case goto_trace_stept::typet::SPAWN:
367
416
{
368
417
xmlt edge (
369
418
" edge" ,
@@ -379,6 +428,10 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
379
428
xmlt &data_l=edge.new_element (" data" );
380
429
data_l.set_attribute (" key" , " startline" );
381
430
data_l.data =id2string (graphml[from].line );
431
+
432
+ xmlt &data_t =edge.new_element (" data" );
433
+ data_t .set_attribute (" key" , " threadId" );
434
+ data_t .data =std::to_string (it->thread_nr );
382
435
}
383
436
384
437
const auto lhs_object = it->get_lhs_object ();
@@ -387,11 +440,19 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
387
440
lhs_object.has_value ())
388
441
{
389
442
const std::string &lhs_id = id2string (lhs_object->get_identifier ());
390
- if (
443
+ if (lhs_id.find (" pthread_create::thread" ) != std::string::npos)
444
+ {
445
+ xmlt &data_t = edge.new_element (" data" );
446
+ data_t .set_attribute (" key" , " createThread" );
447
+ data_t .data = std::to_string (++thread_id);
448
+ }
449
+ else if (
391
450
!contains_symbol_prefix (
392
451
it->full_lhs_value , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
393
452
!contains_symbol_prefix (
394
453
it->full_lhs , SYMEX_DYNAMIC_PREFIX " dynamic_object" ) &&
454
+ lhs_id.find (" thread" ) == std::string::npos &&
455
+ lhs_id.find (" mutex" ) == std::string::npos &&
395
456
(!it->full_lhs_value .is_constant () ||
396
457
!it->full_lhs_value .has_operands () ||
397
458
!has_prefix (
@@ -434,7 +495,6 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
434
495
case goto_trace_stept::typet::OUTPUT:
435
496
case goto_trace_stept::typet::SHARED_READ:
436
497
case goto_trace_stept::typet::SHARED_WRITE:
437
- case goto_trace_stept::typet::SPAWN:
438
498
case goto_trace_stept::typet::MEMORY_BARRIER:
439
499
case goto_trace_stept::typet::ATOMIC_BEGIN:
440
500
case goto_trace_stept::typet::ATOMIC_END:
@@ -456,7 +516,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
456
516
457
517
const graphmlt::node_indext sink=graphml.add_node ();
458
518
graphml[sink].node_name =" sink" ;
459
- graphml[sink].thread_nr =0 ;
460
519
graphml[sink].is_violation =false ;
461
520
graphml[sink].has_invariant =false ;
462
521
@@ -502,7 +561,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
502
561
std::to_string (step_nr);
503
562
graphml[node].file =source_location.get_file ();
504
563
graphml[node].line =source_location.get_line ();
505
- graphml[node].thread_nr =it->source .thread_nr ;
506
564
graphml[node].is_violation =false ;
507
565
graphml[node].has_invariant =false ;
508
566
@@ -543,6 +601,7 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
543
601
case goto_trace_stept::typet::ASSIGNMENT:
544
602
case goto_trace_stept::typet::ASSERT:
545
603
case goto_trace_stept::typet::GOTO:
604
+ case goto_trace_stept::typet::SPAWN:
546
605
{
547
606
xmlt edge (
548
607
" edge" ,
@@ -587,7 +646,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
587
646
case goto_trace_stept::typet::OUTPUT:
588
647
case goto_trace_stept::typet::SHARED_READ:
589
648
case goto_trace_stept::typet::SHARED_WRITE:
590
- case goto_trace_stept::typet::SPAWN:
591
649
case goto_trace_stept::typet::MEMORY_BARRIER:
592
650
case goto_trace_stept::typet::ATOMIC_BEGIN:
593
651
case goto_trace_stept::typet::ATOMIC_END:
0 commit comments