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)
+static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_index)
{
- unsigned long index = UNIX_VERTEX_INDEX_START;
LIST_HEAD(vertex_stack);
struct unix_edge *edge;
LIST_HEAD(edge_stack);
*/
list_add(&vertex->scc_entry, &vertex_stack);
- vertex->index = index;
- vertex->lowlink = index;
- index++;
+ vertex->index = *last_index;
+ vertex->scc_index = *last_index;
+ (*last_index)++;
/* Explore neighbour vertices (receivers of the current vertex's fd). */
list_for_each_entry(edge, &vertex->edges, vertex_entry) {
next_vertex = vertex;
vertex = edge->predecessor->vertex;
- /* If the successor has a smaller lowlink, two vertices
- * are in the same SCC, so propagate the smaller lowlink
+ /* If the successor has a smaller scc_index, two vertices
+ * are in the same SCC, so propagate the smaller scc_index
* to skip SCC finalisation.
*/
- vertex->lowlink = min(vertex->lowlink, next_vertex->lowlink);
+ vertex->scc_index = min(vertex->scc_index, next_vertex->scc_index);
} 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
- * in the same SCC. If the successor has a smaller index,
+ * The successor is on vertex_stack, so two vertices are in
+ * the same SCC. If the successor has a smaller *scc_index*,
* propagate it to skip SCC finalisation.
*/
- vertex->lowlink = min(vertex->lowlink, next_vertex->index);
+ vertex->scc_index = min(vertex->scc_index, next_vertex->scc_index);
} else {
/* The successor was already grouped as another SCC */
}
}
- if (vertex->index == vertex->lowlink) {
+ if (vertex->index == vertex->scc_index) {
struct list_head scc;
/* SCC finalised.
*
- * If the lowlink was not updated, all the vertices above on
+ * If the scc_index was not updated, all the vertices above on
* vertex_stack are in the same SCC. Group them using scc_entry.
*/
__list_cut_position(&scc, &vertex_stack, &vertex->scc_entry);
static void unix_walk_scc(void)
{
+ unsigned long last_index = UNIX_VERTEX_INDEX_START;
+
unix_graph_maybe_cyclic = false;
/* Visit every vertex exactly once.
struct unix_vertex *vertex;
vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry);
- __unix_walk_scc(vertex);
+ __unix_walk_scc(vertex, &last_index);
}
list_replace_init(&unix_visited_vertices, &unix_unvisited_vertices);