AuroraRuntime/Source/IO/IPC/AuIPCMemory.Unix.cpp
J Reece Wilson 766be57a46 [+] Linux build [again]
[+] ProcessSectionViewReserved.Unix.cpp
[*] Fix missing ::Flush() member on ViewWriter
2022-12-16 00:41:01 +00:00

176 lines
4.5 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIPCMemory.Unix.cpp
Date: 2022-4-14
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "IPC.hpp"
#include "AuIPCHandle.hpp"
#include "AuIPCMemory.Unix.hpp"
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#if defined(AURORA_IS_LINUX_DERIVED)
#include "AuIPCMutexFutex.Linux.hpp" /* For import */
#endif
namespace Aurora::IO::IPC
{
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Shared memory
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
AuString GetServerPath(const IPC::IPCToken &handle)
{
AuString path;
path += "/AURORA_";
path += AuToString(AuUInt32(handle.cookie));
path += "_";
path += AuToString(AuUInt32(handle.pid));
return path;
}
IPCSharedMemoryImpl::IPCSharedMemoryImpl(int fd,
void *pBase,
const IPC::IPCHandle &handle,
bool bOwns) :
fd_(fd),
pBase_(pBase),
uLen_(handle.values[0].token.word),
bOwns_(bOwns),
handle_(handle)
{
}
IPCSharedMemoryImpl::~IPCSharedMemoryImpl()
{
if (this->pBase_)
{
::munmap(this->pBase_, this->uLen_);
}
int fd {-1};
if ((fd = AuExchange(this->fd_, -1)) != -1)
{
::close(fd);
}
}
Memory::MemoryViewWrite IPCSharedMemoryImpl::GetMemory()
{
return AuMemoryViewWrite(this->pBase_, this->uLen_);
}
AuUInt IPCSharedMemoryImpl::GetLength()
{
return this->uLen_;
}
AuString IPCSharedMemoryImpl::ExportToString()
{
return this->handle_.ToString();
}
AUKN_SYM AuSPtr<IPCSharedMemory> NewSharedMemory(AuUInt uLength)
{
IPC::IPCHandle handle;
IPC::IPCToken token;
token.pid = handle.pid;
token.word = uLength;
token.NewId();
handle.PushId(EIPCHandleType::eIPCMemory, token);
auto path = GetServerPath(token);
int fd = ::shm_open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
{
SysPushErrorIO();
return {};
}
if (::ftruncate(fd, uLength) == -1)
{
SysPushErrorMem();
::close(fd);
return {};
}
auto map = ::mmap(nullptr, uLength, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
{
SysPushErrorIO();
::close(fd);
return {};
}
auto pObject = AuMakeShared<IPCSharedMemoryImpl>(fd, map, handle, true);
if (!pObject)
{
SysPushErrorMem();
::munmap(map, uLength);
::close(fd);
return {};
}
return pObject;
}
AuSPtr<IPCSharedMemory> ImportSharedMemoryEx(const IPCToken &token)
{
auto path = GetServerPath(token);
int fd = ::shm_open(path.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1)
{
SysPushErrorIO();
return {};
}
auto map = ::mmap(nullptr, token.word, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
{
SysPushErrorIO();
::close(fd);
return {};
}
IPC::IPCHandle handle;
handle.PushId(EIPCHandleType::eIPCMemory, token);
auto pObject = AuMakeShared<IPCSharedMemoryImpl>(fd, map, handle, false);
if (!pObject)
{
SysPushErrorMem();
::munmap(map, token.word);
::close(fd);
return {};
}
return pObject;
}
AUKN_SYM AuSPtr<IPCSharedMemory> ImportSharedMemory(const AuString &handleString)
{
IPC::IPCHandle handle;
if (!handle.FromString(handleString))
{
SysPushErrorParseError("Invalid handle: {}", handleString);
return {};
}
auto val = handle.GetToken(IPC::EIPCHandleType::eIPCMemory, 0);
if (!val)
{
SysPushErrorParseError("Invalid handle: {}", handleString);
return {};
}
return ImportSharedMemoryEx(val->token);
}
}