From fc40820150a86f19fc11e24456e885479582cdc4 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 8 Aug 2026 01:51:43 +0300 Subject: [PATCH] Kernel/Userspace: Replace my custom SHM system with SysV shm This allows xbanan to use shm! --- kernel/arch/i686/Signal.S | 2 +- kernel/arch/x86_64/Signal.S | 2 +- .../kernel/Memory/SharedMemoryObject.h | 59 ++--- kernel/include/kernel/Process.h | 11 +- kernel/kernel/Memory/SharedMemoryObject.cpp | 222 +++++++++++++++--- kernel/kernel/Process.cpp | 54 ++--- kernel/kernel/Thread.cpp | 2 +- userspace/libraries/LibAudio/Audio.cpp | 29 +-- .../LibAudio/include/LibAudio/Audio.h | 3 +- .../libraries/LibC/include/sys/banan-os.h | 7 - userspace/libraries/LibC/include/sys/ipc.h | 16 +- userspace/libraries/LibC/include/sys/shm.h | 6 +- .../libraries/LibC/include/sys/syscall.h | 7 +- userspace/libraries/LibC/sys/banan-os.cpp | 18 -- userspace/libraries/LibC/sys/shm.cpp | 31 ++- userspace/libraries/LibGUI/Window.cpp | 21 +- .../libraries/LibGUI/include/LibGUI/Packet.h | 2 +- .../libraries/LibGUI/include/LibGUI/Window.h | 2 +- .../libraries/LibInput/KeyboardLayout.cpp | 2 +- .../programs/AudioServer/AudioServer.cpp | 12 +- userspace/programs/WindowServer/Window.cpp | 33 ++- userspace/programs/WindowServer/Window.h | 4 +- .../programs/WindowServer/WindowServer.cpp | 7 +- 23 files changed, 327 insertions(+), 225 deletions(-) diff --git a/kernel/arch/i686/Signal.S b/kernel/arch/i686/Signal.S index 9552c355..47b08305 100644 --- a/kernel/arch/i686/Signal.S +++ b/kernel/arch/i686/Signal.S @@ -59,7 +59,7 @@ signal_trampoline: addl $24, %esp // restore sigmask - movl $78, %eax // SYS_SIGPROCMASK + movl $79, %eax // SYS_SIGPROCMASK movl $3, %ebx // SIG_SETMASK leal 72(%esp), %ecx // set xorl %edx, %edx // oset diff --git a/kernel/arch/x86_64/Signal.S b/kernel/arch/x86_64/Signal.S index 07bd5e5e..27ca40de 100644 --- a/kernel/arch/x86_64/Signal.S +++ b/kernel/arch/x86_64/Signal.S @@ -61,7 +61,7 @@ signal_trampoline: addq $40, %rsp // restore sigmask - movq $78, %rdi // SYS_SIGPROCMASK + movq $79, %rdi // SYS_SIGPROCMASK movq $3, %rsi // SIG_SETMASK leaq 192(%rsp), %rdx // set xorq %r10, %r10 // oset diff --git a/kernel/include/kernel/Memory/SharedMemoryObject.h b/kernel/include/kernel/Memory/SharedMemoryObject.h index fafa5bfa..2a6d8a86 100644 --- a/kernel/include/kernel/Memory/SharedMemoryObject.h +++ b/kernel/include/kernel/Memory/SharedMemoryObject.h @@ -6,25 +6,20 @@ #include #include -#include +#include namespace Kernel { - class SharedMemoryObject; - class SharedMemoryObjectManager { - public: - using Key = size_t; - public: static BAN::ErrorOr initialize(); static SharedMemoryObjectManager& get(); - BAN::ErrorOr create_object(size_t size, PageTable::flags_t); - BAN::ErrorOr delete_object(Key); - BAN::ErrorOr> map_object(Key, PageTable&, AddressRange); + BAN::ErrorOr shmget(key_t key, size_t size, int shmflg); + BAN::ErrorOr shmctl(int shmid, int cmd, struct shmid_ds* user_buf); + BAN::ErrorOr> shmat(int shmid, const void* shmaddr, int shmflg); private: SharedMemoryObjectManager() {} @@ -32,49 +27,29 @@ namespace Kernel private: struct Object : public BAN::RefCounted { + Object(key_t key, shmid_ds info) + : key(key) + , info(info) + { } ~Object(); - Key key; - size_t size; - PageTable::flags_t flags; + bool can_current_process_access(int flags) const; + + const key_t key; + shmid_ds info; + + Mutex mutex; BAN::Vector paddrs; - SpinLock spin_lock; + bool marked_for_deletion { false }; }; private: Mutex m_mutex; - BAN::HashMap> m_objects; + BAN::HashMap m_ids; + BAN::HashMap> m_objects; friend class SharedMemoryObject; friend class BAN::UniqPtr; }; - class SharedMemoryObject : public MemoryRegion - { - BAN_NON_COPYABLE(SharedMemoryObject); - BAN_NON_MOVABLE(SharedMemoryObject); - - public: - static BAN::ErrorOr> create(BAN::RefPtr, PageTable&, AddressRange); - - BAN::ErrorOr> clone(PageTable& new_page_table) override; - BAN::ErrorOr> split(size_t offset) override; - - BAN::ErrorOr msync(vaddr_t, size_t, int) override { return {}; } - - protected: - BAN::ErrorOr allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override; - - private: - SharedMemoryObject(BAN::RefPtr object, PageTable& page_table) - : MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR) - , m_object(object) - { } - - private: - BAN::RefPtr m_object; - - friend class BAN::UniqPtr; - }; - } diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index fe361a2f..6fa94371 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -179,9 +179,10 @@ namespace Kernel BAN::ErrorOr sys_mprotect(void* addr, size_t len, int prot); BAN::ErrorOr sys_msync(void* addr, size_t len, int flags); - BAN::ErrorOr sys_smo_create(size_t len, int prot); - BAN::ErrorOr sys_smo_delete(SharedMemoryObjectManager::Key); - BAN::ErrorOr sys_smo_map(SharedMemoryObjectManager::Key); + BAN::ErrorOr sys_shmget(key_t key, size_t size, int shmflg); + BAN::ErrorOr sys_shmctl(int shmid, int cmd, struct shmid_ds* buf); + BAN::ErrorOr sys_shmat(int shmid, const void* shmaddr, int shmflg); + BAN::ErrorOr sys_shmdt(const void* shmaddr); BAN::ErrorOr sys_ttyname(int fildes, char* name, size_t namesize); BAN::ErrorOr sys_posix_openpt(int flags); @@ -255,6 +256,8 @@ namespace Kernel const VirtualFileSystem::File& working_directory() const { return m_working_directory; } const VirtualFileSystem::File& root_file() const { return m_root_file; } + BAN::ErrorOr find_free_address_range(size_t size); + private: Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp); static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0); @@ -280,8 +283,6 @@ namespace Kernel // You must hold reader end of m_mapped_region_lock when calling this. size_t find_mapped_region(vaddr_t) const; - BAN::ErrorOr find_free_address_range(size_t size); - BAN::ErrorOr find_file(int fd, const char* path, int flags) const; BAN::ErrorOr find_parent_file(int fd, const char* path, int flags) const; BAN::ErrorOr find_relative_parent(int fd, const char* path) const; diff --git a/kernel/kernel/Memory/SharedMemoryObject.cpp b/kernel/kernel/Memory/SharedMemoryObject.cpp index 45e95946..94a8f252 100644 --- a/kernel/kernel/Memory/SharedMemoryObject.cpp +++ b/kernel/kernel/Memory/SharedMemoryObject.cpp @@ -1,13 +1,44 @@ #include #include #include +#include #include +#include +#include + +#include namespace Kernel { static BAN::UniqPtr s_instance; + class SharedMemoryObject : public MemoryRegion + { + BAN_NON_COPYABLE(SharedMemoryObject); + BAN_NON_MOVABLE(SharedMemoryObject); + + public: + static BAN::ErrorOr> create(BAN::RefPtr, PageTable&, AddressRange, int status_flags); + ~SharedMemoryObject(); + + BAN::ErrorOr> clone(PageTable& new_page_table) override; + BAN::ErrorOr> split(size_t offset) override; + + BAN::ErrorOr msync(vaddr_t, size_t, int) override { return {}; } + + protected: + BAN::ErrorOr allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override; + + private: + SharedMemoryObject(BAN::RefPtr, PageTable& page_table, int status_flags); + + private: + BAN::RefPtr m_object; + + friend class BAN::UniqPtr; + }; + BAN::ErrorOr SharedMemoryObjectManager::initialize() { ASSERT(!s_instance); @@ -28,70 +59,189 @@ namespace Kernel Heap::get().release_page(paddr); } - BAN::ErrorOr SharedMemoryObjectManager::create_object(size_t size, PageTable::flags_t flags) + BAN::ErrorOr SharedMemoryObjectManager::shmget(key_t key, size_t size, int shmflg) { - ASSERT(size % PAGE_SIZE == 0); - - auto object = TRY(BAN::RefPtr::create()); - object->size = size; - object->flags = flags; - TRY(object->paddrs.resize(size / PAGE_SIZE, 0)); - LockGuard _(m_mutex); - // NOTE: don't set the top bit so cast to signed is not negative - auto generate_key = []() { return Random::get() & (~(Key)0 >> 1); }; + if (key != IPC_PRIVATE) + { + if (auto it = m_ids.find(key); it != m_ids.end()) + { + if (shmflg & IPC_EXCL) + return BAN::Error::from_errno(EEXIST); - Key key = generate_key(); - while (m_objects.contains(key)) - key = generate_key(); - object->key = key; + const auto& object = m_objects[it->value]; + if (object->info.shm_segsz < size) + return BAN::Error::from_errno(EINVAL); - TRY(m_objects.insert(key, object)); - return key; + const int flags = + (shmflg & S_IRUSR ? O_RDONLY : 0) | + (shmflg & S_IWUSR ? O_WRONLY : 0); + if (!object->can_current_process_access(flags)) + return BAN::Error::from_errno(EACCES); + + return it->value; + } + + if (!(shmflg & IPC_CREAT)) + return BAN::Error::from_errno(ENOENT); + } + + const auto& process = Process::current(); + const uid_t uid = process.credentials().euid(); + const gid_t gid = process.credentials().egid(); + const pid_t pid = process.pid(); + const mode_t mode = shmflg & 0777; + + auto object = TRY(BAN::RefPtr::create(key, shmid_ds { + .shm_perm = { + .uid = uid, + .gid = gid, + .cuid = uid, + .cgid = uid, + .mode = mode, + }, + .shm_segsz = size, + .shm_lpid = 0, + .shm_cpid = pid, + .shm_nattch = 0, + .shm_atime = 0, + .shm_dtime = 0, + .shm_ctime = SystemTimer::get().real_time().tv_sec, + })); + TRY(object->paddrs.resize(BAN::Math::div_round_up(size, PAGE_SIZE), 0)); + + auto generate_id = []() { return Random::get() & BAN::numeric_limits::max(); }; + + int shmid = generate_id(); + while (m_ids.contains(shmid)) + shmid = generate_id(); + + if (key != IPC_PRIVATE) + TRY(m_ids.insert(key, shmid)); + + if (auto ret = m_objects.insert(shmid, object); ret.is_error()) + { + if (key != IPC_PRIVATE) + m_ids.remove(key); + return ret.release_error(); + } + + return shmid; } - BAN::ErrorOr SharedMemoryObjectManager::delete_object(Key key) + BAN::ErrorOr SharedMemoryObjectManager::shmctl(int shmid, int cmd, struct shmid_ds* user_buf) { - LockGuard _(m_mutex); + LockGuard _0(m_mutex); - auto it = m_objects.find(key); + auto it = m_objects.find(shmid); if (it == m_objects.end()) - return BAN::Error::from_errno(ENOENT); + return BAN::Error::from_errno(EINVAL); + + LockGuard _1(it->value->mutex); + + switch (cmd) + { + case IPC_RMID: + if (!it->value->can_current_process_access(O_WRONLY)) + return BAN::Error::from_errno(EACCES); + if (it->key != IPC_PRIVATE) + m_ids.remove(it->key); + if (it->value->info.shm_nattch == 0) + m_objects.remove(it); + else + it->value->marked_for_deletion = true; + break; + case IPC_STAT: + TRY(write_to_user(user_buf, &it->value->info, sizeof(shmid_ds))); + break; + case IPC_SET: + { + if (!it->value->can_current_process_access(O_WRONLY)) + return BAN::Error::from_errno(EACCES); + shmid_ds buf; + TRY(read_from_user(user_buf, &buf, sizeof(shmid_ds))); + it->value->info.shm_perm.uid = buf.shm_perm.uid; + it->value->info.shm_perm.gid = buf.shm_perm.gid; + it->value->info.shm_perm.mode = buf.shm_perm.mode & 0777; + break; + } + default: + return BAN::Error::from_errno(EINVAL); + } - m_objects.remove(it); return {}; } - BAN::ErrorOr> SharedMemoryObjectManager::map_object(Key key, PageTable& page_table, AddressRange address_range) + BAN::ErrorOr> SharedMemoryObjectManager::shmat(int shmid, const void* shmaddr, int shmflg) { LockGuard _(m_mutex); - auto it = m_objects.find(key); + auto it = m_objects.find(shmid); if (it == m_objects.end()) return BAN::Error::from_errno(ENOENT); - return TRY(SharedMemoryObject::create(it->value, page_table, address_range)); + const int status_flags = (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR; + if (!it->value->can_current_process_access(status_flags)) + return BAN::Error::from_errno(EACCES); + + const AddressRange address_range = (shmaddr == nullptr) + ? AddressRange { .start = 0x400000, .end = USERSPACE_END } + : TRY(Process::current().find_free_address_range(it->value->info.shm_segsz)); + + auto region = TRY(SharedMemoryObject::create(it->value, Process::current().page_table(), address_range, status_flags)); + return BAN::UniqPtr(BAN::move(region)); } - BAN::ErrorOr> SharedMemoryObject::create(BAN::RefPtr object, PageTable& page_table, AddressRange address_range) + bool SharedMemoryObjectManager::Object::can_current_process_access(int flags) const { - auto smo = TRY(BAN::UniqPtr::create(object, page_table)); - TRY(smo->initialize(address_range)); - return BAN::move(smo); + const auto& creds = Process::current().credentials(); + if (Inode::can_access(info.shm_perm.uid, info.shm_perm.gid, info.shm_perm.mode, creds, flags)) + return true; + if (Inode::can_access(info.shm_perm.cuid, info.shm_perm.cgid, info.shm_perm.mode, creds, flags)) + return true; + return false; + } + + BAN::ErrorOr> SharedMemoryObject::create(BAN::RefPtr object, PageTable& page_table, AddressRange address_range, int status_flags) + { + auto shared_memory_object = TRY(BAN::UniqPtr::create(object, page_table, status_flags)); + TRY(shared_memory_object->initialize(address_range)); + return shared_memory_object; + } + + SharedMemoryObject::SharedMemoryObject(BAN::RefPtr object, PageTable& page_table, int status_flags) + : MemoryRegion( + page_table, + object->info.shm_segsz, + MemoryRegion::Type::SHARED, + PageTable::UserSupervisor | ((status_flags & O_WRONLY) ? PageTable::ReadWrite : 0) | PageTable::Present, + status_flags + ), m_object(object) + { + LockGuard _(m_object->mutex); + m_object->info.shm_nattch++; + m_object->info.shm_atime = SystemTimer::get().real_time().tv_sec; + } + + SharedMemoryObject::~SharedMemoryObject() + { + LockGuard _(m_object->mutex); + if (--m_object->info.shm_nattch == 0 && m_object->marked_for_deletion) + SharedMemoryObjectManager::get().m_objects.remove(m_object->key); + m_object->info.shm_dtime = SystemTimer::get().real_time().tv_sec; } BAN::ErrorOr> SharedMemoryObject::clone(PageTable& new_page_table) { - auto region = TRY(SharedMemoryObject::create(m_object, new_page_table, { .start = vaddr(), .end = vaddr() + size() })); + auto region = TRY(SharedMemoryObject::create(m_object, new_page_table, { .start = vaddr(), .end = vaddr() + size() }, m_status_flags)); return BAN::UniqPtr(BAN::move(region)); } - BAN::ErrorOr> SharedMemoryObject::split(size_t offset) + BAN::ErrorOr> SharedMemoryObject::split(size_t) { - (void)offset; - dwarnln("TODO: SharedMemoryObject::split"); - return BAN::Error::from_errno(ENOTSUP); + derrorln("SharedMemoryObjects are not splittable"); + return BAN::Error::from_errno(EINVAL); } BAN::ErrorOr SharedMemoryObject::allocate_page_containing_impl(vaddr_t address, bool wants_write) @@ -99,12 +249,11 @@ namespace Kernel ASSERT(contains(address)); (void)wants_write; - // Check if address is already mapped - vaddr_t vaddr = address & PAGE_ADDR_MASK; + const vaddr_t vaddr = address & PAGE_ADDR_MASK; if (m_page_table.physical_address_of(vaddr) != 0) return false; - SpinLockGuard _(m_object->spin_lock); + LockGuard _(m_object->mutex); paddr_t paddr = m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE]; if (paddr == 0) @@ -117,6 +266,7 @@ namespace Kernel }); m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE] = paddr; } + m_page_table.map_page_at(paddr, vaddr, m_flags); return true; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 0d323619..c721b72f 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -2928,48 +2928,46 @@ namespace Kernel return 0; } - BAN::ErrorOr Process::sys_smo_create(size_t len, int prot) + BAN::ErrorOr Process::sys_shmget(key_t key, size_t size, int shmflg) { - if (len == 0) - return BAN::Error::from_errno(EINVAL); - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NONE)) - return BAN::Error::from_errno(EINVAL); - - if (auto rem = len % PAGE_SIZE) - len += PAGE_SIZE - rem; - - PageTable::flags_t page_flags = 0; - if (prot & PROT_READ) - page_flags |= PageTable::Flags::Present; - if (prot & PROT_WRITE) - page_flags |= PageTable::Flags::ReadWrite | PageTable::Flags::Present; - if (prot & PROT_EXEC) - page_flags |= PageTable::Flags::Execute | PageTable::Flags::Present; - - if (page_flags == 0) - page_flags |= PageTable::Flags::Reserved; - else - page_flags |= PageTable::Flags::UserSupervisor; - - return TRY(SharedMemoryObjectManager::get().create_object(len, page_flags)); + return TRY(SharedMemoryObjectManager::get().shmget(key, size, shmflg)); } - BAN::ErrorOr Process::sys_smo_delete(SharedMemoryObjectManager::Key key) + BAN::ErrorOr Process::sys_shmctl(int shmid, int cmd, struct shmid_ds* user_buf) { - TRY(SharedMemoryObjectManager::get().delete_object(key)); + TRY(SharedMemoryObjectManager::get().shmctl(shmid, cmd, user_buf)); return 0; } - BAN::ErrorOr Process::sys_smo_map(SharedMemoryObjectManager::Key key) + BAN::ErrorOr Process::sys_shmat(int shmid, const void* shmaddr, int shmflg) { - auto region = TRY(SharedMemoryObjectManager::get().map_object(key, page_table(), { .start = 0x400000, .end = USERSPACE_END })); + RWLockWRGuard _(m_memory_region_lock); + + auto region = TRY(SharedMemoryObjectManager::get().shmat(shmid, shmaddr, shmflg)); - LockGuard _(m_process_lock); const vaddr_t region_vaddr = region->vaddr(); + TRY(add_mapped_region(BAN::move(region))); + return region_vaddr; } + BAN::ErrorOr Process::sys_shmdt(const void* shmaddr) + { + const vaddr_t vaddr = reinterpret_cast(shmaddr); + + RWLockWRGuard _(m_memory_region_lock); + + const size_t idx = find_mapped_region(vaddr); + if (idx >= m_mapped_regions.size() || m_mapped_regions[idx]->vaddr() != vaddr) + return BAN::Error::from_errno(ENOENT); + + m_mapped_regions[idx]->wait_not_pinned(); + m_mapped_regions.remove(idx); + + return 0; + } + BAN::ErrorOr Process::sys_ttyname(int fildes, char* user_buffer, size_t buffer_size) { auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 6ee37196..9be966f8 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -15,7 +15,7 @@ namespace Kernel { - static_assert(SYS_SIGPROCMASK == 78, "this is hard coded in arch/*/Signal.S"); + static_assert(SYS_SIGPROCMASK == 79, "this is hard coded in arch/*/Signal.S"); static_assert(SIG_SETMASK == 3, "this is hard coded in arch/*/Signal.S"); extern "C" [[noreturn]] void start_kernel_thread(); diff --git a/userspace/libraries/LibAudio/Audio.cpp b/userspace/libraries/LibAudio/Audio.cpp index 993732b9..a20f1d99 100644 --- a/userspace/libraries/LibAudio/Audio.cpp +++ b/userspace/libraries/LibAudio/Audio.cpp @@ -5,8 +5,7 @@ #include #include -#include -#include +#include #include #include @@ -49,12 +48,10 @@ namespace LibAudio void Audio::clear() { if (m_audio_buffer) - munmap(m_audio_buffer, m_smo_size); + shmdt(m_audio_buffer); m_audio_buffer = nullptr; - if (m_smo_key != -1) - smo_delete(m_smo_key); - m_smo_key = -1; + m_shmid = -1; if (m_server_fd != -1) close(m_server_fd); @@ -68,14 +65,12 @@ namespace LibAudio clear(); m_server_fd = other.m_server_fd; - m_smo_key = other.m_smo_key; - m_smo_size = other.m_smo_size; + m_shmid = other.m_shmid; m_audio_buffer = other.m_audio_buffer; m_audio_loader = BAN::move(other.m_audio_loader); other.m_server_fd = -1; - other.m_smo_key = -1; - other.m_smo_size = 0; + other.m_shmid = -1; other.m_audio_buffer = nullptr; return *this; @@ -83,14 +78,16 @@ namespace LibAudio BAN::ErrorOr Audio::initialize(uint32_t total_samples) { - m_smo_size = sizeof(AudioBuffer) + total_samples * sizeof(AudioBuffer::sample_t); + const size_t shm_size = sizeof(AudioBuffer) + total_samples * sizeof(AudioBuffer::sample_t); - m_smo_key = smo_create(m_smo_size, PROT_READ | PROT_WRITE); - if (m_smo_key == -1) + m_shmid = shmget(IPC_PRIVATE, shm_size, 0666); + if (m_shmid == -1) return BAN::Error::from_errno(errno); - m_audio_buffer = static_cast(smo_map(m_smo_key)); - if (m_audio_buffer == nullptr) + m_audio_buffer = static_cast(shmat(m_shmid, nullptr, 0)); + shmctl(m_shmid, IPC_RMID, nullptr); + + if (m_audio_buffer == SHM_FAILED) return BAN::Error::from_errno(errno); new (m_audio_buffer) AudioBuffer(); memset(m_audio_buffer->samples, 0, total_samples * sizeof(AudioBuffer::sample_t)); @@ -124,7 +121,7 @@ namespace LibAudio const LibAudio::Packet packet { .type = LibAudio::Packet::RegisterBuffer, - .parameter = static_cast(m_smo_key), + .parameter = static_cast(m_shmid), }; const ssize_t nsend = send(m_server_fd, &packet, sizeof(packet), 0); diff --git a/userspace/libraries/LibAudio/include/LibAudio/Audio.h b/userspace/libraries/LibAudio/include/LibAudio/Audio.h index 608ac490..7d2d8d93 100644 --- a/userspace/libraries/LibAudio/include/LibAudio/Audio.h +++ b/userspace/libraries/LibAudio/include/LibAudio/Audio.h @@ -62,8 +62,7 @@ namespace LibAudio BAN::UniqPtr m_audio_loader; - long m_smo_key { -1 }; - size_t m_smo_size { 0 }; + int m_shmid { -1 }; AudioBuffer* m_audio_buffer { nullptr }; }; diff --git a/userspace/libraries/LibC/include/sys/banan-os.h b/userspace/libraries/LibC/include/sys/banan-os.h index 6d93e4ff..f2e17bf1 100644 --- a/userspace/libraries/LibC/include/sys/banan-os.h +++ b/userspace/libraries/LibC/include/sys/banan-os.h @@ -43,13 +43,6 @@ int poweroff(int command); int load_keymap(const char* path); -// Create shared memory object and return its key or -1 on error -long smo_create(size_t size, int prot); -// Delete shared memory object such that it will be no longer accessible with smo_map(). Existing mappings are still valid -int smo_delete(long key); -// Map shared memory object defined by its key and return address or null on error. Mappings can be unmapped using munmap() -void* smo_map(long key); - __END_DECLS #endif diff --git a/userspace/libraries/LibC/include/sys/ipc.h b/userspace/libraries/LibC/include/sys/ipc.h index e35a169e..2dba162e 100644 --- a/userspace/libraries/LibC/include/sys/ipc.h +++ b/userspace/libraries/LibC/include/sys/ipc.h @@ -22,13 +22,15 @@ struct ipc_perm mode_t mode; /* Read/write permission. */ }; -#define IPC_CREAT 0x01 -#define IPC_EXCL 0x02 -#define IPC_NOWAIT 0x04 -#define IPC_PRIVATE 0x08 -#define IPC_RMID 0x10 -#define IPC_SET 0x20 -#define IPC_STAT 0x40 +#define IPC_CREAT 01000 +#define IPC_EXCL 02000 +#define IPC_NOWAIT 04000 + +#define IPC_PRIVATE 0 + +#define IPC_RMID 1 +#define IPC_SET 2 +#define IPC_STAT 3 key_t ftok(const char* path, int id); diff --git a/userspace/libraries/LibC/include/sys/shm.h b/userspace/libraries/LibC/include/sys/shm.h index eedc112a..fa01cea1 100644 --- a/userspace/libraries/LibC/include/sys/shm.h +++ b/userspace/libraries/LibC/include/sys/shm.h @@ -12,14 +12,14 @@ __BEGIN_DECLS #define __need_time_t #include +#include #include - #include #define SHM_RDONLY 0x01 #define SHM_RND 0x02 - -#define SHMLBA (sysconf(_SC_PAGE_SIZE)) +#define SHM_FAILED ((void*)(intptr_t)-1) +#define SHMLBA (getpagesize()) typedef unsigned int shmatt_t; diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index 24debd9d..975af757 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -72,9 +72,10 @@ __BEGIN_DECLS O(SYS_PSELECT, pselect) \ O(SYS_PPOLL, ppoll) \ O(SYS_FTRUNCATE, ftruncate) \ - O(SYS_SMO_CREATE, smo_create) \ - O(SYS_SMO_DELETE, smo_delete) \ - O(SYS_SMO_MAP, smo_map) \ + O(SYS_SHMAT, shmat) \ + O(SYS_SHMDT, shmdt) \ + O(SYS_SHMGET, shmget) \ + O(SYS_SHMCTL, shmctl) \ O(SYS_GETSOCKNAME, getsockname) \ O(SYS_GETPEERNAME, getpeername) \ O(SYS_GETSOCKOPT, getsockopt) \ diff --git a/userspace/libraries/LibC/sys/banan-os.cpp b/userspace/libraries/LibC/sys/banan-os.cpp index 67489aba..bdeccd55 100644 --- a/userspace/libraries/LibC/sys/banan-os.cpp +++ b/userspace/libraries/LibC/sys/banan-os.cpp @@ -16,21 +16,3 @@ int load_keymap(const char* path) { return syscall(SYS_LOAD_KEYMAP, path); } - -long smo_create(size_t size, int prot) -{ - return syscall(SYS_SMO_CREATE, size, prot); -} - -int smo_delete(long key) -{ - return syscall(SYS_SMO_DELETE, key); -} - -void* smo_map(long key) -{ - long ret = syscall(SYS_SMO_MAP, key); - if (ret < 0) - return nullptr; - return reinterpret_cast(ret); -} diff --git a/userspace/libraries/LibC/sys/shm.cpp b/userspace/libraries/LibC/sys/shm.cpp index ea07066d..bfd7adc8 100644 --- a/userspace/libraries/LibC/sys/shm.cpp +++ b/userspace/libraries/LibC/sys/shm.cpp @@ -1,11 +1,26 @@ -#include - -#include #include +#include +#include -#define TODO_FUNC(type, name, ...) type name(__VA_ARGS__) { dwarnln("TODO: " #name); errno = ENOTSUP; return (type)-1; } +void* shmat(int shmid, const void* shmaddr, int shmflg) +{ + const auto result = syscall(SYS_SHMAT, shmid, shmaddr, shmflg); + if (result == -1) + return SHM_FAILED; + return reinterpret_cast(result); +} -TODO_FUNC(void*, shmat, int, const void*, int) -TODO_FUNC(int, shmctl, int, int, struct shmid_ds*) -TODO_FUNC(int, shmdt, const void*) -TODO_FUNC(int, shmget, key_t, size_t, int) +int shmctl(int shmid, int cmd, struct shmid_ds* buf) +{ + return syscall(SYS_SHMCTL, shmid, cmd, buf); +} + +int shmdt(const void* shmaddr) +{ + return syscall(SYS_SHMDT, shmaddr); +} + +int shmget(key_t key, size_t size, int shmflg) +{ + return syscall(SYS_SHMGET, key, size, shmflg); +} diff --git a/userspace/libraries/LibGUI/Window.cpp b/userspace/libraries/LibGUI/Window.cpp index 607421eb..0b44eee5 100644 --- a/userspace/libraries/LibGUI/Window.cpp +++ b/userspace/libraries/LibGUI/Window.cpp @@ -4,9 +4,8 @@ #include #include -#include #include -#include +#include #include #include #include @@ -165,7 +164,7 @@ namespace LibGUI if (width == m_width) { copy_func( - &m_framebuffer_smo[y * m_width], + &m_framebuffer_shm[y * m_width], &m_texture.pixels()[y * m_width], width * height * sizeof(uint32_t) ); @@ -173,7 +172,7 @@ namespace LibGUI else for (uint32_t y_off = 0; y_off < height; y_off++) { copy_func( - &m_framebuffer_smo[(y + y_off) * m_width + x], + &m_framebuffer_shm[(y + y_off) * m_width + x], &m_texture.pixels()[(y + y_off) * m_width + x], width * sizeof(uint32_t) ); @@ -311,31 +310,31 @@ namespace LibGUI void Window::cleanup() { - munmap(m_framebuffer_smo, m_width * m_height * 4); + shmdt(m_framebuffer_shm); close(m_server_fd); close(m_epoll_fd); } BAN::ErrorOr Window::handle_resize_event(const EventPacket::ResizeWindowEvent& event) { - void* framebuffer_addr = smo_map(event.smo_key); - if (framebuffer_addr == nullptr) + void* framebuffer_addr = shmat(event.shmid, nullptr, 0); + if (framebuffer_addr == SHM_FAILED) { if (errno == ENOENT) return false; return BAN::Error::from_errno(errno); } - if (m_framebuffer_smo) - munmap(m_framebuffer_smo, m_width * m_height * 4); - m_framebuffer_smo = nullptr; + if (m_framebuffer_shm) + shmdt(m_framebuffer_shm); + m_framebuffer_shm = nullptr; TRY(m_texture.resize(event.width, event.height)); if (m_root_widget) TRY(m_root_widget->set_fixed_geometry({ 0, 0, event.width, event.height })); - m_framebuffer_smo = static_cast(framebuffer_addr); + m_framebuffer_shm = static_cast(framebuffer_addr); m_width = event.width; m_height = event.height; diff --git a/userspace/libraries/LibGUI/include/LibGUI/Packet.h b/userspace/libraries/LibGUI/include/LibGUI/Packet.h index b33f12f0..6f219f62 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Packet.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Packet.h @@ -333,7 +333,7 @@ namespace LibGUI ResizeWindowEvent, uint32_t, width, uint32_t, height, - long, smo_key + long, shmid ); DEFINE_PACKET_EXTRA( diff --git a/userspace/libraries/LibGUI/include/LibGUI/Window.h b/userspace/libraries/LibGUI/include/LibGUI/Window.h index 9b2b6461..c0cc544d 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Window.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Window.h @@ -115,7 +115,7 @@ namespace LibGUI Attributes m_attributes; - uint32_t* m_framebuffer_smo { nullptr }; + uint32_t* m_framebuffer_shm { nullptr }; uint32_t m_width { 0 }; uint32_t m_height { 0 }; diff --git a/userspace/libraries/LibInput/KeyboardLayout.cpp b/userspace/libraries/LibInput/KeyboardLayout.cpp index c0724c8b..aaeaa25e 100644 --- a/userspace/libraries/LibInput/KeyboardLayout.cpp +++ b/userspace/libraries/LibInput/KeyboardLayout.cpp @@ -8,13 +8,13 @@ #include #include #else -#include #include #include #include #endif #include +#include namespace LibInput { diff --git a/userspace/programs/AudioServer/AudioServer.cpp b/userspace/programs/AudioServer/AudioServer.cpp index eca8ef32..87483cef 100644 --- a/userspace/programs/AudioServer/AudioServer.cpp +++ b/userspace/programs/AudioServer/AudioServer.cpp @@ -1,8 +1,7 @@ #include "AudioServer.h" -#include #include -#include +#include #include #include @@ -23,10 +22,7 @@ void AudioServer::on_client_disconnect(int fd) ASSERT(it != m_audio_buffers.end()); if (it->value.buffer != nullptr) - { - const size_t bytes = sizeof(LibAudio::AudioBuffer) + it->value.buffer->capacity * sizeof(LibAudio::AudioBuffer::sample_t); - munmap(it->value.buffer, bytes); - } + shmdt(it->value.buffer); m_audio_buffers.remove(it); @@ -54,9 +50,9 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet) dwarnln("Client tried to map second audio buffer??"); return false; } - audio_buffer.buffer = static_cast(smo_map(packet.parameter)); + audio_buffer.buffer = static_cast(shmat(packet.parameter, nullptr, 0)); audio_buffer.queued_head = audio_buffer.buffer->tail; - if (audio_buffer.buffer == nullptr) + if (audio_buffer.buffer == SHM_FAILED) { dwarnln("Failed to map audio buffer: {}", strerror(errno)); return false; diff --git a/userspace/programs/WindowServer/Window.cpp b/userspace/programs/WindowServer/Window.cpp index 78de89c9..ae4161b1 100644 --- a/userspace/programs/WindowServer/Window.cpp +++ b/userspace/programs/WindowServer/Window.cpp @@ -1,19 +1,16 @@ #include "Window.h" #include -#include #include -#include -#include +#include #include #include Window::~Window() { - munmap(m_fb_addr, client_width() * client_height() * 4); - smo_delete(m_smo_key); + shmdt(m_fb_addr); LibGUI::EventPacket::DestroyWindowEvent packet; @@ -45,16 +42,16 @@ BAN::ErrorOr Window::resize(uint32_t width, uint32_t height) { const size_t fb_bytes = width * height * 4; - long smo_key = smo_create(fb_bytes, PROT_READ | PROT_WRITE); - if (smo_key == -1) + const int shmid = shmget(IPC_PRIVATE, fb_bytes, 0666); + if (shmid == -1) return BAN::Error::from_errno(errno); - BAN::ScopeGuard smo_deleter([&]() { smo_delete(smo_key); }); - uint32_t* fb_addr = static_cast(smo_map(smo_key)); - if (fb_addr == nullptr) + uint32_t* fb_addr = static_cast(shmat(shmid, nullptr, 0)); + shmctl(shmid, IPC_RMID, nullptr); + + if (fb_addr == SHM_FAILED) return BAN::Error::from_errno(errno); memset(fb_addr, 0xFF, fb_bytes); - BAN::ScopeGuard smo_unmapper([&]() { munmap(fb_addr, fb_bytes); }); { const auto old_area = m_client_area; @@ -65,19 +62,17 @@ BAN::ErrorOr Window::resize(uint32_t width, uint32_t height) m_client_area = old_area; if (title_bar_ret.is_error()) + { + shmdt(fb_addr); return title_bar_ret.release_error(); + } } - smo_deleter.disable(); - smo_unmapper.disable(); - - if (m_fb_addr) - munmap(m_fb_addr, client_width() * client_height() * 4); - if (m_smo_key) - smo_delete(m_smo_key); + if (m_fb_addr != nullptr) + shmdt(m_fb_addr); m_fb_addr = fb_addr; - m_smo_key = smo_key; + m_shmid = shmid; m_client_area.max_x = m_client_area.min_x + width; m_client_area.max_y = m_client_area.min_y + height; diff --git a/userspace/programs/WindowServer/Window.h b/userspace/programs/WindowServer/Window.h index 302eca4a..b678c79a 100644 --- a/userspace/programs/WindowServer/Window.h +++ b/userspace/programs/WindowServer/Window.h @@ -42,7 +42,7 @@ public: } int client_fd() const { return m_client_fd; } - long smo_key() const { return m_smo_key; } + int shmid() const { return m_shmid; } int32_t client_x() const { return m_client_area.min_x; } int32_t client_y() const { return m_client_area.min_y; } @@ -113,7 +113,7 @@ private: Rectangle m_client_area { 0, 0, 0, 0 }; Rectangle m_min_size { 0, 0, m_title_bar_height, 0 }; Rectangle m_max_size { 0, 0, 10'000, 10'000 }; - long m_smo_key { 0 }; + int m_shmid { -1 }; uint32_t* m_fb_addr { nullptr }; BAN::String m_title; diff --git a/userspace/programs/WindowServer/WindowServer.cpp b/userspace/programs/WindowServer/WindowServer.cpp index e6b01476..71f994a0 100644 --- a/userspace/programs/WindowServer/WindowServer.cpp +++ b/userspace/programs/WindowServer/WindowServer.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -128,7 +127,7 @@ void WindowServer::on_window_create(int fd, const LibGUI::WindowPacket::WindowCr const LibGUI::EventPacket::ResizeWindowEvent event_packet { .width = static_cast(window->client_width()), .height = static_cast(window->client_height()), - .smo_key = window->smo_key(), + .shmid = window->shmid(), }; if (auto ret = append_serialized_packet(event_packet, fd); ret.is_error()) { @@ -731,7 +730,7 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event) const LibGUI::EventPacket::ResizeWindowEvent event_packet { .width = static_cast(m_focused_window->client_width()), .height = static_cast(m_focused_window->client_height()), - .smo_key = m_focused_window->smo_key(), + .shmid = m_focused_window->shmid(), }; if (auto ret = append_serialized_packet(event_packet, m_focused_window->client_fd()); ret.is_error()) { @@ -1771,7 +1770,7 @@ bool WindowServer::resize_window(BAN::RefPtr window, uint32_t width, uin const LibGUI::EventPacket::ResizeWindowEvent event_packet { .width = static_cast(window->client_width()), .height = static_cast(window->client_height()), - .smo_key = window->smo_key(), + .shmid = window->shmid(), }; if (auto ret = append_serialized_packet(event_packet, window->client_fd()); ret.is_error()) {