diff --git a/kernel/src/fs/devices/Device.h b/kernel/src/fs/devices/Device.h index 130aec8d..df251536 100644 --- a/kernel/src/fs/devices/Device.h +++ b/kernel/src/fs/devices/Device.h @@ -10,6 +10,11 @@ class Device : public Shareable virtual Result write(const u8* buf, usize offset, usize length) = 0; + virtual Result query_shared_memory(off_t, usize) + { + return err(EACCES); + } + virtual Result ioctl(int, void*) { return err(ENOTTY); @@ -44,4 +49,7 @@ class Device : public Shareable virtual bool will_block_if_read() const = 0; virtual ~Device() = default; + + protected: + Option m_shmid; }; diff --git a/kernel/src/fs/devices/FramebufferDevice.cpp b/kernel/src/fs/devices/FramebufferDevice.cpp index 23ab7b32..3b82f095 100644 --- a/kernel/src/fs/devices/FramebufferDevice.cpp +++ b/kernel/src/fs/devices/FramebufferDevice.cpp @@ -1,4 +1,6 @@ #include "fs/devices/FramebufferDevice.h" +#include "arch/MMU.h" +#include "memory/SharedMemory.h" #include "video/Framebuffer.h" #include #include @@ -23,6 +25,32 @@ Result FramebufferDevice::write(const u8* buf, usize offset, usize length return length; } +Result FramebufferDevice::query_shared_memory(off_t offset, usize count) +{ + if (offset + (count * ARCH_PAGE_SIZE) > Framebuffer::size()) return err(EINVAL); + + if (!m_shmid.has_value()) + { + u64 shmid = TRY(SharedMemory::create(Framebuffer::ptr() + offset, offset, count)); + m_shmid = shmid; + auto* shm = g_shared_memory_map.try_get_ref(shmid); + shm->device = SharedPtr { this }; + return shmid; + } + + auto* shm = g_shared_memory_map.try_get_ref(*m_shmid); + if (shm->offset > offset) + { + TRY(shm->grow_backward(Framebuffer::ptr() + offset, (shm->offset - offset) / ARCH_PAGE_SIZE)); + } + if (shm->frames.size() < count) + { + TRY(shm->grow_forward(Framebuffer::ptr() + offset + (shm->frames.size() * ARCH_PAGE_SIZE), + count - shm->frames.size())); + } + return *m_shmid; +} + usize FramebufferDevice::size() const { return Framebuffer::size(); diff --git a/kernel/src/fs/devices/FramebufferDevice.h b/kernel/src/fs/devices/FramebufferDevice.h index 76b5ebb7..f28a0a31 100644 --- a/kernel/src/fs/devices/FramebufferDevice.h +++ b/kernel/src/fs/devices/FramebufferDevice.h @@ -11,6 +11,8 @@ class FramebufferDevice : public Device Result write(const u8*, usize, usize) override; + Result query_shared_memory(off_t offset, usize count) override; + bool will_block_if_read() const override; bool is_block_device() const override diff --git a/kernel/src/memory/AddressSpace.cpp b/kernel/src/memory/AddressSpace.cpp index 2716110d..ea230f74 100644 --- a/kernel/src/memory/AddressSpace.cpp +++ b/kernel/src/memory/AddressSpace.cpp @@ -304,6 +304,10 @@ 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); } + if (shmem) + { + if (shmem->inode) shmem->inode->write((const u8*)start, offset, count * ARCH_PAGE_SIZE); + if (shmem->device) shmem->device->write((const u8*)start, offset, count * ARCH_PAGE_SIZE); + } } } diff --git a/kernel/src/memory/SharedMemory.h b/kernel/src/memory/SharedMemory.h index 7541d918..656c3bd4 100644 --- a/kernel/src/memory/SharedMemory.h +++ b/kernel/src/memory/SharedMemory.h @@ -1,5 +1,6 @@ #pragma once #include "fs/VFS.h" +#include "fs/devices/Device.h" #include #include #include @@ -10,6 +11,7 @@ struct SharedMemory off_t offset; int prot; SharedPtr inode {}; + SharedPtr device {}; int refs { 0 }; static Result create(u8* mem, off_t offset, usize count);