diff --git a/kernel/src/memory/AddressSpace.cpp b/kernel/src/memory/AddressSpace.cpp index 5ffefe8d..2716110d 100644 --- a/kernel/src/memory/AddressSpace.cpp +++ b/kernel/src/memory/AddressSpace.cpp @@ -94,13 +94,14 @@ AddressSpace& AddressSpace::operator=(AddressSpace&& other) return *this; } -Result AddressSpace::alloc_region(usize count, int prot, int flags, u64 shmid, bool persistent) +Result AddressSpace::alloc_region(usize count, int prot, int flags, off_t offset, u64 shmid, bool persistent) { auto update_region = [=](VMRegion* region) { region->used = true; region->persistent = persistent; region->prot = prot; region->flags = flags; + region->offset = offset; region->shmid = shmid; }; @@ -130,7 +131,7 @@ Result AddressSpace::alloc_region(usize count, int prot, int flags, u64 shm return err(ENOMEM); } -Result AddressSpace::set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid, +Result AddressSpace::set_region(u64 address, usize count, bool used, int prot, int flags, off_t offset, u64 shmid, bool persistent) { if (address >= VM_END) return err(EINVAL); @@ -143,6 +144,7 @@ Result AddressSpace::set_region(u64 address, usize count, bool used, int p region->persistent = persistent; region->prot = prot; region->flags = flags; + region->offset = offset; region->shmid = shmid; }; @@ -200,6 +202,23 @@ Result AddressSpace::set_region(u64 address, usize count, bool used, int p return true; } +Result AddressSpace::sync_regions(u64 address, usize count) +{ + if (address >= VM_END) return err(EINVAL); + + u64 end = address + (count * ARCH_PAGE_SIZE); + + for (auto* region : m_regions) + { + if (region->end < address) continue; + if (region->start > end) return {}; + + region->sync_shared(); + } + + return {}; +} + void AddressSpace::merge_contiguous_regions(VMRegion* a, VMRegion* b) { a->end = b->end; @@ -279,3 +298,12 @@ void VMRegion::cleanup_shared() } } } + +void VMRegion::sync_shared() +{ + if (used && (flags & MAP_SHARED) && (prot & PROT_WRITE)) + { + SharedMemory* shmem = g_shared_memory_map.try_get_ref(shmid); + if (shmem) { shmem->inode->write((const u8*)start, offset, count * ARCH_PAGE_SIZE); } + } +} diff --git a/kernel/src/memory/AddressSpace.h b/kernel/src/memory/AddressSpace.h index 9a96f51d..a5986f18 100644 --- a/kernel/src/memory/AddressSpace.h +++ b/kernel/src/memory/AddressSpace.h @@ -3,6 +3,7 @@ #include #include #include +#include class VMRegion : LinkedListNode { @@ -15,8 +16,10 @@ class VMRegion : LinkedListNode int flags { 0 }; int prot { 0 }; u64 shmid; + off_t offset { 0 }; void cleanup_shared(); + void sync_shared(); }; class AddressSpace @@ -27,19 +30,21 @@ class AddressSpace AddressSpace& operator=(AddressSpace&& other); - Result alloc_region(usize count, int prot, int flags, u64 shmid = 0, bool persistent = false); + Result alloc_region(usize count, int prot, int flags, off_t offset, u64 shmid = 0, bool persistent = false); - Result test_and_alloc_region(u64 address, usize count, int prot, int flags, u64 shmid = 0, + Result test_and_alloc_region(u64 address, usize count, int prot, int flags, off_t offset, u64 shmid = 0, bool persistent = false) { - return set_region(address, count, true, prot, flags, shmid, persistent); + return set_region(address, count, true, prot, flags, offset, shmid, persistent); } Result free_region(u64 address, usize count) { - return set_region(address, count, false, 0, 0, 0, false); + return set_region(address, count, false, 0, 0, 0, 0, false); } + Result sync_regions(u64 address, usize count); + static Result> try_create(); Result> clone(); @@ -50,7 +55,8 @@ class AddressSpace } private: - Result set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid, bool persistent); + Result set_region(u64 address, usize count, bool used, int prot, int flags, off_t offset, u64 shmid, + bool persistent); Result create_default_region(); Result create_null_region(); void try_merge_region_with_neighbors(VMRegion* region); diff --git a/kernel/src/sys/mmap.cpp b/kernel/src/sys/mmap.cpp index 3bde30ac..10a2c088 100644 --- a/kernel/src/sys/mmap.cpp +++ b/kernel/src/sys/mmap.cpp @@ -16,9 +16,6 @@ Result sys_mmap(Registers*, SyscallArgs args) mmap_params params; if (!MemoryManager::copy_from_user_typed((const mmap_params*)args[0], ¶ms)) return err(EFAULT); - kdbgln("mmap: address=%p, len=%zu, prot=%d, flags=%d, fd=%d, offset=%lu", params.addr, params.len, params.prot, - params.flags, params.fd, params.offset); - if (params.len == 0) return err(EINVAL); if (params.flags < 0) return err(EINVAL); @@ -58,13 +55,14 @@ Result sys_mmap(Registers*, SyscallArgs args) u64 address; if (!params.addr) address = TRY(current->address_space->alloc_region(get_blocks_from_size(params.len, ARCH_PAGE_SIZE), - params.prot, params.flags, shmid)); + params.prot, params.flags, params.offset, shmid)); else { // FIXME: We should be more flexible if MAP_FIXED was not specified. address = align_down((u64)params.addr); - if (!TRY(current->address_space->test_and_alloc_region( - address, get_blocks_from_size(params.len, ARCH_PAGE_SIZE), params.prot, params.flags, shmid))) + if (!TRY(current->address_space->test_and_alloc_region(address, + get_blocks_from_size(params.len, ARCH_PAGE_SIZE), + params.prot, params.flags, params.offset, shmid))) return err(ENOMEM); } @@ -110,3 +108,18 @@ Result sys_munmap(Registers*, SyscallArgs args) return { 0 }; } + +Result sys_msync(Registers*, SyscallArgs args) +{ + u64 address = (u64)args[0]; + usize size = (usize)args[1]; + + if (!size) return 0; + if (!is_aligned(address)) return err(EINVAL); + + Thread* current = Scheduler::current(); + + TRY(current->address_space->sync_regions(address, get_blocks_from_size(size, ARCH_PAGE_SIZE))); + + return { 0 }; +} diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 57baf9ae..281e13d5 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -7,7 +7,7 @@ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \ _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \ - _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) + _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) enum Syscalls {