kernel: Add msync
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-08-02 22:39:07 +02:00
parent 7293d47bf0
commit 84c1ac4cee
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 61 additions and 14 deletions

View File

@ -94,13 +94,14 @@ AddressSpace& AddressSpace::operator=(AddressSpace&& other)
return *this;
}
Result<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shmid, bool persistent)
Result<u64> 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<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shm
return err(ENOMEM);
}
Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid,
Result<bool> 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<bool> 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<bool> AddressSpace::set_region(u64 address, usize count, bool used, int p
return true;
}
Result<void> 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); }
}
}

View File

@ -3,6 +3,7 @@
#include <luna/LinkedList.h>
#include <luna/OwnedPtr.h>
#include <luna/Result.h>
#include <sys/types.h>
class VMRegion : LinkedListNode<VMRegion>
{
@ -15,8 +16,10 @@ class VMRegion : LinkedListNode<VMRegion>
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<u64> alloc_region(usize count, int prot, int flags, u64 shmid = 0, bool persistent = false);
Result<u64> alloc_region(usize count, int prot, int flags, off_t offset, u64 shmid = 0, bool persistent = false);
Result<bool> test_and_alloc_region(u64 address, usize count, int prot, int flags, u64 shmid = 0,
Result<bool> 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<bool> 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<void> sync_regions(u64 address, usize count);
static Result<OwnedPtr<AddressSpace>> try_create();
Result<OwnedPtr<AddressSpace>> clone();
@ -50,7 +55,8 @@ class AddressSpace
}
private:
Result<bool> set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid, bool persistent);
Result<bool> set_region(u64 address, usize count, bool used, int prot, int flags, off_t offset, u64 shmid,
bool persistent);
Result<void> create_default_region();
Result<void> create_null_region();
void try_merge_region_with_neighbors(VMRegion* region);

View File

@ -16,9 +16,6 @@ Result<u64> sys_mmap(Registers*, SyscallArgs args)
mmap_params params;
if (!MemoryManager::copy_from_user_typed((const mmap_params*)args[0], &params)) 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<u64> 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<ARCH_PAGE_SIZE>((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<u64> sys_munmap(Registers*, SyscallArgs args)
return { 0 };
}
Result<u64> sys_msync(Registers*, SyscallArgs args)
{
u64 address = (u64)args[0];
usize size = (usize)args[1];
if (!size) return 0;
if (!is_aligned<ARCH_PAGE_SIZE>(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 };
}

View File

@ -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
{