summaryrefslogtreecommitdiff
path: root/src/kernel/syscalls.c
diff options
context:
space:
mode:
authordzwdz2022-05-26 21:45:34 +0200
committerdzwdz2022-05-26 21:45:34 +0200
commit2dfecbfa898c7db2f5039c81c23a8475966ecfef (patch)
tree74d809b4315f49070c1e780355abdcc909294172 /src/kernel/syscalls.c
parent0604552310847fd695e9cf62fcddb8e18720fc3b (diff)
syscalls/memflag: FINDFREE flag
Diffstat (limited to 'src/kernel/syscalls.c')
-rw-r--r--src/kernel/syscalls.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 4d64d32..540611e 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -250,34 +250,42 @@ int _syscall_fs_respond(char __user *buf, int ret) {
SYSCALL_RETURN(0);
}
-int _syscall_memflag(void __user *addr, size_t len, int flags) {
- userptr_t goal = addr + len;
+void __user *_syscall_memflag(void __user *addr, size_t len, int flags) {
struct pagedir *pages = process_current->pages;
void *phys;
-
addr = (userptr_t)((int __force)addr & ~PAGE_MASK); // align to page boundary
- for (; addr < goal; addr += PAGE_SIZE) {
- if (pagedir_iskern(pages, addr)) {
+
+ if (flags & MEMFLAG_FINDFREE) {
+ addr = pagedir_findfree(pages, addr, len);
+ if (!(flags & MEMFLAG_PRESENT)) goto ret;
+ }
+
+
+ for (userptr_t iter = addr; iter < addr + len; iter += PAGE_SIZE) {
+ if (pagedir_iskern(pages, iter)) {
// TODO reflect failure in return value
continue;
}
- phys = pagedir_virt2phys(pages, addr, false, false);
+ phys = pagedir_virt2phys(pages, iter, false, false);
if (!(flags & MEMFLAG_PRESENT)) {
if (phys)
- page_free(pagedir_unmap(pages, addr), 1);
+ page_free(pagedir_unmap(pages, iter), 1);
continue;
}
if (!phys) {
phys = page_alloc(1);
memset(phys, 0, PAGE_SIZE); // TODO somehow test this
- pagedir_map(pages, addr, phys, true, true);
+ pagedir_map(pages, iter, phys, true, true);
}
}
- SYSCALL_RETURN(-1);
+ret: // the macro is too stupid to handle returning pointers
+ assert(process_current->state == PS_RUNNING); // TODO move to regs_savereturn
+ regs_savereturn(&process_current->regs, (uintptr_t)addr);
+ return addr;
}
int _syscall(int num, int a, int b, int c, int d) {
@@ -303,7 +311,8 @@ int _syscall(int num, int a, int b, int c, int d) {
case _SYSCALL_FS_RESPOND:
return _syscall_fs_respond((userptr_t)a, b);
case _SYSCALL_MEMFLAG:
- return _syscall_memflag((userptr_t)a, b, c);
+ _syscall_memflag((userptr_t)a, b, c);
+ return -1; // unused anyways
default:
kprintf("unknown syscall ");
panic_unimplemented(); // TODO fail gracefully