From 0f64a4d794f69167b9ffee2ac1d1239eb494d16a Mon Sep 17 00:00:00 2001 From: pigeatgarlic Date: Wed, 8 Apr 2026 15:05:59 +0700 Subject: [PATCH] shared memory implementation --- src/interprocess.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++- src/interprocess.h | 20 +++++++++++++++- src/main.cpp | 43 ++++++++++++++++++++++++--------- 3 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/interprocess.cpp b/src/interprocess.cpp index c4d43915..1a054c20 100644 --- a/src/interprocess.cpp +++ b/src/interprocess.cpp @@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include #include @@ -96,7 +97,7 @@ typedef struct IVSHMEM_EVENT { IVSHMEM *IVSHMEM::m_instance = NULL; -IVSHMEM::IVSHMEM(char *path) +IVSHMEM::IVSHMEM(const char *path) : m_initialized(false), m_handle(INVALID_HANDLE_VALUE), m_gotSize(false), m_gotMemory(false) { memset(m_devPath, 0, 512); memcpy(m_devPath, path, strlen(path)); @@ -205,4 +206,58 @@ void copy_to_packet(MediaPacket *packet, void *data, size_t size) { void copy_to_dpacket(DataPacket *packet, void *data, size_t size) { memcpy(packet->data + packet->size, data, size); packet->size += size; +} + +SharedMemory::SharedMemory(const char *name, size_t size) + : m_size(size), m_handle(NULL), m_memory(NULL), m_initialized(false) { + memset(m_name, 0, 512); + if (name) { + strncpy(m_name, name, 511); + } +} + +SharedMemory::~SharedMemory() { + DeInitialize(); +} + +bool SharedMemory::Initialize() { + if (m_initialized) + DeInitialize(); + + m_handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, m_name); + if (m_handle == NULL) { + BOOST_LOG(error) << "OpenFileMappingA failed for " << m_name << ": " << GetLastError(); + return false; + } + + m_memory = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, m_size); + if (m_memory == NULL) { + BOOST_LOG(error) << "MapViewOfFile failed: " << GetLastError(); + CloseHandle(m_handle); + m_handle = NULL; + return false; + } + + m_initialized = true; + return true; +} + +void SharedMemory::DeInitialize() { + if (m_memory) { + UnmapViewOfFile(m_memory); + m_memory = NULL; + } + if (m_handle) { + CloseHandle(m_handle); + m_handle = NULL; + } + m_initialized = false; +} + +size_t SharedMemory::GetSize() { + return m_size; +} + +void *SharedMemory::GetMemory() { + return m_memory; } \ No newline at end of file diff --git a/src/interprocess.h b/src/interprocess.h index d910c7d8..d7188799 100644 --- a/src/interprocess.h +++ b/src/interprocess.h @@ -25,7 +25,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA class IVSHMEM { public: - IVSHMEM(char *path); + IVSHMEM(const char *path); ~IVSHMEM(); bool Initialize(); @@ -47,6 +47,24 @@ private: bool m_gotMemory; }; +class SharedMemory { +public: + SharedMemory(const char *name, size_t size); + ~SharedMemory(); + + bool Initialize(); + void DeInitialize(); + size_t GetSize(); + void *GetMemory(); + +private: + char m_name[512]; + size_t m_size; + HANDLE m_handle; + void *m_memory; + bool m_initialized; +}; + void copy_to_packet(MediaPacket *packet, void *data, size_t size); void copy_to_dpacket(DataPacket *packet, void *data, size_t size); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 84024091..480f04d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,15 +4,16 @@ */ // standard includes +#include "smemory.h" #include #include #include #include #include -#include "smemory.h" #include #include + // local includes #include "audio.h" #include "config.h" @@ -92,17 +93,19 @@ int main(int argc, char *argv[]) { mail::man = std::make_shared(); MediaMemory *memory = NULL; IVSHMEM *ivshmem = NULL; + SharedMemory *shm = NULL; + + std::string ivshmem_path; + std::string shm_name; + for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if (arg == "--force-sw"sv || arg == "-fsw"sv) { config::sunshine.flags.set(config::flag::FORCE_SOFTWARE_ENCODER); - } else if (!ivshmem) { - ivshmem = new IVSHMEM(argv[i]); - ivshmem->Initialize(); - if (ivshmem->GetSize() >= (UINT64)sizeof(MediaMemory)) { - BOOST_LOG(info) << "Found ivshmem shared memory"sv; - memory = (MediaMemory *)ivshmem->GetMemory(); - } + } else if (arg == "--ivshmem"sv && i + 1 < argc) { + ivshmem_path = argv[++i]; + } else if (arg == "--shm"sv && i + 1 < argc) { + shm_name = argv[++i]; } } @@ -111,27 +114,45 @@ int main(int argc, char *argv[]) { BOOST_LOG(error) << "Logging failed to initialize"sv; } + if (!ivshmem_path.empty()) { + ivshmem = new IVSHMEM(ivshmem_path.c_str()); + if (ivshmem->Initialize() && ivshmem->GetSize() >= sizeof(MediaMemory)) { + BOOST_LOG(info) << "Found ivshmem shared memory"sv; + memory = (MediaMemory *)ivshmem->GetMemory(); + } + } else if (!shm_name.empty()) { + shm = new SharedMemory(shm_name.c_str(), sizeof(MediaMemory)); + if (shm->Initialize()) { + BOOST_LOG(info) << "Found named shared memory: " << shm_name; + memory = (MediaMemory *)shm->GetMemory(); + } + } + if (memory == NULL) { - BOOST_LOG(info) << "ivshmem shared memory not available, using mockup memory block"sv; + BOOST_LOG(info) << "IPC shared memory not available, using mockup memory block"sv; memory = (MediaMemory *)calloc(1, sizeof(MediaMemory)); } // Create signal handler after logging has been initialized auto process_shutdown_event = mail::man->event(mail::shutdown); - on_signal(SIGINT, [process_shutdown_event, ivshmem]() { + on_signal(SIGINT, [process_shutdown_event, ivshmem, shm]() { BOOST_LOG(info) << "Interrupt handler called"sv; logging::log_flush(); process_shutdown_event->raise(true); if (ivshmem) ivshmem->DeInitialize(); + if (shm) + shm->DeInitialize(); }); - on_signal(SIGTERM, [process_shutdown_event, ivshmem]() { + on_signal(SIGTERM, [process_shutdown_event, ivshmem, shm]() { BOOST_LOG(info) << "Terminate handler called"sv; logging::log_flush(); process_shutdown_event->raise(true); if (ivshmem) ivshmem->DeInitialize(); + if (shm) + shm->DeInitialize(); }); // Wait as long as possible to terminate Sunshine.exe during logoff/shutdown