shared memory implementation

This commit is contained in:
pigeatgarlic 2026-04-08 15:05:59 +07:00
parent 92a65673d5
commit 0f64a4d794
3 changed files with 107 additions and 13 deletions

View File

@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <initguid.h>
@ -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;
}

View File

@ -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);

View File

@ -4,15 +4,16 @@
*/
// standard includes
#include "smemory.h"
#include <codecvt>
#include <csignal>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include "smemory.h"
#include <sstream>
#include <string_view>
// local includes
#include "audio.h"
#include "config.h"
@ -92,17 +93,19 @@ int main(int argc, char *argv[]) {
mail::man = std::make_shared<safe::mail_raw_t>();
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<bool>(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