Skip to content

Commit 23e677c

Browse files
author
zhangkw
committed
Single-thread generate state graph
1 parent 6fcd250 commit 23e677c

File tree

11 files changed

+263
-671
lines changed

11 files changed

+263
-671
lines changed

src/callback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl PTACallbacks {
166166
terminal_states,
167167
);
168168
for (api_name, initial_mark) in pn.api_marks.iter() {
169-
state_graph.generate_states_with_api(api_name.clone(), initial_mark.clone());
169+
// TODO: API可达图重构
170170
}
171171

172172
// log::info!("deadlock state: {}", state_graph.detect_api_deadlock());

src/detect/atomicity_violation.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use crate::report::{AtomicOperation, AtomicReport, AtomicViolation, ViolationPat
66
use petgraph::graph::NodeIndex;
77
use petgraph::visit::EdgeRef;
88
use petgraph::{Direction, Graph};
9+
use std::cell::RefCell;
910
use std::collections::{HashMap, HashSet};
10-
use std::sync::{Arc, Mutex, RwLock};
11-
use std::thread;
11+
use std::rc::Rc;
12+
use std::sync::{Arc, RwLock};
1213
use std::time::Instant;
1314

1415
pub struct AtomicityViolationDetector<'a> {
@@ -37,10 +38,10 @@ impl<'a> AtomicityViolationDetector<'a> {
3738

3839
// 2. 将图结构包装在 Arc<RwLock> 中
3940
let graph = Arc::new(RwLock::new(self.state_graph.graph.clone()));
40-
let initial_net = Arc::new(RwLock::new(self.state_graph.initial_net.as_ref().clone()));
4141

4242
// 3. 并行检查违背
43-
let violations = self.check_violations(loads, stores, &graph, &initial_net);
43+
let violations =
44+
self.check_violations(loads, stores, &graph, self.state_graph.initial_net.clone());
4445

4546
if !violations.is_empty() {
4647
report.has_violation = true;
@@ -84,8 +85,10 @@ impl<'a> AtomicityViolationDetector<'a> {
8485
let mut loads = HashMap::new();
8586
let mut stores = HashMap::new();
8687

87-
for node_idx in self.state_graph.initial_net.node_indices() {
88-
if let Some(PetriNetNode::T(t)) = self.state_graph.initial_net.node_weight(node_idx) {
88+
for node_idx in self.state_graph.initial_net.borrow().node_indices() {
89+
if let Some(PetriNetNode::T(t)) =
90+
self.state_graph.initial_net.borrow().node_weight(node_idx)
91+
{
8992
match &t.transition_type {
9093
ControlType::Call(CallType::AtomicLoad(var_id, ordering, span, thread_id)) => {
9194
if format!("{:?}", ordering) == "Relaxed" {
@@ -123,50 +126,33 @@ impl<'a> AtomicityViolationDetector<'a> {
123126
loads: HashMap<NodeIndex, AtomicOp>,
124127
stores: HashMap<NodeIndex, AtomicOp>,
125128
graph: &Arc<RwLock<Graph<StateNode, StateEdge>>>,
126-
initial_net: &Arc<RwLock<Graph<PetriNetNode, PetriNetEdge>>>,
129+
initial_net: Rc<RefCell<Graph<PetriNetNode, PetriNetEdge>>>,
127130
) -> Vec<ViolationPattern> {
128-
let all_violations = Arc::new(Mutex::new(Vec::new()));
129-
let mut handles = vec![];
131+
let mut all_violations = Vec::new();
132+
let graph = graph.read().unwrap();
133+
let initial_net = initial_net.borrow();
130134

131135
for (load_trans, load_op) in loads {
132-
let all_violations = Arc::clone(&all_violations);
133-
let stores = stores.clone();
134-
let graph = Arc::clone(graph);
135-
let initial_net = Arc::clone(initial_net);
136-
unsafe {
137-
let handle = thread::spawn(move || {
138-
let graph = graph.read().unwrap();
139-
for state in graph.node_indices() {
140-
for edge in graph.edges_directed(state, Direction::Outgoing) {
141-
if edge.weight().transition == load_trans {
142-
if let Some(violation) = Self::check_state_for_violation(
143-
&graph,
144-
&initial_net.read().unwrap(),
145-
state,
146-
&load_op,
147-
&stores,
148-
) {
149-
all_violations.lock().unwrap().push(violation);
150-
}
151-
}
136+
for state in graph.node_indices() {
137+
for edge in graph.edges_directed(state, Direction::Outgoing) {
138+
if edge.weight().transition == load_trans {
139+
if let Some(violation) = Self::check_state_for_violation(
140+
&graph,
141+
&initial_net,
142+
state,
143+
&load_op,
144+
&stores,
145+
) {
146+
all_violations.push(violation);
152147
}
153148
}
154-
});
155-
handles.push(handle);
149+
}
156150
}
157151
}
158152

159-
for handle in handles {
160-
handle.join().unwrap();
161-
}
162-
163-
let violations = Arc::try_unwrap(all_violations)
164-
.unwrap()
165-
.into_inner()
166-
.unwrap();
167153
let mut pattern_map: HashMap<ViolationPattern, Vec<Vec<(usize, u8)>>> = HashMap::new();
168154

169-
for violation in violations {
155+
for violation in all_violations {
170156
let pattern = ViolationPattern {
171157
load_op: AtomicOperation {
172158
operation_type: "load".to_string(),

src/detect/datarace.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ impl<'a> DataRaceDetector<'a> {
2626
// 收集当前状态的所有不安全操作
2727
for edge in self.state_graph.graph.edges(state) {
2828
let transition = edge.weight().transition;
29-
if let Some(node) = self.state_graph.initial_net.node_weight(transition) {
29+
if let Some(node) = self
30+
.state_graph
31+
.initial_net
32+
.borrow()
33+
.node_weight(transition)
34+
{
3035
match node {
3136
PetriNetNode::T(t) => match &t.transition_type {
3237
ControlType::UnsafeRead(alias_id, span, basic_block, place_ty) => {

src/detect/deadlock.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ impl<'a> DeadlockDetector<'a> {
6666

6767
// 检查是否是正常终止状态
6868
let is_normal_termination = state.mark.iter().any(|(idx, _)| {
69-
if let Some(PetriNetNode::P(place)) =
70-
self.state_graph.initial_net.node_weight(node_index(*idx))
69+
if let Some(PetriNetNode::P(place)) = self
70+
.state_graph
71+
.initial_net
72+
.borrow()
73+
.node_weight(node_index(*idx))
7174
{
7275
place.name.contains("main_end")
7376
} else {
@@ -255,8 +258,11 @@ impl<'a> DeadlockDetector<'a> {
255258
let has_terminal_state = cycle.iter().any(|&node| {
256259
if let Some(state) = self.state_graph.graph.node_weight(node) {
257260
state.mark.iter().any(|(idx, _)| {
258-
if let Some(PetriNetNode::P(place)) =
259-
self.state_graph.initial_net.node_weight(node_index(*idx))
261+
if let Some(PetriNetNode::P(place)) = self
262+
.state_graph
263+
.initial_net
264+
.borrow()
265+
.node_weight(node_index(*idx))
260266
{
261267
place.name.contains("main_end")
262268
} else {
@@ -335,8 +341,8 @@ impl<'a> DeadlockDetector<'a> {
335341
fn collect_lock_transitions(&self) -> HashMap<NodeIndex, Vec<NodeIndex>> {
336342
let mut lock_transitions = HashMap::new();
337343

338-
for node in self.state_graph.initial_net.node_indices() {
339-
if let PetriNetNode::T(transition) = &self.state_graph.initial_net[node] {
344+
for node in self.state_graph.initial_net.borrow().node_indices() {
345+
if let PetriNetNode::T(transition) = &self.state_graph.initial_net.borrow()[node] {
340346
match &transition.transition_type {
341347
ControlType::Call(CallType::Lock(lock_place))
342348
| ControlType::Call(CallType::RwLockWrite(lock_place))
@@ -360,10 +366,14 @@ impl<'a> DeadlockDetector<'a> {
360366
for edge in self
361367
.state_graph
362368
.initial_net
369+
.borrow()
363370
.edges_directed(transition, petgraph::Direction::Incoming)
364371
{
365-
if let Some(PetriNetNode::P(_)) =
366-
self.state_graph.initial_net.node_weight(edge.source())
372+
if let Some(PetriNetNode::P(_)) = self
373+
.state_graph
374+
.initial_net
375+
.borrow()
376+
.node_weight(edge.source())
367377
{
368378
let required_tokens = edge.weight().label;
369379
let available_tokens = state_node
@@ -387,8 +397,11 @@ impl<'a> DeadlockDetector<'a> {
387397
let marking: Vec<(String, u8)> = mark
388398
.iter()
389399
.filter_map(|(idx, tokens)| {
390-
if let Some(PetriNetNode::P(place)) =
391-
self.state_graph.initial_net.node_weight(node_index(*idx))
400+
if let Some(PetriNetNode::P(place)) = self
401+
.state_graph
402+
.initial_net
403+
.borrow()
404+
.node_weight(node_index(*idx))
392405
{
393406
Some((format!("{} ({})", place.name, place.span), *tokens))
394407
} else {

src/extern_tools/lola.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl LolaAnalyzer {
4747
if let PetriNetNode::P(place) = &petri_net.net[index] {
4848
let normalized_name = normalize_name(&place.name);
4949
places.push(normalized_name.clone());
50-
let tokens = place.tokens.read().unwrap();
50+
let tokens = place.tokens.borrow();
5151
if *tokens > 0 {
5252
markings.push(format!("{}: {}", normalized_name, *tokens));
5353
}

src/extern_tools/tina.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl TinaAnalyzer {
6969

7070
for index in petri_net.net.node_indices() {
7171
if let PetriNetNode::P(place) = &petri_net.net[index] {
72-
let tokens = place.tokens.read().unwrap();
72+
let tokens = place.tokens.borrow();
7373
let mut pl_str =
7474
format!("pl {} ({})", normalize_name_for_tina(&place.name), tokens);
7575

src/graph/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ pub mod mir_pn;
33
pub mod net_structure;
44
pub mod pn;
55
pub mod state_graph;
6-
pub mod unfolding_net;

src/graph/net_structure.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ use crate::memory::pointsto::AliasId;
33

44
use super::callgraph::InstanceId;
55
use petgraph::graph::NodeIndex;
6+
use petgraph::Graph;
67
use regex::Regex;
8+
use std::cell::RefCell;
79
use std::collections::HashMap;
810
use std::hash::Hash;
9-
use std::sync::{Arc, RwLock};
11+
use std::rc::Rc;
1012
use thiserror::Error;
1113

1214
#[derive(Debug, Clone)]
@@ -18,13 +20,14 @@ pub enum Shape {
1820
#[derive(Debug, Clone)]
1921
pub struct Place {
2022
pub name: String,
21-
// pub tokens: RefCell<usize>,
22-
pub tokens: Arc<RwLock<u8>>,
23+
pub tokens: Rc<RefCell<u8>>,
2324
pub capacity: u8,
2425
pub span: String,
2526
pub place_type: PlaceType,
2627
}
2728

29+
type PetriNetGraph = Graph<PetriNetNode, PetriNetEdge>;
30+
2831
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
2932
pub enum PlaceType {
3033
Unsafe,
@@ -41,7 +44,7 @@ impl Place {
4144
pub fn new(name: String, token: u8, place_type: PlaceType) -> Self {
4245
Self {
4346
name,
44-
tokens: Arc::new(RwLock::new(token)),
47+
tokens: Rc::new(RefCell::new(token)),
4548
capacity: token,
4649
span: String::new(),
4750
place_type,
@@ -51,7 +54,7 @@ impl Place {
5154
pub fn new_with_span(name: String, token: u8, place_type: PlaceType, span: String) -> Self {
5255
Self {
5356
name,
54-
tokens: Arc::new(RwLock::new(token)),
57+
tokens: Rc::new(RefCell::new(token)),
5558
capacity: 1u8,
5659
span,
5760
place_type,
@@ -61,7 +64,7 @@ impl Place {
6164
pub fn new_with_no_token(name: String, place_type: PlaceType) -> Self {
6265
Self {
6366
name,
64-
tokens: Arc::new(RwLock::new(0)),
67+
tokens: Rc::new(RefCell::new(0)),
6568
capacity: 1u8,
6669
span: String::new(),
6770
place_type,
@@ -78,7 +81,7 @@ impl Place {
7881
) -> Self {
7982
Self {
8083
name,
81-
tokens: Arc::new(RwLock::new(token)),
84+
tokens: Rc::new(RefCell::new(token)),
8285
capacity,
8386
span,
8487
place_type,

src/graph/pn.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ impl<'compilation, 'pn, 'tcx> PetriNet<'compilation, 'pn, 'tcx> {
470470
let func_instance = self.callgraph.graph.node_weight(node_idx).unwrap();
471471
let func_id = func_instance.instance().def_id();
472472
let func_name = format_name(func_id);
473-
log::info!("func_name: {}", func_name);
474473
if !func_name.starts_with(&self.options.crate_name)
475474
|| self.function_counter.contains_key(&func_id)
476475
|| func_name.contains("::deserialize")
@@ -886,8 +885,8 @@ impl<'compilation, 'pn, 'tcx> PetriNet<'compilation, 'pn, 'tcx> {
886885
for node in self.net.node_indices() {
887886
match &self.net[node] {
888887
PetriNetNode::P(place) => {
889-
if *place.tokens.read().unwrap() > 0 {
890-
current_mark.insert((node.clone(), *place.tokens.read().unwrap() as u8));
888+
if *place.tokens.borrow() > 0 {
889+
current_mark.insert((node.clone(), *place.tokens.borrow() as u8));
891890
}
892891
}
893892
PetriNetNode::T(_) => {
@@ -923,7 +922,7 @@ impl<'compilation, 'pn, 'tcx> PetriNet<'compilation, 'pn, 'tcx> {
923922
&|_, nr| {
924923
let label = match &nr.1 {
925924
PetriNetNode::P(place) => {
926-
let tokens = *place.tokens.read().unwrap();
925+
let tokens = *place.tokens.borrow();
927926
format!(
928927
"label = \"{}\\n(tokens: {})\", shape = circle",
929928
place.name, tokens
@@ -1060,7 +1059,7 @@ impl<'compilation, 'pn, 'tcx> PetriNet<'compilation, 'pn, 'tcx> {
10601059
continue;
10611060
}
10621061
_ => {
1063-
terminal_states.push((node_idx.index(), *place.tokens.read().unwrap()));
1062+
terminal_states.push((node_idx.index(), *place.tokens.borrow()));
10641063
}
10651064
}
10661065
}

0 commit comments

Comments
 (0)