diff options
author | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
---|---|---|
committer | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
commit | c63f340d90800895f007de64b7d2d14624263331 (patch) | |
tree | 2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/util/init.c |
Created student weenix repository
Diffstat (limited to 'kernel/util/init.c')
-rw-r--r-- | kernel/util/init.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/kernel/util/init.c b/kernel/util/init.c new file mode 100644 index 0000000..d1bc0d8 --- /dev/null +++ b/kernel/util/init.c @@ -0,0 +1,142 @@ +#include "kernel.h" + +#include "mm/kmalloc.h" + +#include "util/debug.h" +#include "util/init.h" +#include "util/list.h" +#include "util/string.h" + +static int _init_search_count = 0; + +struct init_function +{ + init_func_t if_func; + const char *if_name; + list_link_t if_link; + + int if_search; + int if_called; + list_t if_deps; +}; + +struct init_depends +{ + const char *id_name; + list_link_t id_link; +}; + +static void _init_call(list_t *funcs, struct init_function *func) +{ + list_iterate(&func->if_deps, dep, struct init_depends, id_link) + { + struct init_function *found = NULL; + list_iterate(funcs, f, struct init_function, if_link) + { + if (strcmp(dep->id_name, f->if_name) == 0) + { + found = f; + break; + } + } + + if (!found) + { + panic("'%s' dependency for '%s' does not exist", dep->id_name, + func->if_name); + } + + if (func->if_search == found->if_search) + { + panic("circular dependency between '%s' and '%s'", func->if_name, + found->if_name); + } + + dbg(DBG_INIT, "'%s' depends on '%s': ", func->if_name, found->if_name); + if (!found->if_called) + { + dbgq(DBG_INIT, "calling\n"); + found->if_search = func->if_search; + _init_call(funcs, found); + } + else + { + dbgq(DBG_INIT, "already called\n"); + } + } + + KASSERT(!func->if_called); + + dbg(DBG_INIT, "Calling %s (0x%p)\n", func->if_name, func->if_func); + func->if_func(); + func->if_called = 1; +} + +void init_call_all() +{ + list_t funcs; + char *buf, *end; + + list_init(&funcs); + buf = (char *)&kernel_start_init; + end = (char *)&kernel_end_init; + + while (buf < end) + { + struct init_function *curr = kmalloc(sizeof(*curr)); + KASSERT(NULL != curr); + + list_insert_tail(&funcs, &curr->if_link); + list_init(&curr->if_deps); + + KASSERT(NULL != *(uintptr_t *)buf); + curr->if_func = (init_func_t) * (uintptr_t *)buf; + curr->if_name = buf + sizeof(curr->if_func); + curr->if_search = 0; + curr->if_called = 0; + + buf += sizeof(curr->if_func) + strlen(curr->if_name) + 1; + + while ((NULL == *(uintptr_t *)buf) && (buf < end)) + { + struct init_depends *dep = kmalloc(sizeof(*dep)); + KASSERT(NULL != dep); + + list_insert_tail(&curr->if_deps, &dep->id_link); + + dep->id_name = buf + sizeof(curr->if_func); + buf += sizeof(curr->if_func) + strlen(dep->id_name) + 1; + } + } + + KASSERT(buf == end); + + dbg(DBG_INIT, "Initialization functions and dependencies:\n"); + list_iterate(&funcs, func, struct init_function, if_link) + { + dbgq(DBG_INIT, "%s (0x%p): ", func->if_name, func->if_func); + list_iterate(&func->if_deps, dep, struct init_depends, id_link) + { + dbgq(DBG_INIT, "%s ", dep->id_name); + } + dbgq(DBG_INIT, "\n"); + } + + list_iterate(&funcs, func, struct init_function, if_link) + { + if (!func->if_called) + { + func->if_search = ++_init_search_count; + _init_call(&funcs, func); + } + } + + list_iterate(&funcs, func, struct init_function, if_link) + { + list_iterate(&func->if_deps, dep, struct init_depends, id_link) + { + kfree(dep); + } + kfree(func); + } +} |