87 lines
2.3 KiB
C
87 lines
2.3 KiB
C
#pragma once
|
|
|
|
#include <zinnia/compiler.h>
|
|
#include <zinnia/utils.h>
|
|
#include <stddef.h>
|
|
|
|
enum init_action {
|
|
INIT_EMPTY,
|
|
INIT_CALLBACK,
|
|
INIT_GATE,
|
|
};
|
|
|
|
struct boot_info;
|
|
struct init_node;
|
|
|
|
struct init_edge {
|
|
struct init_node* source;
|
|
struct init_node* target;
|
|
bool propagates_disable;
|
|
struct init_edge* next_in;
|
|
struct init_edge* next_out;
|
|
};
|
|
|
|
struct init_edges {
|
|
struct init_node* node;
|
|
bool depends;
|
|
size_t count;
|
|
struct init_node* const* nodes;
|
|
struct init_edge* edges;
|
|
};
|
|
|
|
struct init_node {
|
|
const char* name;
|
|
enum init_action action;
|
|
union {
|
|
void (*callback)(struct boot_info* info);
|
|
bool (*gate)(struct boot_info* info);
|
|
void* func;
|
|
};
|
|
size_t unsatisfied;
|
|
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;
|
|
};
|
|
|
|
#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__), \
|
|
)} \
|
|
}; \
|
|
[[__used, __section(".initgraph.nodes")]] \
|
|
static struct init_node* const CONCAT(node, _initgraph_node) = node
|
|
|
|
#define _INIT_EDGES(x, from, is_depends, ...) \
|
|
static struct init_node* const CONCAT(x, _nodes)[] = {__VA_ARGS__}; \
|
|
static struct init_edge CONCAT(x, _edges)[ARRAY_SIZE(CONCAT(x, _nodes))]; \
|
|
static const struct init_edges x = { \
|
|
.node = (from), \
|
|
.depends = (is_depends), \
|
|
.count = ARRAY_SIZE(CONCAT(x, _nodes)), \
|
|
.nodes = CONCAT(x, _nodes), \
|
|
.edges = CONCAT(x, _edges), \
|
|
}; \
|
|
[[__used, __section(".initgraph.edges")]] \
|
|
static const struct init_edges* const CONCAT(x, _ptr) = &x
|
|
|
|
#define INIT_DEPENDS(node, ...) _INIT_EDGES(UNIQUE_IDENT(init_edges), node, true, __VA_ARGS__)
|
|
#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();
|