diff options
Diffstat (limited to 'src/bin/src/update.c')
| -rw-r--r-- | src/bin/src/update.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/bin/src/update.c b/src/bin/src/update.c new file mode 100644 index 0000000..3f03ae7 --- /dev/null +++ b/src/bin/src/update.c @@ -0,0 +1,145 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <kprintf.h> +#include <nanowasm/nw.h> +#include <stdbool.h> + +static int load(void) +{ + struct bin *const b = &bin_pending; + + for (struct bin_mod *m = b->mod_head; m;) + { + struct bin_mod *const next = m->next; + + switch (nw_load(&m->mod, &m->mod_out)) + { + case STATE_AGAIN: + break; + + case STATE_FATAL: + /* TODO: call nw_loadexc. */ + kprintf("Module %s failed to load\n", m->path); + + if (bin_unload(m)) + kprintf("Failed to unload module %s\n", m->path); + + bin_mod_free(m); + break; + + case STATE_OK: + kprintf("Module %s loaded successfully\n", m->path); + + if (bin_start(m)) + return -1; + + break; + } + + m = next; + } + + return 0; +} + +static int run(void) +{ + for (struct bin_proc *p = bin_active.proc_head; p;) + { + struct bin_proc *const next = p->next; + struct nw_inst *const i = &p->instance; + + switch (nw_run(i)) + { + case STATE_AGAIN: + break; + + case STATE_FATAL: + kprintf("Instance %s failed to run: %s\n", p->path, nw_rexc(i)); + + if (bin_stop(p)) + kprintf("Failed to stop instance %s\n", p->path); + + break; + + case STATE_OK: + /* TODO: remove from queue. */ + break; + } + + p = next; + } + + return 0; +} + +static int prune(const struct bin_mod *const mod) +{ + for (struct bin_mod *m = bin_active.mod_head; m;) + { + struct bin_mod *const next = m->next; + + if (m == mod) + { + if (bin_mod_move(m, &bin_active, NULL)) + return -1; + + bin_mod_free(m); + break; + } + + m = next; + } + + return 0; +} + +static int kill(void) +{ + for (struct bin_proc *p = bin_zombie.proc_head; p;) + { + struct bin_proc *const next = p->next; + const struct bin_mod *const mod = p->mod; + bool used = false; + + kprintf("%s exited with status %ld\n", p->path, p->retval); + + if (bin_proc_move(p, &bin_zombie, NULL)) + return -1; + + bin_proc_free(p); + + if (!used && prune(mod)) + return -1; + + p = next; + } + + return 0; +} + +int bin_update(void) +{ + return load() || run() || kill(); +} |
