aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/syscall.c
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-03-07 18:27:34 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-03-07 18:27:34 +0100
commitc0ed9fe0d3bd8bf7cf05c5183539e3d72a3d3875 (patch)
treebafb110b838ea4e8b85c18ef618823c2afab51c0 /src/kernel/user/syscall.c
parent92731869cbf96c96b6c79f49310b1982ba3f86ee (diff)
downloadkogata-c0ed9fe0d3bd8bf7cf05c5183539e3d72a3d3875.tar.gz
kogata-c0ed9fe0d3bd8bf7cf05c5183539e3d72a3d3875.zip
Implement wait and exec.
Diffstat (limited to 'src/kernel/user/syscall.c')
-rw-r--r--src/kernel/user/syscall.c72
1 files changed, 68 insertions, 4 deletions
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index fe9b4fe..04144d4 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -1,6 +1,7 @@
#include <string.h>
#include <process.h>
#include <vfs.h>
+#include <elf.h>
#include <sct.h>
@@ -456,19 +457,82 @@ end_bind_fd:
}
static uint32_t proc_exec_sc(sc_args_t args) {
- return -1; //TODO
+ bool ok = false;
+
+ process_t *p = 0;
+ char* exec_name = 0;
+ fs_handle_t *h = 0;
+
+ p = process_find_child(current_process(), args.a);
+ if (p == 0) goto end_exec;
+
+ exec_name = sc_copy_string_x(args.b, args.c);
+ if (exec_name == 0) goto end_exec;
+
+ char* sep = strchr(exec_name, ':');
+ if (sep == 0) goto end_exec;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), exec_name);
+ if (fs == 0) goto end_exec;
+
+ h = fs_open(fs, file, FM_READ | FM_MMAP);
+ if (h == 0) h = fs_open(fs, file, FM_READ);
+ if (h == 0) goto end_exec;
+
+ proc_entry_t *entry = elf_load(h, p);
+ if (entry == 0) goto end_exec;
+
+ ok = start_process(p, entry);
+
+end_exec:
+ if (exec_name) free(exec_name);
+ if (h) unref_file(h);
+ return ok;
}
static uint32_t proc_status_sc(sc_args_t args) {
- return -1; //TODO
+ proc_status_t *st = (proc_status_t*)args.b;
+ probe_for_write(st, sizeof(proc_status_t));
+
+ process_t *p = process_find_child(current_process(), args.a);
+ if (p == 0) return false;
+
+ process_get_status(p, st);
+ return true;
}
static uint32_t proc_kill_sc(sc_args_t args) {
- return -1; //TODO
+ proc_status_t *st = (proc_status_t*)args.b;
+ probe_for_write(st, sizeof(proc_status_t));
+
+ process_t *p = process_find_child(current_process(), args.a);
+ if (p == 0) return false;
+
+ process_exit(p, PS_KILLED, 0);
+ process_wait(p, st, true); // (should return immediately)
+
+ return true;
}
static uint32_t proc_wait_sc(sc_args_t args) {
- return -1; //TODO
+ proc_status_t *st = (proc_status_t*)args.c;
+ probe_for_write(st, sizeof(proc_status_t));
+
+ bool wait = (args.b != 0);
+
+ if (args.a == 0) {
+ process_wait_any_child(current_process(), st, wait);
+ return true;
+ } else {
+ process_t *p = process_find_child(current_process(), args.a);
+ if (p == 0) return false;
+
+ process_wait(p, st, wait);
+ return true;
+ }
}
// ====================== //