From d5d21e1eb0579662df45420b5227bcba9d622796 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 29 Aug 2023 16:25:30 +0200 Subject: [PATCH] libui+wind+libos: Move shared memory handling code to os::SharedMemory --- libos/CMakeLists.txt | 1 + libos/include/os/SharedMemory.h | 36 +++++++++++++++ libos/src/SharedMemory.cpp | 77 +++++++++++++++++++++++++++++++++ libui/src/Window.cpp | 31 +++---------- wind/IPC.cpp | 51 +++------------------- 5 files changed, 124 insertions(+), 72 deletions(-) create mode 100644 libos/include/os/SharedMemory.h create mode 100644 libos/src/SharedMemory.cpp diff --git a/libos/CMakeLists.txt b/libos/CMakeLists.txt index 76bbe50d..321f4b4c 100644 --- a/libos/CMakeLists.txt +++ b/libos/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES src/LocalServer.cpp src/LocalClient.cpp src/IPC.cpp + src/SharedMemory.cpp ) add_library(os ${SOURCES}) diff --git a/libos/include/os/SharedMemory.h b/libos/include/os/SharedMemory.h new file mode 100644 index 00000000..c1a9985c --- /dev/null +++ b/libos/include/os/SharedMemory.h @@ -0,0 +1,36 @@ +/** + * @file SharedMemory.h + * @author apio (cloudapio.eu) + * @brief Create and map areas of memory shared between processes. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#include +#include + +namespace os +{ + namespace SharedMemory + { + /** + * @brief Create a new shared memory region and map it. + * + * @param path The shared memory path to use. It must be of the same format as shm_open(). + * @param size The amount of bytes to use for the shared memory region. + * @return Result An error, or a pointer to the shared memory region. + */ + Result create(StringView path, usize size); + + /** + * @brief Map an existing shared memory region, possibly created by another process. + * + * @param path The shared memory path to use. It must be of the same format as shm_open(). + * @param size The amount of bytes to map from the shared memory region. + * @param delete_fs Whether to delete the region from the file system so no other processes can open it. + * @return Result An error, or a pointer to the shared memory region. + */ + Result adopt(StringView path, usize size, bool delete_fs = true); + }; +} diff --git a/libos/src/SharedMemory.cpp b/libos/src/SharedMemory.cpp new file mode 100644 index 00000000..743567f7 --- /dev/null +++ b/libos/src/SharedMemory.cpp @@ -0,0 +1,77 @@ +/** + * @file SharedMemory.cpp + * @author apio (cloudapio.eu) + * @brief Create and map areas of memory shared between processes. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace os::SharedMemory +{ + Result create(StringView path, usize size) + { + int fd = shm_open(path.chars(), O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd < 0) + { + int olderr = errno; + os::eprintln("os: could not create shared memory region: shm_open failed (%s) - %s", path, + strerror(olderr)); + return err(olderr); + } + + size = align_up(size); + + if (ftruncate(fd, size) < 0) + { + int olderr = errno; + os::eprintln("os: could not create shared memory region: ftruncate failed (%d, %zu) - %s", fd, size, + strerror(olderr)); + shm_unlink(path.chars()); + close(fd); + return err(olderr); + } + + void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) + { + int olderr = errno; + os::eprintln("os: could not create shared memory region: mmap failed (%zu, %d) - %s", size, fd, + strerror(olderr)); + shm_unlink(path.chars()); + close(fd); + return err(olderr); + } + + close(fd); + return (u8*)p; + } + + Result adopt(StringView path, usize size, bool delete_fs) + { + int fd = shm_open(path.chars(), O_RDWR, 0600); + if (delete_fs) shm_unlink(path.chars()); + if (fd < 0) return err(errno); + + void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) + { + int olderr = errno; + os::eprintln("os: could not adopt shared memory region: mmap failed (%zu, %d) - %s", size, fd, + strerror(olderr)); + close(fd); + return 0; + } + + close(fd); + return (u8*)p; + } +} diff --git a/libui/src/Window.cpp b/libui/src/Window.cpp index 29b197e9..8c64b7ca 100644 --- a/libui/src/Window.cpp +++ b/libui/src/Window.cpp @@ -7,35 +7,12 @@ * */ -#include -#include +#include +#include #include #include #include #include -#include - -static Result create_shm_region(const char* path, int* outfd, ui::Rect rect) -{ - int fd = shm_open(path, O_RDWR, 0600); - shm_unlink(path); - if (fd < 0) return err(errno); - - usize size = rect.width * rect.height * 4; // 4 bytes per pixel - - void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) - { - shm_unlink(path); - close(fd); - return 0; - } - - if (outfd) *outfd = fd; - else - close(fd); - return (u32*)p; -} namespace ui { @@ -48,7 +25,9 @@ namespace ui request.decorated = decorated; auto response = TRY(os::IPC::send_sync(App::the().client(), request)); - u32* pixels = TRY(create_shm_region(response.shm_path, nullptr, rect)); + auto path = COPY_IPC_STRING(response.shm_path); + + u32* pixels = (u32*)TRY(os::SharedMemory::adopt(path.view(), rect.height * rect.width * 4)); window->m_canvas = ui::Canvas { rect.width, rect.height, rect.width, (u8*)pixels }; window->m_id = response.window; diff --git a/wind/IPC.cpp b/wind/IPC.cpp index d3ba6475..50eb986e 100644 --- a/wind/IPC.cpp +++ b/wind/IPC.cpp @@ -1,13 +1,10 @@ #include "IPC.h" #include "Screen.h" -#include #include #include #include -#include -#include +#include #include -#include #define TRY_OR_IPC_ERROR(expr) \ ({ \ @@ -21,45 +18,6 @@ _expr_rc.release_value(); \ }) -static Result create_shm_region(const char* path, int* outfd, ui::Rect rect) -{ - int fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd < 0) - { - int olderr = errno; - os::eprintln("wind: could not create shared memory region: shm_open failed (%s) - %s", path, strerror(olderr)); - return err(olderr); - } - - usize size = align_up(rect.width * rect.height * 4); // 4 bytes per pixel - - if (ftruncate(fd, size) < 0) - { - int olderr = errno; - os::eprintln("wind: could not create shared memory region: ftruncate failed (%d, %zu) - %s", fd, size, - strerror(olderr)); - shm_unlink(path); - close(fd); - return err(olderr); - } - - void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) - { - int olderr = errno; - os::eprintln("wind: could not create shared memory region: mmap failed (%zu, %d) - %s", size, fd, - strerror(olderr)); - shm_unlink(path); - close(fd); - return err(olderr); - } - - if (outfd) *outfd = fd; - else - close(fd); - return (u32*)p; -} - #define READ_MESSAGE(request) \ do { \ auto rc = client.conn.recv_typed(request); \ @@ -96,8 +54,6 @@ static Result handle_create_window_message(Client& client) ui::CreateWindowRequest request; READ_MESSAGE(request); - request.rect = request.rect.normalized(); - if (request.decorated) { request.rect.height += @@ -105,6 +61,8 @@ static Result handle_create_window_message(Client& client) request.rect.pos.y -= Window::titlebar_height(); // Adjust it so the contents begin at the expected coordinates. } + request.rect = request.rect.normalized(); + auto name = TRY(String::from_cstring("Window")); auto* window = new (std::nothrow) Window(request.rect, move(name), request.decorated); @@ -116,7 +74,8 @@ static Result handle_create_window_message(Client& client) auto shm_path = TRY_OR_IPC_ERROR(String::format("/wind-shm-%d-%lu"_sv, client.conn.fd(), time(NULL))); - window->pixels = TRY_OR_IPC_ERROR(create_shm_region(shm_path.chars(), nullptr, window->contents)); + window->pixels = (u32*)TRY_OR_IPC_ERROR( + os::SharedMemory::create(shm_path.view(), window->contents.height * window->contents.width * 4)); TRY_OR_IPC_ERROR(client.windows.try_append(window)); int id = static_cast(client.windows.size() - 1);