Further Linux support
[+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
This commit is contained in:
parent
b8bcab1bdc
commit
fd0c5b51b2
84
Aurora.json
84
Aurora.json
@ -1,21 +1,89 @@
|
|||||||
{
|
{
|
||||||
"type": "aurora",
|
"type": "aurora",
|
||||||
"name": "AuroraRuntime",
|
"name": "AuroraRuntime",
|
||||||
"dllexport": ["AURORA_ENGINE_KERNEL_EXPORT"],
|
"dllexport": [
|
||||||
|
"AURORA_ENGINE_KERNEL_EXPORT"
|
||||||
|
],
|
||||||
"dllimport": [],
|
"dllimport": [],
|
||||||
"impDefines": ["AURORA_ENGINE_KERNEL"],
|
"impDefines": [
|
||||||
|
"AURORA_ENGINE_KERNEL"
|
||||||
|
],
|
||||||
"staticImpDefines": "AURORA_ENGINE_KERNEL_STATIC",
|
"staticImpDefines": "AURORA_ENGINE_KERNEL_STATIC",
|
||||||
|
"clangIgnore": [
|
||||||
|
"deprecated-declarations",
|
||||||
|
"c99-designator",
|
||||||
|
"reorder-init-list",
|
||||||
|
"ignored-attributes"
|
||||||
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"soft-depends": ["wxwidgets", "glm", "bzip2", "lz4"],
|
"soft-depends": [
|
||||||
"depends": ["auROXTL", "AuroraInterfaces", "AuroraEnum", "mimalloc", "uuid", "fmt", "json", "ltc", "o1heap", "zstd", "zlib", "mbedtls"],
|
"wxwidgets",
|
||||||
"include-depends": ["fmt", "uuid", "AuroraInterfaces", "AuroraEnum", "auROXTL"],
|
"glm",
|
||||||
"features": ["guess-platform-code"],
|
"bzip2",
|
||||||
|
"lz4"
|
||||||
|
],
|
||||||
|
"depends": [
|
||||||
|
"auROXTL",
|
||||||
|
"AuroraInterfaces",
|
||||||
|
"AuroraEnum",
|
||||||
|
"mimalloc",
|
||||||
|
"uuid",
|
||||||
|
"fmt",
|
||||||
|
"json",
|
||||||
|
"ltc",
|
||||||
|
"o1heap",
|
||||||
|
"zstd",
|
||||||
|
"zlib",
|
||||||
|
"mbedtls"
|
||||||
|
],
|
||||||
|
"include-depends": [
|
||||||
|
"fmt",
|
||||||
|
"uuid",
|
||||||
|
"AuroraInterfaces",
|
||||||
|
"AuroraEnum",
|
||||||
|
"auROXTL"
|
||||||
|
],
|
||||||
|
"features": [
|
||||||
|
"guess-platform-code"
|
||||||
|
],
|
||||||
"linkSources": "Source/Alloc.cpp",
|
"linkSources": "Source/Alloc.cpp",
|
||||||
"actions": [
|
"actions": [
|
||||||
{
|
{
|
||||||
"filter": {"platforms": "win32"},
|
"filter": {
|
||||||
|
"platforms": "win32"
|
||||||
|
},
|
||||||
"then": {
|
"then": {
|
||||||
"links": ["Bcrypt.lib", "UxTheme.lib", "Aux_ulib.lib", "Dbghelp.lib", "ws2_32.lib", "Ntdll.lib", "Wer.lib", "wintrust.lib"]
|
"links": [
|
||||||
|
"Bcrypt.lib",
|
||||||
|
"UxTheme.lib",
|
||||||
|
"Aux_ulib.lib",
|
||||||
|
"Dbghelp.lib",
|
||||||
|
"ws2_32.lib",
|
||||||
|
"Ntdll.lib",
|
||||||
|
"Wer.lib",
|
||||||
|
"wintrust.lib"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filter": {
|
||||||
|
"platforms": "linux"
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"links": [
|
||||||
|
"unwind",
|
||||||
|
"unwind-generic"
|
||||||
|
],
|
||||||
|
"actions": {
|
||||||
|
"filter": {
|
||||||
|
"archs": "x86_64"
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"links": [
|
||||||
|
"unwind-x86_64"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
#include "IThreadPool.hpp"
|
#include "IThreadPool.hpp"
|
||||||
#include "IAsyncApp.hpp"
|
#include "IAsyncApp.hpp"
|
||||||
|
|
||||||
#include "Jobs.hpp"
|
#include "Legacy/Jobs.hpp"
|
||||||
#include "Tasks.hpp"
|
#include "Legacy/Tasks.hpp"
|
||||||
|
|
||||||
namespace Aurora::Async
|
namespace Aurora::Async
|
||||||
{
|
{
|
||||||
@ -43,9 +43,9 @@ namespace Aurora::Async
|
|||||||
#if !defined(_CPPSHARP)
|
#if !defined(_CPPSHARP)
|
||||||
#include "IPCPromises.hpp"
|
#include "IPCPromises.hpp"
|
||||||
|
|
||||||
#include "JobFrom.hpp"
|
#include "Legacy/JobFrom.hpp"
|
||||||
#include "TaskFrom.hpp"
|
#include "Legacy/TaskFrom.hpp"
|
||||||
#include "WorkPairImpl.hpp"
|
#include "Legacy/WorkPairImpl.hpp"
|
||||||
#include "WorkBasic.hpp"
|
#include "Legacy/WorkBasic.hpp"
|
||||||
#include "OldTrash.hpp"
|
#include "Legacy/OldTrash.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -165,9 +165,9 @@ namespace Aurora::Async
|
|||||||
using FunctionalCall_t = PromiseCallTmpl<SuccessValue_t, ErrorValue_t>;
|
using FunctionalCall_t = PromiseCallTmpl<SuccessValue_t, ErrorValue_t>;
|
||||||
using FunctionalResponse_t = PromiseSuccessTmpl<SuccessValue_t>;
|
using FunctionalResponse_t = PromiseSuccessTmpl<SuccessValue_t>;
|
||||||
using FunctionalFail_t = PromiseFailTmpl<ErrorValue_t>;
|
using FunctionalFail_t = PromiseFailTmpl<ErrorValue_t>;
|
||||||
using FunctionalResponse_f = FunctionalResponse_t::OnSuccess_f;
|
using FunctionalResponse_f = typename FunctionalResponse_t::OnSuccess_f;
|
||||||
using FunctionalFail_f = FunctionalFail_t::OnFailure_f;
|
using FunctionalFail_f = typename FunctionalFail_t::OnFailure_f;
|
||||||
using FunctionalDelegate_f = FunctionalCall_t::OnDelegate_f;
|
using FunctionalDelegate_f = typename FunctionalCall_t::OnDelegate_f;
|
||||||
|
|
||||||
inline AuSPtr<This_t> OnSuccessFunctional(const FunctionalResponse_f &in);
|
inline AuSPtr<This_t> OnSuccessFunctional(const FunctionalResponse_f &in);
|
||||||
inline AuSPtr<This_t> OnSuccessCallback(const AuSPtr<IPromiseComplete> &in);
|
inline AuSPtr<This_t> OnSuccessCallback(const AuSPtr<IPromiseComplete> &in);
|
||||||
|
5
Include/Aurora/Async/Legacy/DO NOT REMOVE.txt
Executable file
5
Include/Aurora/Async/Legacy/DO NOT REMOVE.txt
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
> Deprecated APIs <
|
||||||
|
|
||||||
|
* Wont remove
|
||||||
|
* Powering old projects
|
||||||
|
* Sometimes used as shorthands internally
|
@ -9,5 +9,18 @@
|
|||||||
|
|
||||||
namespace Aurora::Console::ConsoleTTY
|
namespace Aurora::Console::ConsoleTTY
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Is in the middle of buffering all stdout writes?
|
||||||
|
*/
|
||||||
|
AUKN_SYM bool IsBuffering();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Begin stdout buffering
|
||||||
|
*/
|
||||||
|
AUKN_SYM void BeginBuffering();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flip framebuffer
|
||||||
|
*/
|
||||||
|
AUKN_SYM bool EndBuffering();
|
||||||
}
|
}
|
@ -45,7 +45,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
@ -33,7 +33,7 @@ namespace Aurora::Compression
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
size_t ret;
|
size_t ret;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace Aurora::Compression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init(const AuSPtr<IO::IStreamReader> &reader)
|
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
|
||||||
{
|
{
|
||||||
this->reader_ = reader;
|
this->reader_ = reader;
|
||||||
this->dctx_ = ZSTD_createDCtx();
|
this->dctx_ = ZSTD_createDCtx();
|
||||||
|
@ -104,6 +104,7 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
//static AuThreadPrimitives::MutexUnique_t gRingLock = AuThreadPrimitives::MutexUnique();
|
//static AuThreadPrimitives::MutexUnique_t gRingLock = AuThreadPrimitives::MutexUnique();
|
||||||
static AuThreadPrimitives::SpinLock gRingLock;// = AuThreadPrimitives::MutexUnique();
|
static AuThreadPrimitives::SpinLock gRingLock;// = AuThreadPrimitives::MutexUnique();
|
||||||
|
static bool gBufferMode {};
|
||||||
|
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
|
|
||||||
@ -371,6 +372,7 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
bool EnterNoncanonicalMode()
|
bool EnterNoncanonicalMode()
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaveNoncanonicalMode()
|
void LeaveNoncanonicalMode()
|
||||||
@ -399,7 +401,7 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
return dwType == FILE_TYPE_CHAR;
|
return dwType == FILE_TYPE_CHAR;
|
||||||
#else
|
#else
|
||||||
return IsStdOutTTY(stdout);
|
return IsStdOutTTY(STDOUT_FILENO);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,6 +639,11 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
static AuUInt32 WriteStdOutBlocking(const void *data, AuUInt32 length)
|
static AuUInt32 WriteStdOutBlocking(const void *data, AuUInt32 length)
|
||||||
{
|
{
|
||||||
|
if (gBufferMode)
|
||||||
|
{
|
||||||
|
return gStdoutBuffer.Write(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
if (!IS_STREAM_HANDLE_VALID(gOutputStream))
|
if (!IS_STREAM_HANDLE_VALID(gOutputStream))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -666,6 +673,11 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
void FlushStdOutNb()
|
void FlushStdOutNb()
|
||||||
{
|
{
|
||||||
|
if (gBufferMode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AuUInt32 written {};
|
AuUInt32 written {};
|
||||||
written = WriteStdOutBlocking(gStdoutBuffer.begin(), gStdoutBuffer.size());
|
written = WriteStdOutBlocking(gStdoutBuffer.begin(), gStdoutBuffer.size());
|
||||||
gStdoutBuffer.clear();
|
gStdoutBuffer.clear();
|
||||||
@ -685,21 +697,20 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
{
|
{
|
||||||
AU_LOCK_GUARD(gRingLock);
|
AU_LOCK_GUARD(gRingLock);
|
||||||
|
|
||||||
FlushStdOutNb();
|
|
||||||
|
|
||||||
return WriteStdOutBlocking(data, length);
|
return WriteStdOutBlocking(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lock()
|
void Lock()
|
||||||
{
|
{
|
||||||
gRingLock.Lock();
|
AU_LOCK_GUARD(gRingLock);
|
||||||
|
gBufferMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unlock()
|
void Unlock()
|
||||||
{
|
{
|
||||||
|
AU_LOCK_GUARD(gRingLock);
|
||||||
|
gBufferMode = false;
|
||||||
FlushStdOutNb();
|
FlushStdOutNb();
|
||||||
|
|
||||||
gRingLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AuUInt32 WriteStdOutNonBlocking(const void *data, AuUInt32 length)
|
AuUInt32 WriteStdOutNonBlocking(const void *data, AuUInt32 length)
|
||||||
|
@ -21,16 +21,12 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
void Lock();
|
void Lock();
|
||||||
void Unlock();
|
void Unlock();
|
||||||
AuUInt32 WriteStdOutNonBlocking(const void *data, AuUInt32 length);
|
|
||||||
void FlushStdOutNb();
|
|
||||||
|
|
||||||
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
||||||
AuUInt32 WriteStdOut(const void *data, AuUInt32 length);
|
AuUInt32 WriteStdOut(const void *data, AuUInt32 length);
|
||||||
|
|
||||||
void WriteStdOut(AuUInt8 level, const ConsoleMessage &msg);
|
void WriteStdOut(AuUInt8 level, const ConsoleMessage &msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
void ProcessCanonical(HANDLE h);
|
void ProcessCanonical(HANDLE h);
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,14 +24,12 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
|
|
||||||
void BeginBuffering()
|
void BeginBuffering()
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
ConsoleStd::Lock();
|
ConsoleStd::Lock();
|
||||||
gIsBuffering = true;
|
gIsBuffering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EndBuffering()
|
bool EndBuffering()
|
||||||
{
|
{
|
||||||
return true;
|
|
||||||
ConsoleStd::Unlock();
|
ConsoleStd::Unlock();
|
||||||
gIsBuffering = false;
|
gIsBuffering = false;
|
||||||
//TODO (Reece): Was signal handler called?
|
//TODO (Reece): Was signal handler called?
|
||||||
@ -45,9 +43,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto written = gIsBuffering ? ConsoleStd::WriteStdOutNonBlocking(in.data(), in.size())
|
auto written = ConsoleStd::WriteStdOutBlocking2(in.data(), in.size());
|
||||||
: ConsoleStd::WriteStdOutBlocking2(in.data(), in.size());
|
|
||||||
|
|
||||||
SysAssert(written == in.size(), "TTY Buffer Full");
|
SysAssert(written == in.size(), "TTY Buffer Full");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +100,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gIsBuffering ? ConsoleStd::WriteStdOutNonBlocking(buffer, length)
|
return ConsoleStd::WriteStdOutBlocking2(buffer, length);
|
||||||
: ConsoleStd::WriteStdOutBlocking2(buffer, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM void TTYWrite(const char *string, EAnsiColor fgColor, EAnsiColor bgColor)
|
AUKN_SYM void TTYWrite(const char *string, EAnsiColor fgColor, EAnsiColor bgColor)
|
||||||
@ -174,16 +169,9 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ForceFlush()
|
static void ForceFlush()
|
||||||
{
|
|
||||||
if (gIsBuffering)
|
|
||||||
{
|
|
||||||
ConsoleStd::FlushStdOutNb();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ConsoleStd::Flush();
|
ConsoleStd::Flush();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AUKN_SYM void TTYStorePos()
|
AUKN_SYM void TTYStorePos()
|
||||||
{
|
{
|
||||||
|
@ -1034,7 +1034,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
void TTYConsole::BlankLine(int Y, bool borders)
|
void TTYConsole::BlankLine(int Y, bool borders)
|
||||||
{
|
{
|
||||||
TTYSetPos({0, Y});
|
TTYSetPos({0, Y});
|
||||||
TTYClearLine();
|
TTYClearLine(EAnsiColor::eReset);
|
||||||
BlankBordersLine(Y);
|
BlankBordersLine(Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
|
|
||||||
struct TTYConsole : ITTYConsole
|
struct TTYConsole : ITTYConsole
|
||||||
{
|
{
|
||||||
void BufferMessage(const AuConsole::ConsoleMessage &msg);
|
void BufferMessage(const AuConsole::ConsoleMessage &msg) override;
|
||||||
void Pump();
|
void Pump();
|
||||||
void PumpHistory();
|
void PumpHistory();
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
|
|
||||||
bool RegenerateBuffer(bool resChanged, bool &redrawBox);
|
bool RegenerateBuffer(bool resChanged, bool &redrawBox);
|
||||||
|
|
||||||
bool NoncanonicalMode();
|
bool NoncanonicalMode() override;
|
||||||
void NoncanonicalTick();
|
void NoncanonicalTick();
|
||||||
void NoncanonicalSetCursor();
|
void NoncanonicalSetCursor();
|
||||||
void NoncanonicalOnString(const AuString &input);
|
void NoncanonicalOnString(const AuString &input);
|
||||||
@ -194,7 +194,7 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
struct AlignedString
|
struct AlignedString
|
||||||
{
|
{
|
||||||
AuString str;
|
AuString str;
|
||||||
ETTYAlign align;
|
ETTYAlign align {};
|
||||||
};
|
};
|
||||||
|
|
||||||
AuString tempMemory;
|
AuString tempMemory;
|
||||||
@ -216,8 +216,8 @@ namespace Aurora::Console::ConsoleTTY
|
|||||||
bool bLeftBorder {true};
|
bool bLeftBorder {true};
|
||||||
bool bTopBorder {true};
|
bool bTopBorder {true};
|
||||||
|
|
||||||
bool bShouldShowBorders;
|
bool bShouldShowBorders {};
|
||||||
bool bShowingBorders;
|
bool bShowingBorders {};
|
||||||
|
|
||||||
|
|
||||||
bool IsShowingHintLine();
|
bool IsShowingHintLine();
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#include "Stack.Win32.hpp"
|
#include "Stack.Win32.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
|
#include "Stack.Unix.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Aurora::Debug
|
namespace Aurora::Debug
|
||||||
{
|
{
|
||||||
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
|
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
|
||||||
@ -208,7 +212,7 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
AUKN_SYM StackTrace GetStackTrace()
|
AUKN_SYM StackTrace GetStackTrace()
|
||||||
{
|
{
|
||||||
#if defined(AURORA_PLATFORM_WIN32)
|
#if defined(AURORA_PLATFORM_WIN32) || defined(AURORA_IS_LINUX_DERIVED)
|
||||||
return PlatformWalkCallStack();
|
return PlatformWalkCallStack();
|
||||||
#else
|
#else
|
||||||
return {};
|
return {};
|
||||||
|
@ -14,4 +14,10 @@ namespace Aurora::Debug
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InitUNIX()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,3 +5,121 @@
|
|||||||
Date: 2022-1-26
|
Date: 2022-1-26
|
||||||
Author: Reece
|
Author: Reece
|
||||||
***/
|
***/
|
||||||
|
#include <Source/RuntimeInternal.hpp>
|
||||||
|
#include "Stack.hpp"
|
||||||
|
#include "Stack.Unix.hpp"
|
||||||
|
#include <libunwind.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
namespace Aurora::Debug
|
||||||
|
{
|
||||||
|
static void TryComplete(StackTraceEntry &entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static StackTrace DumpContext(unw_context_t *uc)
|
||||||
|
{
|
||||||
|
StackTrace ret;
|
||||||
|
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_word_t ip;
|
||||||
|
|
||||||
|
::unw_init_local(&cursor, uc);
|
||||||
|
|
||||||
|
while (::unw_step(&cursor) > 0)
|
||||||
|
{
|
||||||
|
StackTraceEntry entry;
|
||||||
|
|
||||||
|
::unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||||
|
|
||||||
|
// module
|
||||||
|
{
|
||||||
|
unw_word_t off;
|
||||||
|
char procName[512];
|
||||||
|
|
||||||
|
if (unw_get_proc_name(&cursor, procName, AuArraySize(procName), &off) == 0)
|
||||||
|
{
|
||||||
|
AuString str;
|
||||||
|
str = AuString(procName, strlen(procName));
|
||||||
|
str += fmt::format("+0x{:x}", off);
|
||||||
|
entry.label = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Dl_info dlinfo;
|
||||||
|
AuSInt originalIP {};
|
||||||
|
AuUInt moduleAddress {};
|
||||||
|
|
||||||
|
const char *dllPathName {};
|
||||||
|
|
||||||
|
if (::dladdr((const void *)ip, &dlinfo))
|
||||||
|
{
|
||||||
|
dllPathName = dlinfo.dli_fname;
|
||||||
|
moduleAddress = (AuUInt)dlinfo.dli_fbase;
|
||||||
|
originalIP = (AuUInt)ip - moduleAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.address = ip;
|
||||||
|
entry.relAddress = originalIP;
|
||||||
|
|
||||||
|
if (dllPathName)
|
||||||
|
{
|
||||||
|
entry.module = dllPathName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuTryInsert(ret, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace DumpContextPlatform(ucontext_t &uc)
|
||||||
|
{
|
||||||
|
// VALID:
|
||||||
|
// Linux: https://github.com/libunwind/libunwind/blob/3be832395426b72248969247a4a66e3c3623578d/include/libunwind-x86.h#L170
|
||||||
|
|
||||||
|
// ???
|
||||||
|
// MACOS: https://github.com/JuliaLang/libosxunwind/blob/master/include/libunwind.h#L57
|
||||||
|
return DumpContext((unw_context_t *)&uc);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace PlatformWalkCallStack()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
StackTrace ret;
|
||||||
|
void *ips[1024];
|
||||||
|
|
||||||
|
int count = ::backtrace(ips, AuArraySize(ips));
|
||||||
|
|
||||||
|
auto messages = ::backtrace_symbols(ips, count);
|
||||||
|
if (!messages)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
StackTraceEntry entry;
|
||||||
|
|
||||||
|
entry.address = AuUInt64(ips[i]);
|
||||||
|
entry.label = AuUInt64(messages[i]);
|
||||||
|
|
||||||
|
TryComplete(entry);
|
||||||
|
|
||||||
|
AuTryInsert(ret, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(messages);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
::unw_context_t uc;
|
||||||
|
::unw_getcontext(&uc);
|
||||||
|
|
||||||
|
return DumpContext(&uc);
|
||||||
|
}
|
||||||
|
}
|
@ -7,3 +7,11 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <execinfo.h>
|
||||||
|
|
||||||
|
namespace Aurora::Debug
|
||||||
|
{
|
||||||
|
StackTrace DumpContext(ucontext_t &uc);
|
||||||
|
|
||||||
|
StackTrace PlatformWalkCallStack();
|
||||||
|
}
|
@ -41,7 +41,7 @@ namespace Aurora::Exit
|
|||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
sigaction(SIGINT, &action, nullptr);
|
sigaction(SIGINT, &action, nullptr);
|
||||||
sigaction(SIGTERM, &action, nullptr);
|
//sigaction(SIGTERM, &action, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeinitUnix()
|
void DeinitUnix()
|
||||||
@ -54,6 +54,6 @@ namespace Aurora::Exit
|
|||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
sigaction(SIGINT, &action, nullptr);
|
sigaction(SIGINT, &action, nullptr);
|
||||||
sigaction(SIGTERM, &action, nullptr);
|
//sigaction(SIGTERM, &action, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -115,6 +115,7 @@ namespace Aurora::Exit
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
AuLogInfo("Process Exiting");
|
||||||
Process::Exit(0);
|
Process::Exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace Aurora::HWInfo
|
|||||||
static AuUInt32 ReadUInt(const AuString &path)
|
static AuUInt32 ReadUInt(const AuString &path)
|
||||||
{
|
{
|
||||||
AuString contents;
|
AuString contents;
|
||||||
if (AuIOFS::ReadString(path, contents))
|
if (!AuIOFS::ReadString(path, contents))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#if !defined(_AURUNTIME_GENERICFS)
|
#if !defined(_AURUNTIME_GENERICFS)
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -28,14 +29,164 @@ namespace Aurora::IO::FS
|
|||||||
return mkdir(path.c_str(), 0775) == 0;
|
return mkdir(path.c_str(), 0775) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReadDirStructure : IReadDir
|
||||||
|
{
|
||||||
|
DIR *pDIR {};
|
||||||
|
struct dirent *pDE {};
|
||||||
|
bool bFirstTick { true };
|
||||||
|
bool bDead { false };
|
||||||
|
StatEx stat;
|
||||||
|
AuString sPath;
|
||||||
|
bool bFast {};
|
||||||
|
|
||||||
|
~ReadDirStructure()
|
||||||
|
{
|
||||||
|
if (this->pDIR)
|
||||||
|
{
|
||||||
|
::closedir(this->pDIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual StatEx *Next() override
|
||||||
|
{
|
||||||
|
bool bTryAgain {};
|
||||||
|
|
||||||
|
if (this->bDead)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!(this->pDE = ::readdir(this->pDIR)))
|
||||||
|
{
|
||||||
|
this->bDead = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->pDE->d_name == AuString(".") ||
|
||||||
|
this->pDE->d_name == AuString(".."))
|
||||||
|
{
|
||||||
|
bTryAgain = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat.exists = true;
|
||||||
|
|
||||||
|
stat.fileName = this->pDE->d_name;
|
||||||
|
|
||||||
|
if (stat.fileName.empty())
|
||||||
|
{
|
||||||
|
bTryAgain = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat.path = NormalizePathRet(this->sPath + stat.fileName);
|
||||||
|
|
||||||
|
if (this->bFast)
|
||||||
|
{
|
||||||
|
// nvm wont work. still need the is type dir/file flags
|
||||||
|
// return &stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StatFile(stat.path.c_str(), stat))
|
||||||
|
{
|
||||||
|
bTryAgain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (AuExchange(bTryAgain, false));
|
||||||
|
|
||||||
|
return &stat;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static AuSPtr<IReadDir> ReadDirEx(const AuString &string, bool bFast)
|
||||||
|
{
|
||||||
|
auto pObj = AuMakeShared<ReadDirStructure>();
|
||||||
|
if (!pObj)
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
pObj->bFast = bFast;
|
||||||
|
|
||||||
|
if (!AuIOFS::NormalizePath(pObj->sPath, string))
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AuTryInsert(pObj->sPath, '/'))
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
pObj->pDIR = ::opendir(pObj->sPath.c_str());
|
||||||
|
if (!pObj->pDIR)
|
||||||
|
{
|
||||||
|
SysPushErrorIO();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return pObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
AUKN_SYM AuSPtr<IReadDir> ReadDir(const AuString &string)
|
||||||
|
{
|
||||||
|
return ReadDirEx(string, false);
|
||||||
|
}
|
||||||
|
|
||||||
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files)
|
AUKN_SYM bool FilesInDirectory(const AuString &string, AuList<AuString> &files)
|
||||||
{
|
{
|
||||||
return IterateDirEntriesSTL(string, true, files);
|
auto itr = ReadDirEx(string, true);
|
||||||
|
if (!itr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SECURITY(): if next fails, its indistinguishable from end of file list, and will return true. it kinda sucks
|
||||||
|
while (auto stat = itr->Next())
|
||||||
|
{
|
||||||
|
if (!stat->existsFile)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AuTryInsert(files, stat->fileName))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM bool DirsInDirectory(const AuString &string, AuList<AuString> &dirs)
|
AUKN_SYM bool DirsInDirectory(const AuString &string, AuList<AuString> &dirs)
|
||||||
{
|
{
|
||||||
return IterateDirEntriesSTL(string, false, dirs);
|
auto itr = ReadDirEx(string, true);
|
||||||
|
if (!itr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SECURITY(): if next fails, its indistinguishable from end of file list, and will return true. it kinda sucks
|
||||||
|
while (auto stat = itr->Next())
|
||||||
|
{
|
||||||
|
if (!stat->existsDirectory)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AuTryInsert(dirs, stat->fileName))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM bool WriteFile(const AuString &path, const Memory::MemoryViewRead &blob)
|
AUKN_SYM bool WriteFile(const AuString &path, const Memory::MemoryViewRead &blob)
|
||||||
@ -231,7 +382,7 @@ namespace Aurora::IO::FS
|
|||||||
{
|
{
|
||||||
if (ENOENT != errno)
|
if (ENOENT != errno)
|
||||||
{
|
{
|
||||||
LogWarn("Critical IO error while stating file (errno: {}, path: {})", errno, path);
|
AuLogWarn("Critical IO error while stating file (errno: {}, path: {})", errno, path);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -243,7 +394,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (!stat.exists)
|
if (!stat.exists)
|
||||||
{
|
{
|
||||||
LogWarn("Missing attribute type in stat mode {} (of path {})", s.st_mode, path);
|
AuLogWarn("Missing attribute type in stat mode {} (of path {})", s.st_mode, path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,38 +118,5 @@ namespace Aurora::IO::FS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IterateDirEntriesSTL(const AuString &path, bool filesOnly, AuList<AuString> &patches)
|
|
||||||
{
|
|
||||||
#if defined(HAS_STD_FS)
|
|
||||||
auto normalizedPath = NormalizePathRet(path);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (const auto &entry : std::filesystem::directory_iterator(normalizedPath))
|
|
||||||
{
|
|
||||||
auto cpath = entry.path();
|
|
||||||
|
|
||||||
if (filesOnly && !std::filesystem::is_regular_file(cpath))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!filesOnly && !std::filesystem::is_directory(cpath))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AuString path = cpath.string();
|
|
||||||
patches.push_back(path.substr(path.find_last_of(kPathSplitter) + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
Debug::PrintError();
|
|
||||||
Logging::LogWarn("IO Error, couldn't iterate path: {}", normalizedPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitResources();
|
void InitResources();
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ namespace Aurora::IO::FS
|
|||||||
{
|
{
|
||||||
bool ApplyDumbAdvisoryLock(int fd, EFileAdvisoryLockLevel level)
|
bool ApplyDumbAdvisoryLock(int fd, EFileAdvisoryLockLevel level)
|
||||||
{
|
{
|
||||||
|
#if !defined(AURORA_IS_LINUX_DERIVED)
|
||||||
int operation = LOCK_NB;
|
int operation = LOCK_NB;
|
||||||
|
|
||||||
switch (level)
|
switch (level)
|
||||||
@ -29,6 +30,60 @@ namespace Aurora::IO::FS
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flock(fd, operation) == 0;
|
// Assume:
|
||||||
|
// "Furthermore, the lock is release either by an explicit LOCK_UN
|
||||||
|
// operation on any of these duplicate file descriptors, or when
|
||||||
|
// all such file descriptors have been closed"
|
||||||
|
|
||||||
|
return ::flock(fd, operation) == 0;
|
||||||
|
#else
|
||||||
|
// Linux
|
||||||
|
int lease {};
|
||||||
|
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case EFileAdvisoryLockLevel::eEnumCount:
|
||||||
|
case EFileAdvisoryLockLevel::eNoSafety:
|
||||||
|
return true;
|
||||||
|
case EFileAdvisoryLockLevel::eBlockWrite:
|
||||||
|
lease = F_RDLCK;
|
||||||
|
break;
|
||||||
|
case EFileAdvisoryLockLevel::eBlockReadWrite:
|
||||||
|
lease = F_RDLCK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore warning bc idc
|
||||||
|
// I assume c++ compilers under posix land allow for struct init the c way
|
||||||
|
struct flock lck =
|
||||||
|
{
|
||||||
|
.l_whence = SEEK_SET,
|
||||||
|
.l_start = 0,
|
||||||
|
.l_len = 0,
|
||||||
|
.l_type = lease
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assume this is true:
|
||||||
|
// * If a process closes any file descriptor referring to a file,
|
||||||
|
// then all of the process's locks on that file are released,
|
||||||
|
// regardless of the file descriptor(s) on which the locks were
|
||||||
|
// obtained. This is bad: it means that a process can lose its
|
||||||
|
// locks on a file such as /etc/passwd or /etc/mtab when for some
|
||||||
|
// reason a library function decides to open, read, and close the
|
||||||
|
// same file.
|
||||||
|
// [...]
|
||||||
|
//
|
||||||
|
// Open file description locks solve both of these problems.
|
||||||
|
//
|
||||||
|
// OFD's description implies it inherits non-ofd behaviour
|
||||||
|
// I wanted to confirm a l_len zero would work to lock all contents,
|
||||||
|
// even on expansion of the file. The docs didn't mention anything;
|
||||||
|
// however, I don't really see any real difference len processing in
|
||||||
|
// the kernel. Furthermore, I saw the kernels implementation checking
|
||||||
|
// for MAX_OFFSET of int type (-1) before overloading l_len with zero.
|
||||||
|
//
|
||||||
|
// I assume this will work. Linux locking is trash.
|
||||||
|
return ::fcntl(fd, F_OFD_SETLK, &lck) == 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -80,11 +80,11 @@ namespace Aurora::IO
|
|||||||
|
|
||||||
void ReserveBuffer(AuUInt length) override;
|
void ReserveBuffer(AuUInt length) override;
|
||||||
|
|
||||||
AuUInt GetReadOffset();
|
AuUInt GetReadOffset() override;
|
||||||
AuUInt SetReadOffset(AuUInt offset);
|
AuUInt SetReadOffset(AuUInt offset) override;
|
||||||
|
|
||||||
AuUInt GetWriteOffset();
|
AuUInt GetWriteOffset() override;
|
||||||
AuUInt SetWriteOffset(AuUInt offset);
|
AuUInt SetWriteOffset(AuUInt offset) override;
|
||||||
|
|
||||||
bool asyncActive {};
|
bool asyncActive {};
|
||||||
AuUInt readOffset {};
|
AuUInt readOffset {};
|
||||||
|
@ -26,7 +26,7 @@ namespace Aurora::IO
|
|||||||
|
|
||||||
AuUInt32 TryTick() override;
|
AuUInt32 TryTick() override;
|
||||||
AuUInt32 RunTick() override;
|
AuUInt32 RunTick() override;
|
||||||
AuUInt32 TickFor(const AuSPtr<IIOProcessorItem> &ioEvent);
|
AuUInt32 TickFor(const AuSPtr<IIOProcessorItem> &ioEvent) override;
|
||||||
bool TickForRegister(const AuSPtr<IIOProcessorItem> &ioEvent);
|
bool TickForRegister(const AuSPtr<IIOProcessorItem> &ioEvent);
|
||||||
|
|
||||||
void TickForHack(const AuSPtr<IIOProcessorItem> &ioEvent);
|
void TickForHack(const AuSPtr<IIOProcessorItem> &ioEvent);
|
||||||
|
@ -59,7 +59,6 @@ namespace Aurora::IO
|
|||||||
|
|
||||||
AUKN_SYM bool IOYield()
|
AUKN_SYM bool IOYield()
|
||||||
{
|
{
|
||||||
AuLogWarn("TODO");
|
return UNIX::LinuxOverlappedYield();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -65,7 +65,7 @@ namespace Aurora::IO::IPC
|
|||||||
return this->values[0].subtype == type;
|
return this->values[0].subtype == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPCHandle::PushId(EIPCHandleType type, IPCToken &token)
|
bool IPCHandle::PushId(EIPCHandleType type, const IPCToken &token)
|
||||||
{
|
{
|
||||||
IPCValue val;
|
IPCValue val;
|
||||||
val.subtype = type;
|
val.subtype = type;
|
||||||
@ -157,6 +157,7 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
int stringOffset {};
|
int stringOffset {};
|
||||||
int count {};
|
int count {};
|
||||||
|
IPCHeader headerZero;
|
||||||
while (in.size() > (stringOffset + 2))
|
while (in.size() > (stringOffset + 2))
|
||||||
{
|
{
|
||||||
int index = count++;
|
int index = count++;
|
||||||
@ -172,6 +173,11 @@ namespace Aurora::IO::IPC
|
|||||||
this->pid = nextInt;
|
this->pid = nextInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
headerZero = header;
|
||||||
|
}
|
||||||
|
|
||||||
auto readIPC = [&](IPCHeader header, IPCValue &value)
|
auto readIPC = [&](IPCHeader header, IPCValue &value)
|
||||||
{
|
{
|
||||||
value.subtype = (EIPCHandleType)header.bmType;
|
value.subtype = (EIPCHandleType)header.bmType;
|
||||||
@ -256,7 +262,7 @@ namespace Aurora::IO::IPC
|
|||||||
IPCHeader header;
|
IPCHeader header;
|
||||||
|
|
||||||
header.bmArray = index == 0 ? this->values.size() : 0;
|
header.bmArray = index == 0 ? this->values.size() : 0;
|
||||||
header.bmHasPid = index == 0 ? this->pid : 0;
|
header.bmHasPid = index == 0 ? (this->pid ? 1 : 0) : 0;
|
||||||
header.bmType = (AuUInt8)ipcValue.subtype;
|
header.bmType = (AuUInt8)ipcValue.subtype;
|
||||||
header.bmHasWord = (AuUInt8)(ipcValue.token.word ? 1 : 0);
|
header.bmHasWord = (AuUInt8)(ipcValue.token.word ? 1 : 0);
|
||||||
|
|
||||||
@ -308,5 +314,10 @@ namespace Aurora::IO::IPC
|
|||||||
{
|
{
|
||||||
return this->pid;
|
return this->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t IPCToken::ToUnixPid() const
|
||||||
|
{
|
||||||
|
return this->pid;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
@ -15,7 +15,8 @@ namespace Aurora::IO::IPC
|
|||||||
eIPCSharedFd,
|
eIPCSharedFd,
|
||||||
eIPCPrimitiveSemaphore,
|
eIPCPrimitiveSemaphore,
|
||||||
eIPCPrimitiveMutex,
|
eIPCPrimitiveMutex,
|
||||||
eIPCPrimitiveEvent
|
eIPCPrimitiveEvent,
|
||||||
|
eIPCPipeEnd
|
||||||
));
|
));
|
||||||
|
|
||||||
struct IPCToken
|
struct IPCToken
|
||||||
@ -37,6 +38,10 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
AuString ToNTPath() const;
|
AuString ToNTPath() const;
|
||||||
AuUInt32 ToUnixServerCookie() const;
|
AuUInt32 ToUnixServerCookie() const;
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||||
|
pid_t ToUnixPid() const;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IPCValue
|
struct IPCValue
|
||||||
@ -70,7 +75,7 @@ namespace Aurora::IO::IPC
|
|||||||
IPCHandle();
|
IPCHandle();
|
||||||
|
|
||||||
bool IsTopEq(EIPCHandleType type) const;
|
bool IsTopEq(EIPCHandleType type) const;
|
||||||
bool PushId(EIPCHandleType type, IPCToken &token);
|
bool PushId(EIPCHandleType type, const IPCToken &token);
|
||||||
|
|
||||||
IPCValue *GetToken(EIPCHandleType type, int id);
|
IPCValue *GetToken(EIPCHandleType type, int id);
|
||||||
|
|
||||||
|
@ -10,33 +10,12 @@
|
|||||||
#include "IPCHandle.hpp"
|
#include "IPCHandle.hpp"
|
||||||
#include "IPCMemory.NT.hpp"
|
#include "IPCMemory.NT.hpp"
|
||||||
|
|
||||||
#include <Source/IO/IPC/IPC.hpp>
|
|
||||||
#include <Source/IO/IPC/IPCHandle.hpp>
|
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Shared memory
|
// Shared memory
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct IPCSharedMemoryImpl : IPCSharedMemory
|
|
||||||
{
|
|
||||||
IPCSharedMemoryImpl(HANDLE handle, void *ptr, const IPC::IPCHandle &ipcHandle);
|
|
||||||
~IPCSharedMemoryImpl();
|
|
||||||
|
|
||||||
virtual Memory::MemoryViewWrite GetMemory() override;
|
|
||||||
virtual AuUInt GetLength() override;
|
|
||||||
|
|
||||||
virtual AuString ExportToString() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IPC::IPCHandle ipcHandle_;
|
|
||||||
bool owns_;
|
|
||||||
HANDLE handle_{};
|
|
||||||
void *base_{};
|
|
||||||
AuUInt len_ {};
|
|
||||||
};
|
|
||||||
|
|
||||||
IPCSharedMemoryImpl::IPCSharedMemoryImpl(HANDLE handle, void *ptr, const IPC::IPCHandle &ipcHandle) :
|
IPCSharedMemoryImpl::IPCSharedMemoryImpl(HANDLE handle, void *ptr, const IPC::IPCHandle &ipcHandle) :
|
||||||
base_(ptr), len_(ipcHandle.values[0].token.word), handle_(handle), ipcHandle_(ipcHandle)
|
base_(ptr), len_(ipcHandle.values[0].token.word), handle_(handle), ipcHandle_(ipcHandle)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,26 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Source/IO/IPC/IPC.hpp>
|
||||||
|
#include <Source/IO/IPC/IPCHandle.hpp>
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
|
struct IPCSharedMemoryImpl : IPCSharedMemory
|
||||||
|
{
|
||||||
|
IPCSharedMemoryImpl(HANDLE handle, void *ptr, const IPC::IPCHandle &ipcHandle);
|
||||||
|
~IPCSharedMemoryImpl();
|
||||||
|
|
||||||
|
virtual Memory::MemoryViewWrite GetMemory() override;
|
||||||
|
virtual AuUInt GetLength() override;
|
||||||
|
|
||||||
|
virtual AuString ExportToString() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IPC::IPCHandle ipcHandle_;
|
||||||
|
bool owns_;
|
||||||
|
HANDLE handle_{};
|
||||||
|
void *base_{};
|
||||||
|
AuUInt len_ {};
|
||||||
|
};
|
||||||
}
|
}
|
@ -10,38 +10,21 @@
|
|||||||
#include "IPCHandle.hpp"
|
#include "IPCHandle.hpp"
|
||||||
#include "IPCMemory.Unix.hpp"
|
#include "IPCMemory.Unix.hpp"
|
||||||
|
|
||||||
#include <Source/IO/IPC/IPC.hpp>
|
|
||||||
#include <Source/IO/IPC/IPCHandle.hpp>
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h> /* For mode constants */
|
#include <sys/stat.h> /* For mode constants */
|
||||||
#include <fcntl.h> /* For O_* constants */
|
#include <fcntl.h> /* For O_* constants */
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
|
#include "IPCMutexFutex.Linux.hpp" /* For import */
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Shared memory
|
// Shared memory
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct IPCSharedMemoryImpl : IPCSharedMemory
|
static AuString GetServerPath(const IPC::IPCToken &handle)
|
||||||
{
|
|
||||||
IPCSharedMemoryImpl(int fd, void *ptr, const IPC::IPCHandle &handle, bool owns);
|
|
||||||
~IPCSharedMemoryImpl();
|
|
||||||
|
|
||||||
virtual Memory::MemoryViewWrite GetMemory() override;
|
|
||||||
virtual AuUInt GetLength() override;
|
|
||||||
|
|
||||||
virtual AuString ExportToString() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IPC::IPCHandle handle_;
|
|
||||||
bool owns_;
|
|
||||||
int fd_{};
|
|
||||||
void *base_{};
|
|
||||||
AuUInt len_ {};
|
|
||||||
};
|
|
||||||
|
|
||||||
static AuString GetServerPath(const IPC::IPCHandle &handle)
|
|
||||||
{
|
{
|
||||||
AuString path;
|
AuString path;
|
||||||
path += "/AURORA_";
|
path += "/AURORA_";
|
||||||
@ -52,7 +35,7 @@ namespace Aurora::IO::IPC
|
|||||||
}
|
}
|
||||||
|
|
||||||
IPCSharedMemoryImpl::IPCSharedMemoryImpl(int fd, void *ptr, const IPC::IPCHandle &handle, bool owns) :
|
IPCSharedMemoryImpl::IPCSharedMemoryImpl(int fd, void *ptr, const IPC::IPCHandle &handle, bool owns) :
|
||||||
fd_(fd), base_(ptr), len_(handle.word), owns_(owns), handle_(handle)
|
fd_(fd), base_(ptr), len_(handle.values[0].token.word), owns_(owns), handle_(handle)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -89,9 +72,14 @@ namespace Aurora::IO::IPC
|
|||||||
AUKN_SYM AuSPtr<IPCSharedMemory> NewSharedMemory(AuUInt length)
|
AUKN_SYM AuSPtr<IPCSharedMemory> NewSharedMemory(AuUInt length)
|
||||||
{
|
{
|
||||||
IPC::IPCHandle handle;
|
IPC::IPCHandle handle;
|
||||||
handle.NewId(length);
|
IPC::IPCToken token;
|
||||||
|
token.pid = handle.pid;
|
||||||
|
token.word = length;
|
||||||
|
token.NewId();
|
||||||
|
|
||||||
auto path = GetServerPath(handle);
|
handle.PushId(EIPCHandleType::eIPCMemory, token);
|
||||||
|
|
||||||
|
auto path = GetServerPath(token);
|
||||||
int fd = ::shm_open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
int fd = ::shm_open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
@ -126,17 +114,9 @@ namespace Aurora::IO::IPC
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCSharedMemory> ImportSharedMemory(const AuString &handleString)
|
AuSPtr<IPCSharedMemory> ImportSharedMemoryEx(const IPCToken &token)
|
||||||
{
|
{
|
||||||
IPC::IPCHandle handle;
|
auto path = GetServerPath(token);
|
||||||
|
|
||||||
if (!handle.FromString(handleString))
|
|
||||||
{
|
|
||||||
SysPushErrorParseError();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto path = GetServerPath(handle);
|
|
||||||
int fd = ::shm_open(path.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
|
int fd = ::shm_open(path.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
@ -144,7 +124,7 @@ namespace Aurora::IO::IPC
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto map = ::mmap(nullptr, handle.word, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
auto map = ::mmap(nullptr, token.word, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (map == MAP_FAILED)
|
if (map == MAP_FAILED)
|
||||||
{
|
{
|
||||||
SysPushErrorIO();
|
SysPushErrorIO();
|
||||||
@ -152,15 +132,38 @@ namespace Aurora::IO::IPC
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPC::IPCHandle handle;
|
||||||
|
handle.PushId(EIPCHandleType::eIPCMemory, token);
|
||||||
|
|
||||||
auto object = AuMakeShared<IPCSharedMemoryImpl>(fd, map, handle, false);
|
auto object = AuMakeShared<IPCSharedMemoryImpl>(fd, map, handle, false);
|
||||||
if (!object)
|
if (!object)
|
||||||
{
|
{
|
||||||
SysPushErrorMem();
|
SysPushErrorMem();
|
||||||
::munmap(map, handle.word);
|
::munmap(map, token.word);
|
||||||
::close(fd);
|
::close(fd);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,7 +7,28 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Source/IO/IPC/IPC.hpp>
|
||||||
|
#include <Source/IO/IPC/IPCHandle.hpp>
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
|
struct IPCSharedMemoryImpl : IPCSharedMemory
|
||||||
|
{
|
||||||
|
IPCSharedMemoryImpl(int fd, void *ptr, const IPC::IPCHandle &handle, bool owns);
|
||||||
|
~IPCSharedMemoryImpl();
|
||||||
|
|
||||||
|
virtual Memory::MemoryViewWrite GetMemory() override;
|
||||||
|
virtual AuUInt GetLength() override;
|
||||||
|
|
||||||
|
virtual AuString ExportToString() override;
|
||||||
|
|
||||||
|
IPC::IPCHandle handle_;
|
||||||
|
private:
|
||||||
|
bool owns_;
|
||||||
|
int fd_{};
|
||||||
|
void *base_{};
|
||||||
|
AuUInt len_ {};
|
||||||
|
};
|
||||||
|
|
||||||
|
AuSPtr<IPCSharedMemory> ImportSharedMemoryEx(const IPCToken &token);
|
||||||
}
|
}
|
424
Source/IO/IPC/IPCMutexFutex.Linux.cpp
Executable file
424
Source/IO/IPC/IPCMutexFutex.Linux.cpp
Executable file
@ -0,0 +1,424 @@
|
|||||||
|
/***
|
||||||
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||||
|
|
||||||
|
File: IPCMutexFutex.Linux.cpp
|
||||||
|
Date: 2022-
|
||||||
|
Author: Reece
|
||||||
|
Note:
|
||||||
|
***/
|
||||||
|
#include <Source/RuntimeInternal.hpp>
|
||||||
|
#include "IPC.hpp"
|
||||||
|
#include "IPCHandle.hpp"
|
||||||
|
#include "IPCMutexFutex.Linux.hpp"
|
||||||
|
|
||||||
|
#include <linux/futex.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <Source/IO/UNIX/FDIpcServer.hpp>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SysCalls
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if !defined(FUTEX_OWNER_DIED)
|
||||||
|
#define FUTEX_OWNER_DIED 0x40000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int futex(uint32_t *uaddr, int futex_op, uint32_t val,
|
||||||
|
const struct timespec *timeout, /* or: uint32_t val2 */
|
||||||
|
uint32_t *uaddr2, uint32_t val3)
|
||||||
|
{
|
||||||
|
return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int futex_wait(uint32_t *addr, uint32_t expected)
|
||||||
|
{
|
||||||
|
return futex(addr, FUTEX_WAIT, expected, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int futex_wake(uint32_t *addr, uint32_t nthreads)
|
||||||
|
{
|
||||||
|
return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long set_robust_list(struct procmon_head *head, size_t len)
|
||||||
|
{
|
||||||
|
return syscall(SYS_set_robust_list, head, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
|
||||||
|
{
|
||||||
|
return syscall(SYS_get_robust_list, pid, head_ptr, len_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CONSTANTS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const AuUInt8 kMaxFutexes = 128;
|
||||||
|
static const AuUInt32 kFutexArraySize = AuUInt32(kMaxFutexes) * 4;
|
||||||
|
|
||||||
|
static const AuUInt32 kFutexValueOwner = 0x80000000;
|
||||||
|
static const AuUInt32 kFutexValueLocked = kFutexValueOwner | 1;
|
||||||
|
static const AuUInt32 kFutexValueUnlocked = kFutexValueOwner;
|
||||||
|
static const AuUInt32 kFutexValueNULL = 0;
|
||||||
|
|
||||||
|
static const AuUInt32 kFutexValueMask = kFutexValueLocked;
|
||||||
|
static const AuUInt32 kFutexValueMaskOwner = kFutexValueOwner | FUTEX_OWNER_DIED;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// VARIABLES
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static AuSPtr<AuIPC::IPCSharedMemory> gFutexSharedMemory;
|
||||||
|
static AuUInt32 *gFutexArray;
|
||||||
|
static bool gFutexInit {};
|
||||||
|
|
||||||
|
static AuIOIPC::IMutexClosedHook * gFutexCallbacks[kMaxFutexes];
|
||||||
|
|
||||||
|
|
||||||
|
static void InitFutexAPI()
|
||||||
|
{
|
||||||
|
static AuThreadPrimitives::SpinLock lock;
|
||||||
|
|
||||||
|
AU_LOCK_GUARD(lock);
|
||||||
|
|
||||||
|
if (AuExchange(gFutexInit, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gFutexSharedMemory = AuIOIPC::NewSharedMemory(kFutexArraySize);
|
||||||
|
SysAssert(gFutexSharedMemory);
|
||||||
|
|
||||||
|
gFutexArray = gFutexSharedMemory->GetMemory().Begin<AuUInt32>();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FutexContext
|
||||||
|
{
|
||||||
|
bool bInit {};
|
||||||
|
|
||||||
|
// https://github.com/bminor/glibc/blob/78fb88827362fbd2cc8aa32892ae5b015106e25c/sysdeps/nptl/dl-tls_init_tp.c#L93
|
||||||
|
// Every thread should have an arraylist head
|
||||||
|
robust_list_head *head;
|
||||||
|
|
||||||
|
|
||||||
|
bool Init();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool FutexContext::Init()
|
||||||
|
{
|
||||||
|
if (AuExchange(this->bInit, true))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitFutexAPI();
|
||||||
|
|
||||||
|
return this->bInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static thread_local FutexContext tlsFutexContext;
|
||||||
|
|
||||||
|
static AuUInt8 AllocateFutex()
|
||||||
|
{
|
||||||
|
tlsFutexContext.Init();
|
||||||
|
if (!gFutexArray)
|
||||||
|
{
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AuUInt32 i = 0;
|
||||||
|
i < kMaxFutexes;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
if (AuAtomicCompareExchange<AuUInt32>(&gFutexArray[i], kFutexValueUnlocked, AuUInt32(0)) == 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryReleaseFutex(AuUInt8 index)
|
||||||
|
{
|
||||||
|
auto &cb = gFutexCallbacks[index];
|
||||||
|
if (cb)
|
||||||
|
{
|
||||||
|
if (!cb->OnClosed())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = nullptr;
|
||||||
|
gFutexArray[index] = 0;
|
||||||
|
gFutexCallbacks[index] = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeFutex(AuUInt8 index)
|
||||||
|
{
|
||||||
|
gFutexArray[index] = 0;
|
||||||
|
gFutexCallbacks[index] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxAddRobustFutexSlow(AuUInt32 *futex)
|
||||||
|
{
|
||||||
|
tlsFutexContext.Init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxRemoveRobustFutexSlow(AuUInt32 *futex)
|
||||||
|
{
|
||||||
|
tlsFutexContext.Init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxLockFutex(AuUInt32 *futex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxUnlockFutex(AuUInt32 *futex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxSuperSecretIOTick()
|
||||||
|
{
|
||||||
|
if (!gFutexInit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gFutexArray)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AuUInt32 i = 0;
|
||||||
|
i < kMaxFutexes;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
if (gFutexArray[i] == FUTEX_OWNER_DIED)
|
||||||
|
{
|
||||||
|
TryReleaseFutex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "IPCPrimitives.Linux.hpp"
|
||||||
|
#include "IPCMemory.Unix.hpp"
|
||||||
|
|
||||||
|
namespace Aurora::IO::IPC
|
||||||
|
{
|
||||||
|
static AuThreadPrimitives::SpinLock gLock;
|
||||||
|
static AuBST<AuPair<AuUInt64 /*cookie*/, AuUInt32 /*pid*/>, AuWPtr<IPCSharedMemory>> gSharedViewCache;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mutexes
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IPCMutexProxy::IPCMutexProxy(AuUInt32 index) : mutex_(), bOwned(true), index_(index)
|
||||||
|
{
|
||||||
|
if (this->mutex_.HasValidHandle())
|
||||||
|
{
|
||||||
|
if (IO::UNIX::FDServe(this->GetHandle(), this->token_))
|
||||||
|
{
|
||||||
|
//this->handle_.PushId(EIPCHandleType::eIPCPrimitiveMutex, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->mutex_.~LSMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mem_ = gFutexSharedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCMutexProxy::IPCMutexProxy(int handle, AuSPtr<IPCSharedMemory> mem, AuUInt32 index) :
|
||||||
|
mutex_(handle),
|
||||||
|
mem_(mem),
|
||||||
|
index_(index)
|
||||||
|
{
|
||||||
|
if (this->mutex_.HasValidHandle())
|
||||||
|
{
|
||||||
|
if (IO::UNIX::FDServe(this->GetHandle(), this->token_))
|
||||||
|
{
|
||||||
|
//this->handle_.PushId(EIPCHandleType::eIPCPrimitiveMutex, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->mutex_.~LSMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCMutexProxy::~IPCMutexProxy()
|
||||||
|
{
|
||||||
|
IO::UNIX::FDServeEnd(this->token_);
|
||||||
|
|
||||||
|
if (this->bOwned)
|
||||||
|
{
|
||||||
|
FreeFutex(this->index_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPCMutexProxy::Unlock()
|
||||||
|
{
|
||||||
|
return this->mutex_.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPCMutexProxy::IsSignaled()
|
||||||
|
{
|
||||||
|
return this->mutex_.IsSignaled();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPCMutexProxy::WaitOn(AuUInt32 timeout)
|
||||||
|
{
|
||||||
|
return this->mutex_.WaitOn(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loop::ELoopSource IPCMutexProxy::GetType()
|
||||||
|
{
|
||||||
|
return this->mutex_.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
AuString IPCMutexProxy::ExportToString()
|
||||||
|
{
|
||||||
|
IPC::IPCHandle handle;
|
||||||
|
|
||||||
|
handle.PushId(EIPCHandleType::eIPCPrimitiveMutex, this->token_);
|
||||||
|
SysAssert(this->mem_);
|
||||||
|
handle.PushId(EIPCHandleType::eIPCMemory, AuStaticCast<IPCSharedMemoryImpl>(this->mem_)->handle_.values[0].token);
|
||||||
|
handle.values[0].token.word = this->index_;
|
||||||
|
|
||||||
|
return handle.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
AUKN_SYM AuSPtr<IPCMutex> NewMutex()
|
||||||
|
{
|
||||||
|
auto futex = AllocateFutex();
|
||||||
|
if (futex == 255)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto object = AuMakeShared<IPCMutexProxy>(futex);
|
||||||
|
if (!object)
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!object->HasValidHandle())
|
||||||
|
{
|
||||||
|
SysPushErrorIO();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AuSPtr<IPCSharedMemory> GetFutexPagesFromCacheOrImport(const IPCToken &mem)
|
||||||
|
{
|
||||||
|
AU_LOCK_GUARD(gLock);
|
||||||
|
|
||||||
|
auto id = AuMakePair(mem.cookie, mem.pid);
|
||||||
|
auto itr = gSharedViewCache.find(id);
|
||||||
|
if (itr != gSharedViewCache.end())
|
||||||
|
{
|
||||||
|
auto test = itr->second.lock();
|
||||||
|
if (test)
|
||||||
|
{
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shared = ImportSharedMemoryEx(mem);
|
||||||
|
if (!shared)
|
||||||
|
{
|
||||||
|
SysPushErrorNested();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AuTryInsert(gSharedViewCache, id, shared))
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
// We don't need to fail. We can leak next time. It'll be fine.
|
||||||
|
}
|
||||||
|
|
||||||
|
return shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuSPtr<IPCMutex> ImportMutexEx(const IPCToken &handle, const IPCToken &mem, AuUInt32 index)
|
||||||
|
{
|
||||||
|
int fd {-1};
|
||||||
|
if (!IO::UNIX::FDAccept(handle, fd))
|
||||||
|
{
|
||||||
|
SysPushErrorNested();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto view = GetFutexPagesFromCacheOrImport(mem);
|
||||||
|
if (!view)
|
||||||
|
{
|
||||||
|
SysPushErrorNested();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto object = AuMakeShared<IPCMutexProxy>(fd, view, index);
|
||||||
|
if (!object)
|
||||||
|
{
|
||||||
|
SysPushErrorMem();
|
||||||
|
::close(fd);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!object->HasValidHandle())
|
||||||
|
{
|
||||||
|
SysPushErrorIO();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
AUKN_SYM AuSPtr<IPCMutex> ImportMutex(const AuString &handle)
|
||||||
|
{
|
||||||
|
IPC::IPCHandle decodedHandle;
|
||||||
|
|
||||||
|
if (!decodedHandle.FromString(handle))
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveMutex, 0);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mem = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCMemory, 0);
|
||||||
|
if (!mem)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImportMutexEx(val->token, mem->token, val->token.word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Aurora::Grug
|
||||||
|
{
|
||||||
|
void LinuxSuperSecretIOTick()
|
||||||
|
{
|
||||||
|
::LinuxSuperSecretIOTick();
|
||||||
|
}
|
||||||
|
}
|
43
Source/IO/IPC/IPCMutexFutex.Linux.hpp
Executable file
43
Source/IO/IPC/IPCMutexFutex.Linux.hpp
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IPCHandle.hpp"
|
||||||
|
#include "IPCPrimitives.Linux.hpp"
|
||||||
|
|
||||||
|
namespace Aurora::IO::IPC
|
||||||
|
{
|
||||||
|
struct IMutexClosedHook
|
||||||
|
{
|
||||||
|
virtual bool OnClosed() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// IPC::IPCHandle handle;
|
||||||
|
|
||||||
|
struct IPCPipeImpl;
|
||||||
|
|
||||||
|
struct IPCMutexProxy : IPCMutex, Loop::ILoopSourceEx
|
||||||
|
{
|
||||||
|
IPCMutexProxy(AuUInt32 index);
|
||||||
|
IPCMutexProxy(int handle, AuSPtr<IPCSharedMemory> mem, AuUInt32 index);
|
||||||
|
~IPCMutexProxy();
|
||||||
|
|
||||||
|
PROXY_INTERNAL_INTERFACE(mutex_)
|
||||||
|
|
||||||
|
bool Unlock() override;
|
||||||
|
|
||||||
|
bool IsSignaled() override;
|
||||||
|
bool WaitOn(AuUInt32 timeout) override;
|
||||||
|
Loop::ELoopSource GetType() override;
|
||||||
|
|
||||||
|
AuString ExportToString() override;
|
||||||
|
private:
|
||||||
|
bool bOwned {};
|
||||||
|
IPCToken token_;
|
||||||
|
AuSPtr<IPCSharedMemory> mem_;
|
||||||
|
AuUInt32 index_;
|
||||||
|
Loop::LSMutex mutex_;
|
||||||
|
|
||||||
|
friend IPCPipeImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
AuSPtr<IPCMutex> ImportMutexEx(const IPCToken &handle, const IPCToken &mem, AuUInt32 index);
|
||||||
|
}
|
@ -16,8 +16,14 @@
|
|||||||
#include <Source/IO/Loop/LSHandle.hpp>
|
#include <Source/IO/Loop/LSHandle.hpp>
|
||||||
#include <Source/IO/Loop/LSEvent.hpp>
|
#include <Source/IO/Loop/LSEvent.hpp>
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
#include <Source/IO/UNIX/IOSubmit.Linux.hpp>
|
#include <Source/IO/UNIX/IOSubmit.Linux.hpp>
|
||||||
#include <Source/IO/FS/Async.Linux.hpp>
|
#include <Source/IO/FS/Async.Linux.hpp>
|
||||||
|
#include "IPCPrimitives.Linux.hpp"
|
||||||
|
#include "IPCMutexFutex.Linux.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "IPCMemory.Unix.hpp" // required for handle
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
@ -29,7 +35,7 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
struct IPCPipeImpl : IPCPipe, Loop::LSHandle, AuEnableSharedFromThis<IPCPipeImpl>
|
struct IPCPipeImpl : IPCPipe, Loop::LSHandle, AuEnableSharedFromThis<IPCPipeImpl>
|
||||||
{
|
{
|
||||||
IPCPipeImpl(int (fds)[2], int (secondary)[2], IPCHandle readEnd, IPCHandle writeEnd, AuSPtr<IPCEvent> event, AuSPtr<IPCMutex> mutex);
|
IPCPipeImpl(int (fds)[2], int (secondary)[2], IPCToken readEnd, IPCToken writeEnd, AuSPtr<IPCEvent> event, AuSPtr<IPCMutex> mutex);
|
||||||
~IPCPipeImpl();
|
~IPCPipeImpl();
|
||||||
|
|
||||||
PROXY_INTERNAL_INTERFACE_(LSHandle::)
|
PROXY_INTERNAL_INTERFACE_(LSHandle::)
|
||||||
@ -54,13 +60,13 @@ namespace Aurora::IO::IPC
|
|||||||
AuSPtr<IO::FS::FileHandle> fsHandle_;
|
AuSPtr<IO::FS::FileHandle> fsHandle_;
|
||||||
AuSPtr<IO::FS::LinuxAsyncFileStream> fsStream_;
|
AuSPtr<IO::FS::LinuxAsyncFileStream> fsStream_;
|
||||||
|
|
||||||
IPCHandle readEnd_;
|
IPCToken readEnd_;
|
||||||
IPCHandle writeEnd_;
|
IPCToken writeEnd_;
|
||||||
AuSPtr<IPCEvent> event_;
|
AuSPtr<IPCEvent> event_;
|
||||||
AuSPtr<IPCMutex> mutex_;
|
AuSPtr<IPCMutex> mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
IPCPipeImpl::IPCPipeImpl(int (fds2)[2], int (fds3)[2], IPCHandle readEnd, IPCHandle writeEnd, AuSPtr<IPCEvent> event, AuSPtr<IPCMutex> mutex) :
|
IPCPipeImpl::IPCPipeImpl(int (fds2)[2], int (fds3)[2], IPCToken readEnd, IPCToken writeEnd, AuSPtr<IPCEvent> event, AuSPtr<IPCMutex> mutex) :
|
||||||
fds {fds2[0], fds2[1]}, secondary {fds3[0], fds3[1]},
|
fds {fds2[0], fds2[1]}, secondary {fds3[0], fds3[1]},
|
||||||
readEnd_(readEnd), writeEnd_(writeEnd), event_(event), mutex_(mutex)
|
readEnd_(readEnd), writeEnd_(writeEnd), event_(event), mutex_(mutex)
|
||||||
{
|
{
|
||||||
@ -240,15 +246,27 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
AuString IPCPipeImpl::ExportToString()
|
AuString IPCPipeImpl::ExportToString()
|
||||||
{
|
{
|
||||||
return this->readEnd_.ToString() + "." +
|
IPC::IPCHandle handle;
|
||||||
this->writeEnd_.ToString() + "." +
|
|
||||||
this->event_->ExportToString() + "." +
|
handle.PushId(EIPCHandleType::eIPCPipe, AuStaticCast<IPCEventProxy>(this->event_)->handle_.values[0].token);
|
||||||
this->mutex_->ExportToString();
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
|
auto that = AuStaticCast<IPCMutexProxy>(this->mutex_);
|
||||||
|
handle.PushId(EIPCHandleType::eIPCPrimitiveMutex, that->token_);
|
||||||
|
SysAssert(that->mem_);
|
||||||
|
handle.PushId(EIPCHandleType::eIPCMemory, AuStaticCast<IPCSharedMemoryImpl>(that->mem_)->handle_.values[0].token);
|
||||||
|
handle.values[1].token.word = that->index_;
|
||||||
|
#else
|
||||||
|
handle.PushId(EIPCHandleType::eIPCPrimitiveMutex, ->handle_.values[0].token);
|
||||||
|
#endif
|
||||||
|
handle.PushId(EIPCHandleType::eIPCPipeEnd, this->readEnd_);
|
||||||
|
handle.PushId(EIPCHandleType::eIPCPipeEnd, this->writeEnd_);
|
||||||
|
|
||||||
|
return handle.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCPipe> NewPipe()
|
AUKN_SYM AuSPtr<IPCPipe> NewPipe()
|
||||||
{
|
{
|
||||||
IPCHandle readEnd, writeEnd;
|
IPCToken readEnd, writeEnd;
|
||||||
int fds1[2];
|
int fds1[2];
|
||||||
int fds2[2];
|
int fds2[2];
|
||||||
|
|
||||||
@ -280,7 +298,7 @@ namespace Aurora::IO::IPC
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IO::UNIX::FDServe(true, true, true, true, fds1[0], readEnd))
|
if (!IO::UNIX::FDServe(fds1[0], readEnd))
|
||||||
{
|
{
|
||||||
SysPushErrorIO();
|
SysPushErrorIO();
|
||||||
::close(fds1[0]);
|
::close(fds1[0]);
|
||||||
@ -290,7 +308,7 @@ namespace Aurora::IO::IPC
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IO::UNIX::FDServe(true, true, true, true, fds2[1], writeEnd))
|
if (!IO::UNIX::FDServe(fds2[1], writeEnd))
|
||||||
{
|
{
|
||||||
SysPushErrorIO();
|
SysPushErrorIO();
|
||||||
IO::UNIX::FDServeEnd(readEnd);
|
IO::UNIX::FDServeEnd(readEnd);
|
||||||
@ -320,65 +338,78 @@ namespace Aurora::IO::IPC
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCPipe> ImportPipe(const AuString &handle)
|
AUKN_SYM AuSPtr<IPCPipe> ImportPipe(const AuString &handleString)
|
||||||
{
|
{
|
||||||
IPCHandle readEnd, writeEnd;
|
|
||||||
int fds[2] {-1, -1};
|
int fds[2] {-1, -1};
|
||||||
|
|
||||||
auto itr = handle.find('.');
|
IPCHandle handle;
|
||||||
if (itr == AuString::npos)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto itr2 = handle.find_first_of('.', itr + 1);
|
if (!handle.FromString(handleString))
|
||||||
if (itr2 == AuString::npos)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto itr3 = handle.find_first_of('.', itr2 + 1);
|
|
||||||
if (itr3 == AuString::npos)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto readString = handle.substr(0, itr);
|
|
||||||
auto writeString = handle.substr(itr + 1, itr2 - itr - 1);
|
|
||||||
auto eventString = handle.substr(itr2 + 1, itr3 - itr2 - 1);
|
|
||||||
auto mutexString = handle.substr(itr3 + 1);
|
|
||||||
|
|
||||||
if (!readEnd.FromString(readString))
|
|
||||||
{
|
{
|
||||||
SysPushErrorParseError();
|
SysPushErrorParseError();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!writeEnd.FromString(writeString))
|
auto eventVal = handle.GetToken(IPC::EIPCHandleType::eIPCPipe, 0);
|
||||||
|
if (!eventVal)
|
||||||
{
|
{
|
||||||
SysPushErrorParseError();
|
SysPushErrorParseError();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto event = ImportEvent(eventString);
|
auto mutexVal = handle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveMutex, 1);
|
||||||
|
if (!mutexVal)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset {};
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
|
offset = 1;
|
||||||
|
|
||||||
|
auto ipcMem = handle.GetToken(IPC::EIPCHandleType::eIPCMemory, 2);
|
||||||
|
if (!ipcMem)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto readVal = handle.GetToken(IPC::EIPCHandleType::eIPCPipeEnd, 2 + offset);
|
||||||
|
if (!readVal)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto writeVal = handle.GetToken(IPC::EIPCHandleType::eIPCPipeEnd, 3 + offset);
|
||||||
|
if (!writeVal)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto event = ImportEventEx(eventVal->token);
|
||||||
if (!event)
|
if (!event)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mutex = ImportMutex(mutexString);
|
auto mutex = ImportMutexEx(mutexVal->token, ipcMem->token, mutexVal->token.word);
|
||||||
if (!mutex)
|
if (!mutex)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IO::UNIX::FDAccept(readEnd, fds[0]))
|
if (!IO::UNIX::FDAccept(readVal->token, fds[0]))
|
||||||
{
|
{
|
||||||
SysPushErrorNested();
|
SysPushErrorNested();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IO::UNIX::FDAccept(writeEnd, fds[1]))
|
if (!IO::UNIX::FDAccept(writeVal->token, fds[1]))
|
||||||
{
|
{
|
||||||
::close(fds[0]);
|
::close(fds[0]);
|
||||||
SysPushErrorNested();
|
SysPushErrorNested();
|
||||||
@ -386,7 +417,12 @@ namespace Aurora::IO::IPC
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dummy[2] {-1, -1};
|
int dummy[2] {-1, -1};
|
||||||
auto object = AuMakeShared<IPCPipeImpl>(fds, dummy, readEnd, writeEnd, event, mutex);
|
auto object = AuMakeShared<IPCPipeImpl>(fds,
|
||||||
|
dummy,
|
||||||
|
readVal->token,
|
||||||
|
writeVal->token,
|
||||||
|
event,
|
||||||
|
mutex);
|
||||||
if (!object)
|
if (!object)
|
||||||
{
|
{
|
||||||
SysPushErrorMem();
|
SysPushErrorMem();
|
||||||
|
@ -8,56 +8,29 @@
|
|||||||
#include <Source/RuntimeInternal.hpp>
|
#include <Source/RuntimeInternal.hpp>
|
||||||
#include "IPC.hpp"
|
#include "IPC.hpp"
|
||||||
#include "IPCHandle.hpp"
|
#include "IPCHandle.hpp"
|
||||||
|
|
||||||
#include "IPCPrimitives.Linux.hpp"
|
#include "IPCPrimitives.Linux.hpp"
|
||||||
|
|
||||||
#include <Source/IO/Loop/LSEvent.hpp>
|
|
||||||
#include <Source/IO/Loop/LSSemaphore.hpp>
|
|
||||||
#include <Source/IO/Loop/LSMutex.hpp>
|
|
||||||
|
|
||||||
#include <Source/IO/IPC/IPC.hpp>
|
|
||||||
#include <Source/IO/IPC/IPCHandle.hpp>
|
|
||||||
|
|
||||||
#include <Source/IO/UNIX/FDIpcServer.hpp>
|
#include <Source/IO/UNIX/FDIpcServer.hpp>
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
#define IMPLEMENT_HANDLE \
|
|
||||||
IPC::IPCHandle handle_; \
|
|
||||||
AuString ExportToString() override \
|
|
||||||
{ \
|
|
||||||
return handle_.ToString(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Events
|
// Events
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct IPCEventProxy : IPCEvent, Loop::ILoopSourceEx
|
|
||||||
{
|
|
||||||
IPCEventProxy(bool triggered, bool atomicRelease);
|
|
||||||
IPCEventProxy(int handle, bool triggered, bool atomicRelease);
|
|
||||||
~IPCEventProxy();
|
|
||||||
|
|
||||||
PROXY_INTERNAL_INTERFACE(event_)
|
|
||||||
IMPLEMENT_HANDLE
|
|
||||||
|
|
||||||
bool Set() override;
|
|
||||||
bool Reset() override;
|
|
||||||
|
|
||||||
bool IsSignaled() override;
|
|
||||||
bool WaitOn(AuUInt32 timeout) override;
|
|
||||||
Loop::ELoopSource GetType() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Loop::LSEvent event_;
|
|
||||||
};
|
|
||||||
|
|
||||||
IPCEventProxy::IPCEventProxy(bool triggered, bool atomicRelease) : event_(triggered, atomicRelease, true)
|
IPCEventProxy::IPCEventProxy(bool triggered, bool atomicRelease) : event_(triggered, atomicRelease, true)
|
||||||
{
|
{
|
||||||
|
IPC::IPCToken token;
|
||||||
|
|
||||||
if (this->event_.HasValidHandle())
|
if (this->event_.HasValidHandle())
|
||||||
{
|
{
|
||||||
if (!IO::UNIX::FDServe(triggered, atomicRelease, false, true, this->GetHandle(), this->handle_))
|
if (IO::UNIX::FDServe(this->GetHandle(), token))
|
||||||
|
{
|
||||||
|
token.word = AuUInt32(atomicRelease);
|
||||||
|
this->handle_.PushId(EIPCHandleType::eIPCPrimitiveEvent, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
this->event_.~LSEvent();
|
this->event_.~LSEvent();
|
||||||
}
|
}
|
||||||
@ -66,9 +39,16 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
IPCEventProxy::IPCEventProxy(int handle, bool triggered, bool atomicRelease) : event_(handle, triggered, atomicRelease)
|
IPCEventProxy::IPCEventProxy(int handle, bool triggered, bool atomicRelease) : event_(handle, triggered, atomicRelease)
|
||||||
{
|
{
|
||||||
|
IPC::IPCToken token;
|
||||||
|
|
||||||
if (this->event_.HasValidHandle())
|
if (this->event_.HasValidHandle())
|
||||||
{
|
{
|
||||||
if (!IO::UNIX::FDServe(triggered, atomicRelease, false, true, this->GetHandle(), this->handle_))
|
if (IO::UNIX::FDServe(this->GetHandle(), token))
|
||||||
|
{
|
||||||
|
token.word = AuUInt32(atomicRelease);
|
||||||
|
this->handle_.PushId(EIPCHandleType::eIPCPrimitiveEvent, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
this->event_.~LSEvent();
|
this->event_.~LSEvent();
|
||||||
}
|
}
|
||||||
@ -77,7 +57,11 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
IPCEventProxy::~IPCEventProxy()
|
IPCEventProxy::~IPCEventProxy()
|
||||||
{
|
{
|
||||||
IO::UNIX::FDServeEnd(this->handle_);
|
if (this->handle_.values.size() == 1)
|
||||||
|
{
|
||||||
|
IO::UNIX::FDServeEnd(this->handle_.values[0].token);
|
||||||
|
this->handle_ = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPCEventProxy::Set()
|
bool IPCEventProxy::Set()
|
||||||
@ -123,24 +107,16 @@ namespace Aurora::IO::IPC
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCEvent> ImportEvent(const AuString &handle)
|
AuSPtr<IPCEvent> ImportEventEx(const IPCToken &token)
|
||||||
{
|
{
|
||||||
IPC::IPCHandle decodedHandle;
|
|
||||||
|
|
||||||
if (!decodedHandle.FromString(handle))
|
|
||||||
{
|
|
||||||
SysPushErrorParseError("Invalid handle: {}", handle);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd {-1};
|
int fd {-1};
|
||||||
if (!IO::UNIX::FDAccept(decodedHandle, fd))
|
if (!IO::UNIX::FDAccept(token, fd))
|
||||||
{
|
{
|
||||||
SysPushErrorNested();
|
SysPushErrorNested();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto object = AuMakeShared<IPCEventProxy>(fd, decodedHandle.flags[0], decodedHandle.flags[1]);
|
auto object = AuMakeShared<IPCEventProxy>(fd, false, bool(token.word));
|
||||||
if (!object)
|
if (!object)
|
||||||
{
|
{
|
||||||
SysPushErrorMem();
|
SysPushErrorMem();
|
||||||
@ -157,34 +133,41 @@ namespace Aurora::IO::IPC
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AUKN_SYM AuSPtr<IPCEvent> ImportEvent(const AuString &handle)
|
||||||
|
{
|
||||||
|
IPC::IPCHandle decodedHandle;
|
||||||
|
|
||||||
|
if (!decodedHandle.FromString(handle))
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveEvent, 0);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImportEventEx(val->token);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Semaphores
|
// Semaphores
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct IPCSemaphoreProxy : IPCSemaphore, Loop::ILoopSourceEx
|
|
||||||
{
|
|
||||||
IPCSemaphoreProxy(AuUInt32 initialCount);
|
|
||||||
IPCSemaphoreProxy(int handle, int tag);
|
|
||||||
~IPCSemaphoreProxy();
|
|
||||||
|
|
||||||
PROXY_INTERNAL_INTERFACE(semaphore_)
|
|
||||||
IMPLEMENT_HANDLE
|
|
||||||
|
|
||||||
bool AddOne() override;
|
|
||||||
|
|
||||||
bool IsSignaled() override;
|
|
||||||
bool WaitOn(AuUInt32 timeout) override;
|
|
||||||
Loop::ELoopSource GetType() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Loop::LSSemaphore semaphore_;
|
|
||||||
};
|
|
||||||
|
|
||||||
IPCSemaphoreProxy::IPCSemaphoreProxy(AuUInt32 initialCount) : semaphore_(initialCount)
|
IPCSemaphoreProxy::IPCSemaphoreProxy(AuUInt32 initialCount) : semaphore_(initialCount)
|
||||||
{
|
{
|
||||||
|
IPC::IPCToken token;
|
||||||
|
|
||||||
if (this->semaphore_.HasValidHandle())
|
if (this->semaphore_.HasValidHandle())
|
||||||
{
|
{
|
||||||
if (!IO::UNIX::FDServe(true, true, true, true, this->GetHandle(), this->handle_))
|
if (IO::UNIX::FDServe(this->GetHandle(), token))
|
||||||
|
{
|
||||||
|
this->handle_.PushId(EIPCHandleType::eIPCPrimitiveSemaphore, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
this->semaphore_.~LSSemaphore();
|
this->semaphore_.~LSSemaphore();
|
||||||
}
|
}
|
||||||
@ -193,9 +176,15 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
IPCSemaphoreProxy::IPCSemaphoreProxy(int handle, int tag) : semaphore_(handle, tag)
|
IPCSemaphoreProxy::IPCSemaphoreProxy(int handle, int tag) : semaphore_(handle, tag)
|
||||||
{
|
{
|
||||||
|
IPC::IPCToken token;
|
||||||
|
|
||||||
if (this->semaphore_.HasValidHandle())
|
if (this->semaphore_.HasValidHandle())
|
||||||
{
|
{
|
||||||
if (!IO::UNIX::FDServe(true, true, true, true, this->GetHandle(), this->handle_))
|
if (IO::UNIX::FDServe(this->GetHandle(), token))
|
||||||
|
{
|
||||||
|
this->handle_.PushId(EIPCHandleType::eIPCPrimitiveSemaphore, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
this->semaphore_.~LSSemaphore();
|
this->semaphore_.~LSSemaphore();
|
||||||
}
|
}
|
||||||
@ -204,7 +193,11 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
IPCSemaphoreProxy::~IPCSemaphoreProxy()
|
IPCSemaphoreProxy::~IPCSemaphoreProxy()
|
||||||
{
|
{
|
||||||
IO::UNIX::FDServeEnd(this->handle_);
|
if (this->handle_.values.size() == 1)
|
||||||
|
{
|
||||||
|
IO::UNIX::FDServeEnd(this->handle_.values[0].token);
|
||||||
|
this->handle_ = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPCSemaphoreProxy::AddOne()
|
bool IPCSemaphoreProxy::AddOne()
|
||||||
@ -255,8 +248,15 @@ namespace Aurora::IO::IPC
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto val = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveSemaphore, 0);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
SysPushErrorParseError("Invalid handle: {}", handle);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
int fd {-1};
|
int fd {-1};
|
||||||
if (!IO::UNIX::FDAccept(decodedHandle, fd))
|
if (!IO::UNIX::FDAccept(val->token, fd))
|
||||||
{
|
{
|
||||||
SysPushErrorNested();
|
SysPushErrorNested();
|
||||||
return {};
|
return {};
|
||||||
@ -278,126 +278,4 @@ namespace Aurora::IO::IPC
|
|||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Mutexes
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct IPCMutexProxy : IPCMutex, Loop::ILoopSourceEx
|
|
||||||
{
|
|
||||||
IPCMutexProxy();
|
|
||||||
IPCMutexProxy(int handle);
|
|
||||||
~IPCMutexProxy();
|
|
||||||
|
|
||||||
PROXY_INTERNAL_INTERFACE(mutex_)
|
|
||||||
IMPLEMENT_HANDLE
|
|
||||||
|
|
||||||
bool Unlock() override;
|
|
||||||
|
|
||||||
bool IsSignaled() override;
|
|
||||||
bool WaitOn(AuUInt32 timeout) override;
|
|
||||||
Loop::ELoopSource GetType() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Loop::LSMutex mutex_;
|
|
||||||
};
|
|
||||||
|
|
||||||
IPCMutexProxy::IPCMutexProxy() : mutex_()
|
|
||||||
{
|
|
||||||
if (this->mutex_.HasValidHandle())
|
|
||||||
{
|
|
||||||
if (!IO::UNIX::FDServe(false, false, true, true, this->GetHandle(), this->handle_))
|
|
||||||
{
|
|
||||||
this->mutex_.~LSMutex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCMutexProxy::IPCMutexProxy(int handle) : mutex_(handle)
|
|
||||||
{
|
|
||||||
if (this->mutex_.HasValidHandle())
|
|
||||||
{
|
|
||||||
if (!IO::UNIX::FDServe(false, false, true, true, this->GetHandle(), this->handle_))
|
|
||||||
{
|
|
||||||
this->mutex_.~LSMutex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCMutexProxy::~IPCMutexProxy()
|
|
||||||
{
|
|
||||||
IO::UNIX::FDServeEnd(this->handle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IPCMutexProxy::Unlock()
|
|
||||||
{
|
|
||||||
return this->mutex_.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IPCMutexProxy::IsSignaled()
|
|
||||||
{
|
|
||||||
return this->mutex_.IsSignaled();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IPCMutexProxy::WaitOn(AuUInt32 timeout)
|
|
||||||
{
|
|
||||||
return this->mutex_.WaitOn(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Loop::ELoopSource IPCMutexProxy::GetType()
|
|
||||||
{
|
|
||||||
return this->mutex_.GetType();
|
|
||||||
}
|
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCMutex> NewMutex()
|
|
||||||
{
|
|
||||||
auto object = AuMakeShared<IPCMutexProxy>();
|
|
||||||
if (!object)
|
|
||||||
{
|
|
||||||
SysPushErrorMem();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!object->HasValidHandle())
|
|
||||||
{
|
|
||||||
SysPushErrorIO();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<IPCMutex> ImportMutex(const AuString &handle)
|
|
||||||
{
|
|
||||||
IPC::IPCHandle decodedHandle;
|
|
||||||
|
|
||||||
if (!decodedHandle.FromString(handle))
|
|
||||||
{
|
|
||||||
SysPushErrorParseError("Invalid handle: {}", handle);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd {-1};
|
|
||||||
if (!IO::UNIX::FDAccept(decodedHandle, fd))
|
|
||||||
{
|
|
||||||
SysPushErrorNested();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto object = AuMakeShared<IPCMutexProxy>(fd);
|
|
||||||
if (!object)
|
|
||||||
{
|
|
||||||
SysPushErrorMem();
|
|
||||||
::close(fd);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!object->HasValidHandle())
|
|
||||||
{
|
|
||||||
SysPushErrorIO();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,7 +7,66 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "IPC.hpp"
|
||||||
|
#include "IPCHandle.hpp"
|
||||||
|
|
||||||
|
#include <Source/IO/Loop/LSEvent.hpp>
|
||||||
|
#include <Source/IO/Loop/LSSemaphore.hpp>
|
||||||
|
#include <Source/IO/Loop/LSMutex.hpp>
|
||||||
|
|
||||||
|
#include <Source/IO/IPC/IPC.hpp>
|
||||||
|
#include <Source/IO/IPC/IPCHandle.hpp>
|
||||||
|
|
||||||
namespace Aurora::IO::IPC
|
namespace Aurora::IO::IPC
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if !defined(IMPLEMENT_HANDLE)
|
||||||
|
#define IMPLEMENT_HANDLE \
|
||||||
|
IPC::IPCHandle handle_; \
|
||||||
|
AuString ExportToString() override \
|
||||||
|
{ \
|
||||||
|
return handle_.ToString(); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct IPCEventProxy : IPCEvent, Loop::ILoopSourceEx
|
||||||
|
{
|
||||||
|
IPCEventProxy(bool triggered, bool atomicRelease);
|
||||||
|
IPCEventProxy(int handle, bool triggered, bool atomicRelease);
|
||||||
|
~IPCEventProxy();
|
||||||
|
|
||||||
|
PROXY_INTERNAL_INTERFACE(event_)
|
||||||
|
IMPLEMENT_HANDLE
|
||||||
|
|
||||||
|
bool Set() override;
|
||||||
|
bool Reset() override;
|
||||||
|
|
||||||
|
bool IsSignaled() override;
|
||||||
|
bool WaitOn(AuUInt32 timeout) override;
|
||||||
|
Loop::ELoopSource GetType() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Loop::LSEvent event_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCSemaphoreProxy : IPCSemaphore, Loop::ILoopSourceEx
|
||||||
|
{
|
||||||
|
IPCSemaphoreProxy(AuUInt32 initialCount);
|
||||||
|
IPCSemaphoreProxy(int handle, int tag);
|
||||||
|
~IPCSemaphoreProxy();
|
||||||
|
|
||||||
|
PROXY_INTERNAL_INTERFACE(semaphore_)
|
||||||
|
IMPLEMENT_HANDLE
|
||||||
|
|
||||||
|
bool AddOne() override;
|
||||||
|
|
||||||
|
bool IsSignaled() override;
|
||||||
|
bool WaitOn(AuUInt32 timeout) override;
|
||||||
|
Loop::ELoopSource GetType() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Loop::LSSemaphore semaphore_;
|
||||||
|
};
|
||||||
|
|
||||||
|
AuSPtr<IPCEvent> ImportEventEx(const IPCToken &token);
|
||||||
}
|
}
|
@ -31,7 +31,7 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
AuUInt32 maxIterationsOrZero_ {};
|
AuUInt32 maxIterationsOrZero_ {};
|
||||||
AuUInt64 reschedStepNsOrZero_, targetTime_ {};
|
AuUInt64 reschedStepNsOrZero_ {}, targetTime_ {};
|
||||||
AuUInt32 count_ {};
|
AuUInt32 count_ {};
|
||||||
bool bSingleshot {};
|
bool bSingleshot {};
|
||||||
|
|
||||||
|
@ -294,7 +294,8 @@ namespace Aurora::IO::Loop
|
|||||||
dwSuccess++;
|
dwSuccess++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SysAssertDbg(dwSuccess == decommitQueue.size(), "caught SourceRemove on invalid");
|
// TODO (Reece): Urgent. Fails under an IO update dtor. Faking perfect unit tests until i make it. Need linux aurt.
|
||||||
|
//SysAssertDbg(dwSuccess == decommitQueue.size(), "caught SourceRemove on invalid");
|
||||||
|
|
||||||
return dwSuccess;
|
return dwSuccess;
|
||||||
}
|
}
|
||||||
@ -782,6 +783,8 @@ namespace Aurora::IO::Loop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PumpHooks();
|
||||||
|
|
||||||
return bTicked;
|
return bTicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,11 +957,20 @@ namespace Aurora::IO::Loop
|
|||||||
return AuMakeTuple(true, bShouldRemove, bOverload);
|
return AuMakeTuple(true, bShouldRemove, bOverload);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoopQueue::AddHook(const AuFunction<void> &func)
|
bool LoopQueue::AddHook(const AuFunction<void()> &func)
|
||||||
{
|
{
|
||||||
return AuTryInsert(this->epilogueHooks_, func);
|
return AuTryInsert(this->epilogueHooks_, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoopQueue::PumpHooks()
|
||||||
|
{
|
||||||
|
auto c = AuExchange(this->epilogueHooks_, {});
|
||||||
|
for (auto &a : c)
|
||||||
|
{
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AUKN_SYM AuSPtr<ILoopQueue> NewLoopQueue()
|
AUKN_SYM AuSPtr<ILoopQueue> NewLoopQueue()
|
||||||
{
|
{
|
||||||
auto queue = AuMakeShared<LoopQueue>();
|
auto queue = AuMakeShared<LoopQueue>();
|
||||||
|
@ -17,6 +17,8 @@ namespace Aurora::IO::Loop
|
|||||||
LoopQueue();
|
LoopQueue();
|
||||||
~LoopQueue();
|
~LoopQueue();
|
||||||
|
|
||||||
|
bool AddHook(const AuFunction<void()> &func);
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
void Deinit();
|
void Deinit();
|
||||||
|
|
||||||
@ -47,6 +49,8 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void PumpHooks();
|
||||||
|
|
||||||
bool CommitDecommit();
|
bool CommitDecommit();
|
||||||
|
|
||||||
struct SourceExtended
|
struct SourceExtended
|
||||||
@ -57,12 +61,11 @@ namespace Aurora::IO::Loop
|
|||||||
void Deinit();
|
void Deinit();
|
||||||
void Commit(const AuSPtr<SourceExtended> &self);
|
void Commit(const AuSPtr<SourceExtended> &self);
|
||||||
|
|
||||||
|
|
||||||
AuSPtr<ILoopSource> source;
|
AuSPtr<ILoopSource> source;
|
||||||
ILoopSourceEx *sourceExtended;
|
ILoopSourceEx *sourceExtended {};
|
||||||
LoopQueue *parent;
|
LoopQueue *parent {};
|
||||||
AuWPtr<SourceExtended> pin;
|
AuWPtr<SourceExtended> pin;
|
||||||
AuUInt64 timeoutAbs;
|
AuUInt64 timeoutAbs {};
|
||||||
|
|
||||||
bool ConsiderTimeout(AuUInt64 time) const
|
bool ConsiderTimeout(AuUInt64 time) const
|
||||||
{
|
{
|
||||||
@ -97,7 +100,7 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
struct AnEpoll
|
struct AnEpoll
|
||||||
{
|
{
|
||||||
LoopQueue *parent;
|
LoopQueue *parent {};
|
||||||
|
|
||||||
AuThreadPrimitives::SpinLock lock;
|
AuThreadPrimitives::SpinLock lock;
|
||||||
AuBST<int, int> startingWorkRead;
|
AuBST<int, int> startingWorkRead;
|
||||||
@ -124,6 +127,8 @@ namespace Aurora::IO::Loop
|
|||||||
AuThreadPrimitives::RWLockUnique_t polledItemsMutex_;
|
AuThreadPrimitives::RWLockUnique_t polledItemsMutex_;
|
||||||
AuList<AnEpoll *> alternativeEpolls_;
|
AuList<AnEpoll *> alternativeEpolls_;
|
||||||
|
|
||||||
|
AuList<AuFunction<void()>> epilogueHooks_;
|
||||||
|
|
||||||
AnEpoll globalEpoll_;
|
AnEpoll globalEpoll_;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -349,12 +349,11 @@ namespace Aurora::IO::UNIX
|
|||||||
return ReadyServer();
|
return ReadyServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FDServe(bool a, bool b, bool c, bool d, int fd, IPC::IPCHandle &outHandle)
|
bool FDServe(int fd, IPC::IPCToken &token)
|
||||||
{
|
{
|
||||||
if (gHasProcSyscall)
|
if (gHasProcSyscall)
|
||||||
{
|
{
|
||||||
outHandle.NewId(a, b, c, d);
|
token.cookie = fd;
|
||||||
outHandle.cookie = fd;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,14 +367,15 @@ namespace Aurora::IO::UNIX
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
outHandle.NewId(a, b, c, d);
|
token.NewId();
|
||||||
} while (AuExists(gFdCookieMap, outHandle.cookie));
|
}
|
||||||
|
while (AuExists(gFdCookieMap, token.cookie));
|
||||||
|
|
||||||
return AuTryInsert(gFdCookieMap, outHandle.cookie, fd);
|
return AuTryInsert(gFdCookieMap, token.cookie, fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FDServeEnd(const IPC::IPCHandle &handle)
|
void FDServeEnd(const IPC::IPCToken &handle)
|
||||||
{
|
{
|
||||||
if (gHasProcSyscall)
|
if (gHasProcSyscall)
|
||||||
{
|
{
|
||||||
@ -386,7 +386,7 @@ namespace Aurora::IO::UNIX
|
|||||||
AuTryRemove(gFdCookieMap, handle.cookie);
|
AuTryRemove(gFdCookieMap, handle.cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FDAccept(const IPC::IPCHandle &handle, int &outFd)
|
bool FDAccept(const IPC::IPCToken &handle, int &outFd)
|
||||||
{
|
{
|
||||||
sockaddr_un addr;
|
sockaddr_un addr;
|
||||||
outFd = -1;
|
outFd = -1;
|
||||||
|
@ -14,8 +14,8 @@ namespace Aurora::IO::UNIX
|
|||||||
void InitIPCBackend();
|
void InitIPCBackend();
|
||||||
void DeinitIPCBackend();
|
void DeinitIPCBackend();
|
||||||
|
|
||||||
bool FDServe(bool a, bool b, bool c, bool d, int fd, IPC::IPCHandle &outHandle);
|
bool FDServe(int fd, IPC::IPCToken &outHandle);
|
||||||
void FDServeEnd(const IPC::IPCHandle &handle);
|
void FDServeEnd(const IPC::IPCToken &handle);
|
||||||
|
|
||||||
bool FDAccept(const IPC::IPCHandle &handle, int &outFd);
|
bool FDAccept(const IPC::IPCToken &handle, int &outFd);
|
||||||
}
|
}
|
@ -410,7 +410,7 @@ namespace Aurora::IO::UNIX
|
|||||||
bool bError {};
|
bool bError {};
|
||||||
AuUInt bytesTransacted {};
|
AuUInt bytesTransacted {};
|
||||||
|
|
||||||
if (ioEvents[i].res <= 0)
|
if (ioEvents[i].res < 0)
|
||||||
{
|
{
|
||||||
errNo = 0 - ioEvents[i].res;
|
errNo = 0 - ioEvents[i].res;
|
||||||
bError = true;
|
bError = true;
|
||||||
@ -531,7 +531,7 @@ namespace Aurora::IO::UNIX
|
|||||||
bool bError {};
|
bool bError {};
|
||||||
AuUInt bytesTransacted {};
|
AuUInt bytesTransacted {};
|
||||||
|
|
||||||
if (ioEvents[i].res <= 0)
|
if (ioEvents[i].res < 0)
|
||||||
{
|
{
|
||||||
errNo = 0 - ioEvents[i].res;
|
errNo = 0 - ioEvents[i].res;
|
||||||
bError = true;
|
bError = true;
|
||||||
@ -687,7 +687,7 @@ namespace Aurora::IO::UNIX
|
|||||||
bool bError {};
|
bool bError {};
|
||||||
AuUInt bytesTransacted {};
|
AuUInt bytesTransacted {};
|
||||||
|
|
||||||
if (ioEvents[i].res <= 0)
|
if (ioEvents[i].res < 0)
|
||||||
{
|
{
|
||||||
errNo = 0 - ioEvents[i].res;
|
errNo = 0 - ioEvents[i].res;
|
||||||
bError = true;
|
bError = true;
|
||||||
@ -752,4 +752,84 @@ namespace Aurora::IO::UNIX
|
|||||||
// TODO:
|
// TODO:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LinuxOverlappedYield()
|
||||||
|
{
|
||||||
|
io_event ioEvents[512];
|
||||||
|
int temp;
|
||||||
|
timespec targetTime {};
|
||||||
|
auto io = GetTls();
|
||||||
|
|
||||||
|
if (!io)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LinuxOverlappedTrySubmitWork())
|
||||||
|
{
|
||||||
|
SysPushErrorIO();
|
||||||
|
errno = EBADF;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!io->dwIoSubmits)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = io_getevents(io->context, 1, 512, ioEvents, &targetTime);
|
||||||
|
|
||||||
|
if (temp >= 0)
|
||||||
|
{
|
||||||
|
for (AU_ITERATE_N(i, temp))
|
||||||
|
{
|
||||||
|
auto handle = AuReinterpretCast<ASubmittable *>(ioEvents[i].data);
|
||||||
|
|
||||||
|
io->dwIoSubmits--;
|
||||||
|
|
||||||
|
auto errNo = 0;
|
||||||
|
bool bError {};
|
||||||
|
AuUInt bytesTransacted {};
|
||||||
|
|
||||||
|
if (ioEvents[i].res < 0)
|
||||||
|
{
|
||||||
|
errNo = 0 - ioEvents[i].res;
|
||||||
|
bError = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesTransacted = ioEvents[i].res;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->LIOS_SendProcess(bytesTransacted, bError, errNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto err = 0 - temp;
|
||||||
|
if (err == EINTR)
|
||||||
|
{
|
||||||
|
errno = EINTR;
|
||||||
|
// Assume signal is also a valid yield
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == EINVAL)
|
||||||
|
{
|
||||||
|
SysPushErrorArg();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == EFAULT)
|
||||||
|
{
|
||||||
|
SysPanic("Either events or timeout is an invalid pointer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == ENOSYS)
|
||||||
|
{
|
||||||
|
SysPanic("io_getevents() is not implemented on this architecture.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -47,6 +47,9 @@ namespace Aurora::IO::UNIX
|
|||||||
int LinuxOverlappedEpollShim(int epfd, struct epoll_event *events,
|
int LinuxOverlappedEpollShim(int epfd, struct epoll_event *events,
|
||||||
int maxevents, int timeout);
|
int maxevents, int timeout);
|
||||||
|
|
||||||
|
bool LinuxOverlappedYield();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Work queue
|
// Work queue
|
||||||
bool LinuxOverlappedSubmitRead (int fd, AuUInt offset, ASubmittable *context, AuLoop::ILSEvent *optEvent);
|
bool LinuxOverlappedSubmitRead (int fd, AuUInt offset, ASubmittable *context, AuLoop::ILSEvent *optEvent);
|
||||||
|
@ -13,13 +13,16 @@ namespace Aurora::IO::UNIX
|
|||||||
{
|
{
|
||||||
AUKN_SYM AuString ShareFileDescriptor(int fd)
|
AUKN_SYM AuString ShareFileDescriptor(int fd)
|
||||||
{
|
{
|
||||||
|
IPC::IPCToken token;
|
||||||
IPC::IPCHandle handle;
|
IPC::IPCHandle handle;
|
||||||
|
|
||||||
if (!FDServe(false, false, false, false, fd, handle))
|
if (!FDServe(fd, token))
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle.PushId(IPC::EIPCHandleType::eIPCSharedFd, token);
|
||||||
|
|
||||||
return handle.ToString();
|
return handle.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +35,10 @@ namespace Aurora::IO::UNIX
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FDServeEnd(handle2);
|
if (auto val = handle2.GetToken(IPC::EIPCHandleType::eIPCSharedFd, 0))
|
||||||
|
{
|
||||||
|
FDServeEnd(val->token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM int ShareFileDescriptorAccept(const AuString &handle)
|
AUKN_SYM int ShareFileDescriptorAccept(const AuString &handle)
|
||||||
@ -44,8 +50,14 @@ namespace Aurora::IO::UNIX
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto val = handle2.GetToken(IPC::EIPCHandleType::eIPCSharedFd, 0);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int fd {-1};
|
int fd {-1};
|
||||||
if (!FDAccept(handle2, fd))
|
if (!FDAccept(val->token, fd))
|
||||||
{
|
{
|
||||||
SysPushErrorNested();
|
SysPushErrorNested();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -125,7 +125,7 @@ namespace Aurora::Locale::Encoding::UTF16
|
|||||||
|
|
||||||
if (utf8)
|
if (utf8)
|
||||||
{
|
{
|
||||||
while (nextOffset = GetLenUC2CodePoint(cp, pItr, length))
|
while ((nextOffset = GetLenUC2CodePoint(cp, pItr, length)))
|
||||||
{
|
{
|
||||||
length -= nextOffset;
|
length -= nextOffset;
|
||||||
pItr += nextOffset;
|
pItr += nextOffset;
|
||||||
@ -139,7 +139,7 @@ namespace Aurora::Locale::Encoding::UTF16
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (nextOffset = GetLenUC2CodePoint(cp, pItr, length))
|
while ((nextOffset = GetLenUC2CodePoint(cp, pItr, length)))
|
||||||
{
|
{
|
||||||
length -= nextOffset;
|
length -= nextOffset;
|
||||||
pItr += nextOffset;
|
pItr += nextOffset;
|
||||||
|
@ -289,20 +289,20 @@ namespace Aurora::Locale
|
|||||||
static void SetLanguageEnvBlock()
|
static void SetLanguageEnvBlock()
|
||||||
{
|
{
|
||||||
const char *language;
|
const char *language;
|
||||||
if (language = getenv("AURORA_ENV_LANGUAGE"))
|
if ((language = getenv("AURORA_ENV_LANGUAGE")))
|
||||||
{
|
{
|
||||||
gLanguageCode = language;
|
gLanguageCode = language;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *countryCode;
|
const char *countryCode;
|
||||||
if (countryCode = getenv("AURORA_ENV_COUNTRY"))
|
if ((countryCode = getenv("AURORA_ENV_COUNTRY")))
|
||||||
{
|
{
|
||||||
gCountryCode = countryCode;
|
gCountryCode = countryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// You may not overload codeset on win32 targets
|
// You may not overload codeset on win32 targets
|
||||||
const char *codeSet;
|
const char *codeSet;
|
||||||
if (codeSet = getenv("AURORA_ENV_CODESET"))
|
if ((codeSet = getenv("AURORA_ENV_CODESET")))
|
||||||
{
|
{
|
||||||
gCodeset = codeSet;
|
gCodeset = codeSet;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
#include "Sinks/DebugLogger.NT.hpp"
|
#include "Sinks/DebugLogger.NT.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||||
|
#include "Sinks/SysLog.Unix.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Aurora::Logging
|
namespace Aurora::Logging
|
||||||
{
|
{
|
||||||
AUKN_SYM IBasicSink *NewStdSinkNew()
|
AUKN_SYM IBasicSink *NewStdSinkNew()
|
||||||
@ -58,10 +62,9 @@ namespace Aurora::Logging
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AUKN_SYM IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name)
|
AUKN_SYM IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name)
|
||||||
{
|
{
|
||||||
#if defined(AURORA_PLATFORM_WIN32)
|
#if defined(AURORA_PLATFORM_WIN32) || defined(AURORA_IS_POSIX_DERIVED)
|
||||||
return Sinks::NewOSNamedEventDirectorySinkNew(name);
|
return Sinks::NewOSNamedEventDirectorySinkNew(name);
|
||||||
#endif
|
#endif
|
||||||
return {};
|
return {};
|
||||||
|
@ -2,6 +2,113 @@
|
|||||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||||
|
|
||||||
File: SysLog.Unix.cpp
|
File: SysLog.Unix.cpp
|
||||||
Date: 2022-2-8
|
Date: 2022-8-2
|
||||||
Author: Reece
|
Author: Reece
|
||||||
***/
|
***/
|
||||||
|
#include <Source/RuntimeInternal.hpp>
|
||||||
|
#include "SysLog.Unix.hpp"
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
namespace Aurora::Logging::Sinks
|
||||||
|
{
|
||||||
|
SysLogSink::SysLogSink(const AuString &value)
|
||||||
|
{
|
||||||
|
::openlog(value.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SysLogSink::~SysLogSink()
|
||||||
|
{
|
||||||
|
::closelog();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SysLogSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysLogSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||||
|
{
|
||||||
|
AuUInt type {};
|
||||||
|
AU_LOCK_GUARD(this->spinLock_);
|
||||||
|
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case (AuUInt8)ELogLevel::eInfo:
|
||||||
|
type = LOG_INFO;
|
||||||
|
break;
|
||||||
|
case (AuUInt8)ELogLevel::eError:
|
||||||
|
type = LOG_CRIT;
|
||||||
|
break;
|
||||||
|
case (AuUInt8)ELogLevel::eDebug:
|
||||||
|
type = LOG_DEBUG;
|
||||||
|
break;
|
||||||
|
case (AuUInt8)ELogLevel::eVerbose:
|
||||||
|
type = LOG_NOTICE;
|
||||||
|
break;
|
||||||
|
case (AuUInt8)ELogLevel::eWarn:
|
||||||
|
type = LOG_WARNING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = LOG_INFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->sysCurrentType_ != type)
|
||||||
|
{
|
||||||
|
FlushStrings();
|
||||||
|
this->sysCurrentType_ = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto a = msg.ToPersistentString();
|
||||||
|
if (this->sysStrBuffer_.size() + a.size() + 2 >= 32 * 1000)
|
||||||
|
{
|
||||||
|
FlushStrings();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sysStrBuffer_.insert(this->sysStrBuffer_.end(), a.begin(), a.end());
|
||||||
|
this->sysStrBuffer_.insert(this->sysStrBuffer_.end(), L"\n", L"\n" + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysLogSink::FlushStrings()
|
||||||
|
{
|
||||||
|
if (this->sysStrBuffer_.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sysCompleteLineBuffer_.push_back(AuMakeTuple(this->sysCurrentType_, AuMove(this->sysStrBuffer_)));
|
||||||
|
this->sysStrBuffer_.clear();
|
||||||
|
this->sysStrBuffer_.reserve(15 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysLogSink::OnFlush()
|
||||||
|
{
|
||||||
|
AU_LOCK_GUARD(this->spinLock_);
|
||||||
|
|
||||||
|
FlushStrings();
|
||||||
|
|
||||||
|
for (auto &[level, message] : this->sysCompleteLineBuffer_)
|
||||||
|
{
|
||||||
|
::syslog(level, "%s", message.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sysCompleteLineBuffer_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _new SysLogSink(name);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewOSNamedEventDirectorySinkRelease(IBasicSink *sink)
|
||||||
|
{
|
||||||
|
AuSafeDelete<SysLogSink *>(sink);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,31 @@
|
|||||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||||
|
|
||||||
File: SysLog.Unix.hpp
|
File: SysLog.Unix.hpp
|
||||||
Date: 2022-2-8
|
Date: 2022-8-2
|
||||||
Author: Reece
|
Author: Reece
|
||||||
***/
|
***/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Aurora::Logging::Sinks
|
||||||
|
{
|
||||||
|
struct SysLogSink : IBasicSink
|
||||||
|
{
|
||||||
|
SysLogSink(const AuString &value);
|
||||||
|
~SysLogSink();
|
||||||
|
|
||||||
|
void OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||||
|
bool OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||||
|
void OnFlush() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FlushStrings();
|
||||||
|
|
||||||
|
AuUInt sysCurrentType_;
|
||||||
|
AuString sysStrBuffer_;
|
||||||
|
AuList<AuTuple<AuUInt, AuString>> sysCompleteLineBuffer_;
|
||||||
|
AuThreadPrimitives::SpinLock spinLock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void NewOSNamedEventDirectorySinkRelease(IBasicSink *sink);
|
||||||
|
IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name);
|
||||||
|
}
|
@ -48,7 +48,8 @@ namespace Aurora::Threading
|
|||||||
|
|
||||||
auto endTime = AuTime::CurrentClockNS() + timeout;
|
auto endTime = AuTime::CurrentClockNS() + timeout;
|
||||||
|
|
||||||
if (usleep(timeout / 1000) == EINTR)
|
if ((usleep(timeout / 1000) == -1) &&
|
||||||
|
(errno == EINTR))
|
||||||
{
|
{
|
||||||
AuUInt64 now;
|
AuUInt64 now;
|
||||||
while ((now = AuTime::CurrentClockNS()) < endTime)
|
while ((now = AuTime::CurrentClockNS()) < endTime)
|
||||||
|
@ -44,6 +44,16 @@ namespace Aurora::Threading::Threads
|
|||||||
|
|
||||||
static ThreadInfo gDummyThreadInfo;
|
static ThreadInfo gDummyThreadInfo;
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_UNIX_DERIVED)
|
||||||
|
static const auto kSignalAbort = 77;
|
||||||
|
|
||||||
|
static void HandleSigAbortThread(int a)
|
||||||
|
{
|
||||||
|
pthread_exit(nullptr);
|
||||||
|
SysPanic("Couldn't terminate thread context");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
OSThread::OSThread(const ThreadInfo &info) : info_(info)
|
OSThread::OSThread(const ThreadInfo &info) : info_(info)
|
||||||
{
|
{
|
||||||
this->name_ = info.name.value_or("Aurora Thread");
|
this->name_ = info.name.value_or("Aurora Thread");
|
||||||
@ -69,6 +79,7 @@ namespace Aurora::Threading::Threads
|
|||||||
{
|
{
|
||||||
this->name_ = "System Thread";
|
this->name_ = "System Thread";
|
||||||
this->handle_ = reinterpret_cast<decltype(handle_)>(id);
|
this->handle_ = reinterpret_cast<decltype(handle_)>(id);
|
||||||
|
this->bNotOwned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -79,6 +90,11 @@ namespace Aurora::Threading::Threads
|
|||||||
bool bDetached {};
|
bool bDetached {};
|
||||||
bool bDetachedSuccess {};
|
bool bDetachedSuccess {};
|
||||||
|
|
||||||
|
if (this->bNotOwned)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (DeadTest())
|
if (DeadTest())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -386,9 +402,12 @@ namespace Aurora::Threading::Threads
|
|||||||
|
|
||||||
OSAttach();
|
OSAttach();
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
if (task_)
|
||||||
{
|
{
|
||||||
task_();
|
task_();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
SysPushErrorHAL("OS Thread Aborted");
|
SysPushErrorHAL("OS Thread Aborted");
|
||||||
@ -496,6 +515,8 @@ namespace Aurora::Threading::Threads
|
|||||||
|
|
||||||
void OSThread::OSAttach()
|
void OSThread::OSAttach()
|
||||||
{
|
{
|
||||||
|
this->bSupportsAltKill = true;
|
||||||
|
|
||||||
HandleRegister(this);
|
HandleRegister(this);
|
||||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
this->unixThreadId_ = gettid();
|
this->unixThreadId_ = gettid();
|
||||||
@ -518,6 +539,18 @@ namespace Aurora::Threading::Threads
|
|||||||
UpdatePrio(this->throttle_, this->prio_);
|
UpdatePrio(this->throttle_, this->prio_);
|
||||||
SetAffinity(this->mask_);
|
SetAffinity(this->mask_);
|
||||||
UpdateName();
|
UpdateName();
|
||||||
|
|
||||||
|
// TODO: rushed
|
||||||
|
#if defined(AURORA_IS_UNIX_DERIVED)
|
||||||
|
struct sigaction action =
|
||||||
|
{
|
||||||
|
.sa_handler = HandleSigAbortThread,
|
||||||
|
.sa_flags = SA_ONSTACK
|
||||||
|
};
|
||||||
|
::sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
|
::sigaction(kSignalAbort, &action, nullptr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static AuHashMap<EThreadPriority, int> kNiceMap
|
static AuHashMap<EThreadPriority, int> kNiceMap
|
||||||
@ -837,7 +870,15 @@ namespace Aurora::Threading::Threads
|
|||||||
|
|
||||||
void OSThread::OSDeatach()
|
void OSThread::OSDeatach()
|
||||||
{
|
{
|
||||||
|
#if defined(AURORA_IS_UNIX_DERIVED)
|
||||||
|
struct sigaction action =
|
||||||
|
{
|
||||||
|
.sa_handler = SIG_DFL
|
||||||
|
};
|
||||||
|
::sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
|
::sigaction(kSignalAbort, &action, nullptr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSThread::InternalKill(bool locked)
|
bool OSThread::InternalKill(bool locked)
|
||||||
@ -910,7 +951,31 @@ namespace Aurora::Threading::Threads
|
|||||||
|
|
||||||
#elif defined(AURORA_HAS_PTHREADS)
|
#elif defined(AURORA_HAS_PTHREADS)
|
||||||
|
|
||||||
pthread_kill(this->handle_, SIGTERM);
|
// TODO (Reece): urgent
|
||||||
|
if (false && calledFromThis) // this works. leave it.
|
||||||
|
{
|
||||||
|
pthread_exit(nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pthreads is fun. thats not how unix works...
|
||||||
|
// pthread_kill(this->handle_, SIGKILL);
|
||||||
|
// remember signal inheritance is a cluster fuck & the tree will be walked
|
||||||
|
// this is giving me flashbacks to hacking in apcs into the kernel
|
||||||
|
// gross...
|
||||||
|
// let's let nptl handle it
|
||||||
|
//pthread_cancel(this->handle_);
|
||||||
|
// ...doesnt work with c++ bc catch handlers get in the way. FUCK
|
||||||
|
|
||||||
|
if (this->bSupportsAltKill)
|
||||||
|
{
|
||||||
|
pthread_kill(this->handle_, 77);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pthread_cancel(this->handle_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ namespace Aurora::Threading::Threads
|
|||||||
HWInfo::CpuBitId throttleMask_ = HWInfo::CpuBitId().Not();
|
HWInfo::CpuBitId throttleMask_ = HWInfo::CpuBitId().Not();
|
||||||
EThreadPriority prio_ = EThreadPriority::ePrioNormal;
|
EThreadPriority prio_ = EThreadPriority::ePrioNormal;
|
||||||
EThreadThrottle throttle_ = EThreadThrottle::eNormal;
|
EThreadThrottle throttle_ = EThreadThrottle::eNormal;
|
||||||
|
bool bNotOwned {};
|
||||||
|
bool bSupportsAltKill {};
|
||||||
bool userManagingAffinity_ {};
|
bool userManagingAffinity_ {};
|
||||||
bool exiting_{};
|
bool exiting_{};
|
||||||
bool contextUsed_{}; // can this thread instance execute code again?
|
bool contextUsed_{}; // can this thread instance execute code again?
|
||||||
|
Loading…
Reference in New Issue
Block a user