forked from Bananymous/banan-os
Kernel/LibC: Implement very basic msync
This commit is contained in:
parent
ab9954fe73
commit
60e755210c
|
@ -10,6 +10,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
~SharedFileData();
|
~SharedFileData();
|
||||||
|
|
||||||
|
void sync(size_t page_index);
|
||||||
|
|
||||||
// FIXME: this should probably be ordered tree like map
|
// FIXME: this should probably be ordered tree like map
|
||||||
// for fast lookup and less memory usage
|
// for fast lookup and less memory usage
|
||||||
BAN::Vector<paddr_t> pages;
|
BAN::Vector<paddr_t> pages;
|
||||||
|
@ -26,6 +28,8 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
||||||
~FileBackedRegion();
|
~FileBackedRegion();
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
||||||
~MemoryBackedRegion();
|
~MemoryBackedRegion();
|
||||||
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
// Copy data from buffer into this region
|
// Copy data from buffer into this region
|
||||||
// This can fail if no memory is mapped and no free memory was available
|
// This can fail if no memory is mapped and no free memory was available
|
||||||
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace Kernel
|
||||||
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||||
size_t physical_page_count() const { return m_physical_page_count; }
|
size_t physical_page_count() const { return m_physical_page_count; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||||
|
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
// Returns true if page was succesfully allocated
|
// Returns true if page was succesfully allocated
|
||||||
// Returns false if page was already allocated
|
// Returns false if page was already allocated
|
||||||
|
|
|
@ -130,6 +130,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||||
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
||||||
|
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <kernel/Memory/FileBackedRegion.h>
|
#include <kernel/Memory/FileBackedRegion.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -70,17 +72,43 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (pages[i] == 0)
|
if (pages[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
sync(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedFileData::sync(size_t page_index)
|
||||||
|
{
|
||||||
|
// FIXME: should this be locked?
|
||||||
|
|
||||||
|
if (pages[page_index] == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
PageTable::map_fast_page(pages[i]);
|
PageTable::with_fast_page(pages[page_index], [&] {
|
||||||
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
||||||
PageTable::unmap_fast_page();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
|
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
|
||||||
dwarnln("{}", ret.error());
|
dwarnln("{}", ret.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags)
|
||||||
|
{
|
||||||
|
if (flags != MS_SYNC)
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
if (m_type != Type::SHARED)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
vaddr_t first_page = address & PAGE_ADDR_MASK;
|
||||||
|
vaddr_t last_page = BAN::Math::div_round_up<vaddr_t>(address + size, PAGE_SIZE) * PAGE_SIZE;
|
||||||
|
|
||||||
|
for (vaddr_t page_addr = first_page; page_addr < last_page; page_addr += PAGE_SIZE)
|
||||||
|
if (contains(page_addr))
|
||||||
|
m_shared_data->sync((page_addr - m_vaddr) / PAGE_SIZE);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<bool> FileBackedRegion::allocate_page_containing_impl(vaddr_t address)
|
BAN::ErrorOr<bool> FileBackedRegion::allocate_page_containing_impl(vaddr_t address)
|
||||||
|
|
|
@ -1098,6 +1098,24 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_msync(void* addr, size_t len, int flags)
|
||||||
|
{
|
||||||
|
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
vaddr_t vaddr = (vaddr_t)addr;
|
||||||
|
if (vaddr % PAGE_SIZE != 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
for (auto& mapped_region : m_mapped_regions)
|
||||||
|
if (mapped_region->overlaps(vaddr, len))
|
||||||
|
TRY(mapped_region->msync(vaddr, len, flags));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
|
@ -217,6 +217,9 @@ namespace Kernel
|
||||||
case SYS_READLINKAT:
|
case SYS_READLINKAT:
|
||||||
ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4);
|
ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4);
|
||||||
break;
|
break;
|
||||||
|
case SYS_MSYNC:
|
||||||
|
ret = Process::current().sys_msync((void*)arg1, (size_t)arg2, (int)arg3);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dwarnln("Unknown syscall {}", syscall);
|
dwarnln("Unknown syscall {}", syscall);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -61,6 +61,7 @@ __BEGIN_DECLS
|
||||||
#define SYS_UNLINK 58
|
#define SYS_UNLINK 58
|
||||||
#define SYS_READLINK 59
|
#define SYS_READLINK 59
|
||||||
#define SYS_READLINKAT 60
|
#define SYS_READLINKAT 60
|
||||||
|
#define SYS_MSYNC 61
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -22,3 +22,8 @@ int munmap(void* addr, size_t len)
|
||||||
{
|
{
|
||||||
return syscall(SYS_MUNMAP, addr, len);
|
return syscall(SYS_MUNMAP, addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msync(void* addr, size_t len, int flags)
|
||||||
|
{
|
||||||
|
return syscall(SYS_MSYNC, addr, len, flags);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue