summaryrefslogtreecommitdiff
path: root/src/bin/src/update.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/src/update.c')
-rw-r--r--src/bin/src/update.c145
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();
+}