summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/unix/garbage.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 8d0912c1d01a..cec6189126ba 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -115,16 +115,20 @@ static struct unix_vertex *unix_edge_successor(struct unix_edge *edge)
static LIST_HEAD(unix_unvisited_vertices);
enum unix_vertex_index {
- UNIX_VERTEX_INDEX_UNVISITED,
+ UNIX_VERTEX_INDEX_MARK1,
+ UNIX_VERTEX_INDEX_MARK2,
UNIX_VERTEX_INDEX_START,
};
+static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1;
+
static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge)
{
struct unix_vertex *vertex = edge->predecessor->vertex;
if (!vertex) {
vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry);
+ vertex->index = unix_vertex_unvisited_index;
vertex->out_degree = 0;
INIT_LIST_HEAD(&vertex->edges);
@@ -265,6 +269,7 @@ void unix_destroy_fpl(struct scm_fp_list *fpl)
}
static LIST_HEAD(unix_visited_vertices);
+static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2;
static void __unix_walk_scc(struct unix_vertex *vertex)
{
@@ -274,10 +279,10 @@ static void __unix_walk_scc(struct unix_vertex *vertex)
LIST_HEAD(edge_stack);
next_vertex:
- /* Push vertex to vertex_stack.
+ /* Push vertex to vertex_stack and mark it as on-stack
+ * (index >= UNIX_VERTEX_INDEX_START).
* The vertex will be popped when finalising SCC later.
*/
- vertex->on_stack = true;
list_add(&vertex->scc_entry, &vertex_stack);
vertex->index = index;
@@ -291,7 +296,7 @@ next_vertex:
if (!next_vertex)
continue;
- if (next_vertex->index == UNIX_VERTEX_INDEX_UNVISITED) {
+ if (next_vertex->index == unix_vertex_unvisited_index) {
/* Iterative deepening depth first search
*
* 1. Push a forward edge to edge_stack and set
@@ -317,7 +322,7 @@ prev_vertex:
* to skip SCC finalisation.
*/
vertex->lowlink = min(vertex->lowlink, next_vertex->lowlink);
- } else if (next_vertex->on_stack) {
+ } else if (next_vertex->index != unix_vertex_grouped_index) {
/* Loop detected by a back/cross edge.
*
* The successor is on vertex_stack, so two vertices are
@@ -344,7 +349,8 @@ prev_vertex:
/* Don't restart DFS from this vertex in unix_walk_scc(). */
list_move_tail(&vertex->entry, &unix_visited_vertices);
- vertex->on_stack = false;
+ /* Mark vertex as off-stack. */
+ vertex->index = unix_vertex_grouped_index;
}
list_del(&scc);
@@ -357,20 +363,18 @@ prev_vertex:
static void unix_walk_scc(void)
{
- struct unix_vertex *vertex;
-
- list_for_each_entry(vertex, &unix_unvisited_vertices, entry)
- vertex->index = UNIX_VERTEX_INDEX_UNVISITED;
-
/* Visit every vertex exactly once.
* __unix_walk_scc() moves visited vertices to unix_visited_vertices.
*/
while (!list_empty(&unix_unvisited_vertices)) {
+ struct unix_vertex *vertex;
+
vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry);
__unix_walk_scc(vertex);
}
list_replace_init(&unix_visited_vertices, &unix_unvisited_vertices);
+ swap(unix_vertex_unvisited_index, unix_vertex_grouped_index);
}
static LIST_HEAD(gc_candidates);