This commit is contained in:
parent
7293d47bf0
commit
84c1ac4cee
@ -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); }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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], ¶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<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 };
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user