libui+wind+libos: Move shared memory handling code to os::SharedMemory
All checks were successful
continuous-integration/drone/pr Build is passing

This commit is contained in:
apio 2023-08-29 16:25:30 +02:00
parent e85dc97e91
commit d5d21e1eb0
Signed by: apio
GPG Key ID: B8A7D06E42258954
5 changed files with 124 additions and 72 deletions

View File

@ -17,6 +17,7 @@ set(SOURCES
src/LocalServer.cpp src/LocalServer.cpp
src/LocalClient.cpp src/LocalClient.cpp
src/IPC.cpp src/IPC.cpp
src/SharedMemory.cpp
) )
add_library(os ${SOURCES}) add_library(os ${SOURCES})

View File

@ -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 <luna/Result.h>
#include <luna/StringView.h>
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<u8*> An error, or a pointer to the shared memory region.
*/
Result<u8*> 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<u8*> An error, or a pointer to the shared memory region.
*/
Result<u8*> adopt(StringView path, usize size, bool delete_fs = true);
};
}

View File

@ -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 <errno.h>
#include <luna/Alignment.h>
#include <os/File.h>
#include <os/SharedMemory.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
namespace os::SharedMemory
{
Result<u8*> 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<PAGE_SIZE>(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<u8*> 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;
}
}

View File

@ -7,35 +7,12 @@
* *
*/ */
#include <errno.h> #include <luna/String.h>
#include <fcntl.h> #include <os/SharedMemory.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <ui/App.h> #include <ui/App.h>
#include <ui/Window.h> #include <ui/Window.h>
#include <ui/ipc/Server.h> #include <ui/ipc/Server.h>
#include <unistd.h>
static Result<u32*> 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 namespace ui
{ {
@ -48,7 +25,9 @@ namespace ui
request.decorated = decorated; request.decorated = decorated;
auto response = TRY(os::IPC::send_sync<ui::CreateWindowResponse>(App::the().client(), request)); auto response = TRY(os::IPC::send_sync<ui::CreateWindowResponse>(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_canvas = ui::Canvas { rect.width, rect.height, rect.width, (u8*)pixels };
window->m_id = response.window; window->m_id = response.window;

View File

@ -1,13 +1,10 @@
#include "IPC.h" #include "IPC.h"
#include "Screen.h" #include "Screen.h"
#include <errno.h>
#include <luna/Alignment.h> #include <luna/Alignment.h>
#include <luna/String.h> #include <luna/String.h>
#include <os/File.h> #include <os/File.h>
#include <string.h> #include <os/SharedMemory.h>
#include <sys/mman.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#define TRY_OR_IPC_ERROR(expr) \ #define TRY_OR_IPC_ERROR(expr) \
({ \ ({ \
@ -21,45 +18,6 @@
_expr_rc.release_value(); \ _expr_rc.release_value(); \
}) })
static Result<u32*> 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<PAGE_SIZE>(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) \ #define READ_MESSAGE(request) \
do { \ do { \
auto rc = client.conn.recv_typed(request); \ auto rc = client.conn.recv_typed(request); \
@ -96,8 +54,6 @@ static Result<void> handle_create_window_message(Client& client)
ui::CreateWindowRequest request; ui::CreateWindowRequest request;
READ_MESSAGE(request); READ_MESSAGE(request);
request.rect = request.rect.normalized();
if (request.decorated) if (request.decorated)
{ {
request.rect.height += request.rect.height +=
@ -105,6 +61,8 @@ static Result<void> 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.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 name = TRY(String::from_cstring("Window"));
auto* window = new (std::nothrow) Window(request.rect, move(name), request.decorated); auto* window = new (std::nothrow) Window(request.rect, move(name), request.decorated);
@ -116,7 +74,8 @@ static Result<void> 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))); 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)); TRY_OR_IPC_ERROR(client.windows.try_append(window));
int id = static_cast<int>(client.windows.size() - 1); int id = static_cast<int>(client.windows.size() - 1);