mark initgraph nodes red and dimmed if not run
This commit is contained in:
+29
-3
@@ -17,6 +17,7 @@ static void initgraph_option(bool value) {
|
||||
CMDLINE_OPTION("initgraph", "Print the init graph in DOT format after running", initgraph_option);
|
||||
|
||||
static bool edges_linked = false;
|
||||
static struct init_node* failed_node = nullptr;
|
||||
|
||||
struct init_queue {
|
||||
struct init_node* head;
|
||||
@@ -96,6 +97,7 @@ static void reach_node(struct init_node* node, struct boot_info* info) {
|
||||
log_status("Skipping stage \"%s\"\n", node->name);
|
||||
} else {
|
||||
log_status("Running stage \"%s\"\n", node->name);
|
||||
failed_node = node;
|
||||
switch (node->action) {
|
||||
case INIT_EMPTY:
|
||||
break;
|
||||
@@ -103,10 +105,14 @@ static void reach_node(struct init_node* node, struct boot_info* info) {
|
||||
node->callback(info);
|
||||
break;
|
||||
case INIT_GATE:
|
||||
if (!node->gate(info))
|
||||
if (!node->gate(info)) {
|
||||
node->disabled = true;
|
||||
node->failed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
failed_node = nullptr;
|
||||
node->executed = true;
|
||||
}
|
||||
node->done = true;
|
||||
}
|
||||
@@ -115,13 +121,31 @@ static void dump() {
|
||||
kprintf("digraph initgraph {\n");
|
||||
for (auto cur = __ld_initgraph_nodes_start; cur < __ld_initgraph_nodes_end; cur++) {
|
||||
struct init_node* node = *cur;
|
||||
kprintf("\tn%p [label=\"%s\"];\n", node, node->name);
|
||||
const char* style = "";
|
||||
if (node->failed || node == failed_node)
|
||||
style = ", color=red, fontcolor=red";
|
||||
else if (!node->executed)
|
||||
style = ", color=gray, fontcolor=gray";
|
||||
kprintf("\tn%p [label=\"%s\"%s];\n", node, node->name, style);
|
||||
for (struct init_edge* edge = node->in_edges; edge; edge = edge->next_in)
|
||||
kprintf("\tn%p -> n%p;\n", edge->source, edge->target);
|
||||
kprintf(
|
||||
"\tn%p -> n%p%s;\n",
|
||||
edge->source,
|
||||
edge->target,
|
||||
edge->source->executed && edge->target->executed ? "" : " [color=gray]"
|
||||
);
|
||||
}
|
||||
kprintf("}\n");
|
||||
}
|
||||
|
||||
void initgraph_panic() {
|
||||
static bool dumping = false;
|
||||
if (!dump_graph || !failed_node || dumping)
|
||||
return;
|
||||
dumping = true;
|
||||
dump();
|
||||
}
|
||||
|
||||
void initgraph_run(struct init_node* goal, struct boot_info* info) {
|
||||
if (!edges_linked)
|
||||
link_edges();
|
||||
@@ -153,6 +177,8 @@ void initgraph_run(struct init_node* goal, struct boot_info* info) {
|
||||
}
|
||||
|
||||
for (auto cur = __ld_initgraph_nodes_start; cur < __ld_initgraph_nodes_end; cur++) {
|
||||
if ((*cur)->wanted && !(*cur)->done)
|
||||
failed_node = *cur;
|
||||
assert(
|
||||
!(*cur)->wanted || (*cur)->done,
|
||||
"The dependencies for stage \"%s\" could not be resolved",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/irq.h>
|
||||
#include <zinnia/ksyms.h>
|
||||
#include <zinnia/panic.h>
|
||||
@@ -64,6 +65,8 @@ void panic(const char* msg, ...) {
|
||||
print_backtrace();
|
||||
panic_log("End of panic message\n");
|
||||
|
||||
initgraph_panic();
|
||||
|
||||
while (true) {
|
||||
irq_wait();
|
||||
}
|
||||
|
||||
+15
-11
@@ -41,6 +41,8 @@ struct init_node {
|
||||
bool wanted;
|
||||
bool done;
|
||||
bool disabled;
|
||||
bool executed;
|
||||
bool failed;
|
||||
struct init_edge* in_edges;
|
||||
struct init_edge* out_edges;
|
||||
struct init_node* queue_next;
|
||||
@@ -49,17 +51,17 @@ struct init_node {
|
||||
#define INIT_EXTERN(node) extern struct init_node node[1]
|
||||
|
||||
#define INIT_TASK(node, display, ...) \
|
||||
struct init_node node[1] = {{ \
|
||||
.name = (display), \
|
||||
__VA_OPT__( \
|
||||
.action = _Generic( \
|
||||
(__VA_ARGS__), \
|
||||
void (*)(struct boot_info*): INIT_CALLBACK, \
|
||||
bool (*)(struct boot_info*): INIT_GATE \
|
||||
), \
|
||||
.func = (void*)(__VA_ARGS__), \
|
||||
) \
|
||||
}}; \
|
||||
struct init_node node[1] = { \
|
||||
{.name = (display), \
|
||||
__VA_OPT__( \
|
||||
.action = _Generic( \
|
||||
(__VA_ARGS__), \
|
||||
void (*)(struct boot_info*): INIT_CALLBACK, \
|
||||
bool (*)(struct boot_info*): INIT_GATE \
|
||||
), \
|
||||
.func = (void*)(__VA_ARGS__), \
|
||||
)} \
|
||||
}; \
|
||||
[[__used, __section(".initgraph.nodes")]] \
|
||||
static struct init_node* const CONCAT(node, _initgraph_node) = node
|
||||
|
||||
@@ -80,3 +82,5 @@ struct init_node {
|
||||
#define INIT_ENTAILS(node, ...) _INIT_EDGES(UNIQUE_IDENT(init_edges), node, false, __VA_ARGS__)
|
||||
|
||||
void initgraph_run(struct init_node* goal, struct boot_info* info);
|
||||
|
||||
void initgraph_panic();
|
||||
|
||||
Reference in New Issue
Block a user