-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.cc
120 lines (112 loc) · 3.74 KB
/
graph.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "graph.hh"
void graph_edge::message(int loop_id)
{
caller->print_call_path_to(invocation, loop_id, 0);
class_desc* abstract_class = invocation->method->cls;
invocation->method->cls = vertex->cls;
if (!strcmp(invocation->method->name.as_asciz(), "<synch>")) {
// special error message about synchronized blocks
if (invocation->method->attr & method_desc::m_sync_block) {
const char* lock1 = invocation->self_class->name.as_asciz();
// pretty print lock set
string lockset = "";
monitor_stack::const_iterator entry = caller->locksAtEntry.begin();
while (entry != caller->locksAtEntry.end()) {
if ((*entry)->cls == NULL)
break;
const char* full_name =
compound_name((*entry)->cls->name.as_asciz(),
(*entry)->name.as_asciz());
if (strcmp(full_name, lock1)) {
lockset += string(", ");
if (strcmp(full_name, "")) {
lockset += full_name;
} else {
lockset += "<unknown>";
}
}
entry++;
}
if (caller->locksAtEntry.nLocks() > 2) {
lockset += "}";
lockset.replace(0, 2, "set {");
} else {
lockset.replace(0, 2, "");
}
if (lockset == "") {
lockset = "<unknown>";
}
invocation->message(msg_lock, lock1, lockset.c_str());
} else {
invocation->message(msg_lock, invocation->self_class->name.as_asciz(),
caller->cls->name.as_asciz());
}
} else {
if (!(invocation->method->attr & method_desc::m_sync_block)) {
invocation->message(msg_sync_loop, (void*)loop_id, invocation->method);
}
}
invocation->method->cls = abstract_class;
mask |= (1 << (loop_id & 31));
}
void graph_vertex::verify()
{
graph_edge** stack = new graph_edge*[n_vertexes];
int marker = 0;
int n_loops = 0;
for (graph_vertex* root = graph; root != NULL; root = root->next) {
if (root->marker <= marker || root->visited >= max_shown_paths) {
continue;
}
int sp = 0;
int i;
graph_edge* edge = root->edges;
root->visited |= flag_vertex_on_path;
root->marker = ++marker;
while (edge != NULL) {
while (edge->vertex->marker >= marker ||
edge->vertex->visited < max_shown_paths)
{
graph_vertex* vertex = edge->vertex;
stack[sp++] = edge;
if (vertex->visited & flag_vertex_on_path) {
// we found loop in the graph
unsigned mask = edge->mask;
for (i = sp-1; --i >= 0 && stack[i]->vertex != vertex;) {
mask &= stack[i]->mask;
}
if (mask == 0) {
n_loops += 1;
while (++i < sp) {
stack[i]->message(n_loops);
}
}
} else {
// Pass through the graph in depth first order
if (vertex->edges != NULL) {
vertex->visited =
(vertex->visited + 1) | flag_vertex_on_path;
vertex->marker = marker;
vertex->n_loops = n_loops;
edge = vertex->edges;
continue;
}
}
sp -= 1;
break;
} // end of depth-first loop
while (edge->next == NULL) {
if (--sp < 0) break;
edge = stack[sp];
edge->vertex->visited &= ~flag_vertex_on_path;
if (edge->vertex->n_loops == n_loops) {
// This path doesn't lead to deadlock: avoid future
// visits of this vertex
edge->vertex->marker = 0;
}
}
edge = edge->next;
}
root->visited &= ~flag_vertex_on_path;
}
}