[*] Begin resolving 8 months of Linux neglect

This commit is contained in:
Reece Wilson 2023-08-11 16:51:42 +01:00
parent 7100c807c8
commit 1f173a8799
47 changed files with 815 additions and 379 deletions

View File

@ -177,7 +177,7 @@ protected:
friend struct __detail::FutureAccessor; friend struct __detail::FutureAccessor;
CppFun<T>::B &GetValue() typename CppFun<T>::B &GetValue()
{ {
return value; return value;
} }
@ -316,7 +316,7 @@ private:
this->pid = AuAsync::GetCurrentWorkerPId(); this->pid = AuAsync::GetCurrentWorkerPId();
} }
CppFun<T>::B value; typename CppFun<T>::B value;
ErrorStore_t errorValue; ErrorStore_t errorValue;
AuThreadPrimitives::Mutex mutex; AuThreadPrimitives::Mutex mutex;

View File

@ -35,6 +35,22 @@ namespace Aurora::Threading::Primitives
static const auto kPrimitiveSize32NTCond = 20; static const auto kPrimitiveSize32NTCond = 20;
static const auto kPrimitiveSize32NTCondMutex = 8; static const auto kPrimitiveSize32NTCondMutex = 8;
static const auto kPrimitiveSize64LinuxMutex = 16;
static const auto kPrimitiveSize64LinuxSemaphore = 16;
static const auto kPrimitiveSize64LinuxCS = 128;
static const auto kPrimitiveSize64LinuxEvent = 152;
static const auto kPrimitiveSize64LinuxRWLock = 200;
static const auto kPrimitiveSize64LinuxCond = 88;
static const auto kPrimitiveSize64LinuxCondMutex = 48;
static const auto kPrimitiveSize32LinuxMutex = 8;
static const auto kPrimitiveSize32LinuxSemaphore = 8;
static const auto kPrimitiveSize32LinuxCS = 128;
static const auto kPrimitiveSize32LinuxEvent = 152;
static const auto kPrimitiveSize32LinuxRWLock = 200;
static const auto kPrimitiveSize32LinuxCond = 88;
static const auto kPrimitiveSize32LinuxCondMutex = 48;
// TODO: Other platforms... // TODO: Other platforms...
#else #else
@ -64,13 +80,33 @@ namespace Aurora::Threading::Primitives
#define AURT_ENABLE_HYPER_MUTEX #define AURT_ENABLE_HYPER_MUTEX
#elif defined(AURORA_PLATFORM_LINUX)
static const auto kPrimitiveSize64Mutex = kPrimitiveSize64LinuxMutex;
static const auto kPrimitiveSize64Semaphore = kPrimitiveSize64LinuxSemaphore;
static const auto kPrimitiveSize64CS = kPrimitiveSize64LinuxCS;
static const auto kPrimitiveSize64Event = kPrimitiveSize64LinuxEvent;
static const auto kPrimitiveSize64RWLock = kPrimitiveSize64LinuxRWLock;
static const auto kPrimitiveSize64Cond = kPrimitiveSize64LinuxCond;
static const auto kPrimitiveSize64CondMutex = kPrimitiveSize64LinuxCondMutex;
static const auto kPrimitiveSize32Mutex = kPrimitiveSize32LinuxMutex;
static const auto kPrimitiveSize32Semaphore = kPrimitiveSize32LinuxSemaphore;
static const auto kPrimitiveSize32CS = kPrimitiveSize32LinuxCS;
static const auto kPrimitiveSize32Event = kPrimitiveSize32LinuxEvent;
static const auto kPrimitiveSize32RWLock = kPrimitiveSize32LinuxRWLock;
static const auto kPrimitiveSize32Cond = kPrimitiveSize32LinuxCond;
static const auto kPrimitiveSize32CondMutex = kPrimitiveSize32LinuxCondMutex;
#define AURT_ENABLE_HYPER_MUTEX
#else #else
static const auto kPrimitiveSize64Mutex = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64Mutex = kDefaultPrimitiveSize64;
static const auto kPrimitiveSize64Semaphore = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64Semaphore = kDefaultPrimitiveSize64;
static const auto kPrimitiveSize64CS = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64CS = kDefaultPrimitiveSize64;
static const auto kPrimitiveSize64Event = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64Event = kDefaultPrimitiveSize64;
static const auto kPrimitiveSize64RWLock = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64RWLock = kDefaultPrimitiveSize64 * 2;
static const auto kPrimitiveSize64Cond = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64Cond = kDefaultPrimitiveSize64;
static const auto kPrimitiveSize64CondMutex = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64CondMutex = kDefaultPrimitiveSize64;

View File

@ -187,7 +187,10 @@ namespace Aurora::Async
void DeinitSched() void DeinitSched()
{ {
gThread->SendExitSignal(); if (gThread)
{
gThread->SendExitSignal();
}
gSchedCondvar->Broadcast(); gSchedCondvar->Broadcast();
gThread.reset(); gThread.reset();
} }

View File

@ -21,7 +21,6 @@ namespace Crypto
yarrow_start(&gPrng); yarrow_start(&gPrng);
gHashTiger = register_hash(&tiger_desc); gHashTiger = register_hash(&tiger_desc);
register_hash(&md5_desc);
gHashSha1 = register_hash(&sha1_desc); gHashSha1 = register_hash(&sha1_desc);
gHashSha256 = register_hash(&sha256_desc); gHashSha256 = register_hash(&sha256_desc);
gHashSha384 = register_hash(&sha384_desc); gHashSha384 = register_hash(&sha384_desc);

View File

@ -123,8 +123,9 @@ static void Pump()
::LinuxSuperSecretIOTick(); ::LinuxSuperSecretIOTick();
#endif #endif
#if defined(AURORA_PLATFORM_WIN32)
Aurora::Win32DropSchedulerResolution(); Aurora::Win32DropSchedulerResolution();
#endif
} }
static void RuntimeLateClean(); static void RuntimeLateClean();

View File

@ -197,7 +197,7 @@ namespace Aurora::Compression
{ {
size_t outNext {}; size_t outNext {};
uint8_t *pOut {}; uint8_t *pOut {};
while (outNext == 0 || BrotliEncoderHasMoreOutput(this->pState)); while (outNext == 0 || BrotliEncoderHasMoreOutput(this->pState))
{ {
auto [pMainDOut, uMainDOutLength] = this->GetDOutPair(); auto [pMainDOut, uMainDOutLength] = this->GetDOutPair();

View File

@ -10,12 +10,11 @@
namespace Aurora::Debug namespace Aurora::Debug
{ {
void PlatformHandleFatal(bool fatal) void PlatformHandleFatal(bool fatal, bool bNoExit)
{ {
} }
void InitUNIX() void InitUNIX()
{ {

View File

@ -39,10 +39,10 @@ namespace Aurora::Grug
pArrow->pCallback = pCallback; pArrow->pCallback = pCallback;
pArrow->pCallbackRunaway = pCallbackRunaway; pArrow->pCallbackRunaway = pCallbackRunaway;
#if defined(ARROW_NO_MUTEX) #if !defined(ARROW_NO_MUTEX)
SignalSafeSleepLockYield(&pArrow->spinSemaphore);
#else
SignalSafeSleepLockYield(pArrow->spinSemaphore2.AsPointer()); SignalSafeSleepLockYield(pArrow->spinSemaphore2.AsPointer());
#else
SignalSafeSleepLockYield(&pArrow->spinSemaphore);
#endif #endif
{ {
@ -113,7 +113,9 @@ namespace Aurora::Grug
auto lastCallback = last->pCallbackRunaway; auto lastCallback = last->pCallbackRunaway;
last->spinSemaphore.Unlock(); last->spinSemaphore.Unlock();
#if !defined(ARROW_NO_MUTEX)
last->spinSemaphore2->Unlock(); last->spinSemaphore2->Unlock();
#endif
gReservedArrows.pop_back(); gReservedArrows.pop_back();

View File

@ -93,6 +93,7 @@ namespace Aurora::IO
if (create.bDirectIOMode) if (create.bDirectIOMode)
{ {
dwFlags |= FILE_FLAG_NO_BUFFERING; dwFlags |= FILE_FLAG_NO_BUFFERING;
this->bDirectIOMode = true;
} }
if (!dwFlags) if (!dwFlags)

View File

@ -0,0 +1,174 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.Unix.cpp
Date: 2023-8-11
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "AuIOHandle.hpp"
#include "AuIOHandle.Unix.hpp"
#include "FS/FS.hpp"
#include "FS/FileAdvisory.Unix.hpp"
#include "FS/FileStream.Unix.hpp"
#include <fcntl.h>
namespace Aurora::IO
{
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess)
{
int fd = dup(uOSHandle);
if (fd < 0)
{
return 0;
}
return AuUInt64(fd);
}
void AFileHandle::CloseHandle(AuUInt64 uOSHandle)
{
int fd = (int)uOSHandle;
if (fd < 0)
{
return;
}
::close(fd);
}
struct UnixIOHandle final : AFileHandle
{
bool InitFromPath(HandleCreate create) override
{
int iFileDescriptor { -1 };
if (create.path.empty())
{
SysPushErrorArg("Cannot open an IO handle to the provided empty path");
return false;
}
if (!FS::EFileOpenModeIsValid(create.eMode))
{
SysPushErrorParam("Invalid open mode");
return false;
}
if (!FS::EFileAdvisoryLockLevelIsValid(create.eAdvisoryLevel))
{
SysPushErrorParam("Invalid lock mode");
return false;
}
auto pathex = FS::NormalizePathRet(create.path);
if (pathex.empty())
{
SysPushErrorMemory();
return false;
}
if (create.bAsyncHandle ||
create.bDirectIOMode)
{
this->bDirectIO = true;
}
switch (create.eMode)
{
case FS::EFileOpenMode::eRead:
{
break;
}
case FS::EFileOpenMode::eReadWrite:
case FS::EFileOpenMode::eWrite:
{
if (create.bAlwaysCreateDirTree)
{
FS::CreateDirectories(pathex, true);
}
if (create.bFailIfNonEmptyFile)
{
if (AuFS::FileExists(pathex.c_str()))
{
SysPushErrorResourceExists("File {} already exists", create.path);
return false;
}
}
break;
}
};
iFileDescriptor = ::open(pathex.c_str(),
(create.eMode == FS::EFileOpenMode::eRead ? O_RDONLY : (O_RDWR | O_CREAT)) | O_CLOEXEC | (this->bDirectIO ? O_DIRECT : 0),
0664);
if (iFileDescriptor < 0)
{
SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno);
return false;
}
if (!FS::ApplyDumbAdvisoryLock(iFileDescriptor, create.eAdvisoryLevel))
{
SysPushErrorIO("Couldn't open file: {}. File node (not section) is locked.", path);
::close(iFileDescriptor);
return false;
}
if (create.bFailIfNonEmptyFile)
{
if (FS::PosixGetLength(iFileDescriptor))
{
SysPushErrorResourceExists("File {} already exists", create.path);
::close(iFileDescriptor);
return false;
}
}
switch (create.eMode)
{
case FS::EFileOpenMode::eRead:
{
this->uOSReadHandle = AuUInt64(iFileDescriptor);
break;
}
case FS::EFileOpenMode::eReadWrite:
{
this->uOSWriteHandle = AuUInt64(iFileDescriptor);
this->uOSReadHandle = AuUInt64(iFileDescriptor);
break;
}
case FS::EFileOpenMode::eWrite:
{
this->uOSWriteHandle = AuUInt64(iFileDescriptor);
break;
}
};
this->bIsAsync = create.bAsyncHandle;
this->path = create.path;
return this->IsValid();
}
};
AUKN_SYM IIOHandle *IOHandleNew()
{
return _new UnixIOHandle();
}
AUKN_SYM void IOHandleRelease(IIOHandle *pIOHandle)
{
AuSafeDelete<UnixIOHandle *>(pIOHandle);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, IOHandle, UnixIOHandle)
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.Unix.hpp
Date: 2023-8-11
Author: Reece
***/
#pragma once
namespace Aurora::IO
{
}

View File

@ -7,6 +7,11 @@
***/ ***/
#pragma once #pragma once
namespace Aurora::IO::IPC
{
struct IPCPipeImpl;
}
namespace Aurora::IO namespace Aurora::IO
{ {
struct AFileHandle : IIOHandle struct AFileHandle : IIOHandle
@ -48,6 +53,8 @@ namespace Aurora::IO
AuSPtr<IIOHandle> pThat; AuSPtr<IIOHandle> pThat;
bool bIsAsync {}; bool bIsAsync {};
AuString path; AuString path;
IPC::IPCPipeImpl *pIPCPipe {};
bool bDirectIO {};
protected: protected:
// Implement me: // Implement me:

View File

@ -17,9 +17,12 @@
#include "FileStream.Unix.hpp" #include "FileStream.Unix.hpp"
#include "Async.Linux.hpp" #include "Async.Linux.hpp"
#include <Source/IO/IPC/AuIPCPipe.Unix.hpp> #include <Source/IO/IPC/AuIPCPipe.Unix.hpp>
#include <Source/IO/AuIOHandle.hpp>
namespace Aurora::IO::FS namespace Aurora::IO::FS
{ {
#define IPC_PIPE AuStaticCast<AFileHandle>(this->pHandle_)->pIPCPipe
struct LinuxAsyncFileTransactionLoopSource : Aurora::IO::Loop::LSEvent struct LinuxAsyncFileTransactionLoopSource : Aurora::IO::Loop::LSEvent
{ {
LinuxAsyncFileTransactionLoopSource(AuSPtr<LinuxAsyncFileTransaction> that); LinuxAsyncFileTransactionLoopSource(AuSPtr<LinuxAsyncFileTransaction> that);
@ -38,16 +41,16 @@ namespace Aurora::IO::FS
AuList<AuUInt> handles_; AuList<AuUInt> handles_;
}; };
LinuxAsyncFileTransactionLoopSource::LinuxAsyncFileTransactionLoopSource(AuSPtr<LinuxAsyncFileTransaction> that) : caller_(that), Loop::LSEvent(false, false, true) LinuxAsyncFileTransactionLoopSource::LinuxAsyncFileTransactionLoopSource(AuSPtr<LinuxAsyncFileTransaction> that) :
caller_(that),
Loop::LSEvent(false, false, true)
{ {
if (that) if (that)
{ {
auto possiblePipe = that->GetFileHandle()->pIPCPipe; if (auto pPipe = AuStaticCast<AFileHandle>(that->GetFileHandle())->pIPCPipe)
if (possiblePipe)
{ {
this->bExMode = true; this->bExMode = true;
this->handles_ = {pPipe->GetPreemptFd(), Loop::LSEvent::GetHandle()};
this->handles_ = {possiblePipe->GetPreemptFd(), Loop::LSEvent::GetHandle()};
} }
} }
} }
@ -94,80 +97,9 @@ namespace Aurora::IO::FS
{ {
} }
FileHandle::~FileHandle() void LinuxAsyncFileStream::Init(const AuSPtr<IIOHandle> &handle)
{ {
if ((this->readHandle != 0) && this->pHandle_ = handle;
(this->readHandle != -1))
{
::close(this->readHandle);
}
if ((this->writeHandle != 0) &&
(this->writeHandle != -1) &&
(this->writeHandle != this->readHandle))
{
::close(this->writeHandle);
}
this->readHandle = this->writeHandle = -1;
}
bool FileHandle::Init(const AuString &path, EFileOpenMode openMode, bool bDirectIO, EFileAdvisoryLockLevel lock)
{
int fileHandle;
int fOpenMode;
auto pathex = NormalizePathRet(path);
if (pathex.empty())
{
return false;
}
fOpenMode = openMode == EFileOpenMode::eRead ? O_RDONLY : (O_RDWR | O_CREAT);
if (bDirectIO)
{
fOpenMode |= O_DIRECT;
}
fileHandle = ::open(pathex.c_str(),
fOpenMode,
0664);
if (fileHandle == -1)
{
SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno);
return false;
}
if (!ApplyDumbAdvisoryLock(fileHandle, lock))
{
SysPushErrorIO("Couldn't open file: {}. File node (not section) is locked.", path);
return false;
}
this->directIO = bDirectIO;
this->readHandle = this->writeHandle = fileHandle;
this->readOnly = openMode == EFileOpenMode::eRead;
return true;
}
void FileHandle::Init(int read, int write)
{
this->readHandle = read;
this->writeHandle = write;
this->directIO = true;
this->readOnly = false;
}
AuSPtr<FileHandle> LinuxAsyncFileStream::GetHandle()
{
return handle_;
}
void LinuxAsyncFileStream::Init(const AuSPtr<FileHandle> &handle)
{
this->handle_ = handle;
} }
AuSPtr<IAsyncTransaction> LinuxAsyncFileStream::NewTransaction() AuSPtr<IAsyncTransaction> LinuxAsyncFileStream::NewTransaction()
@ -178,7 +110,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
if (!shared->Init(this->handle_)) if (!shared->Init(this->pHandle_))
{ {
return {}; return {};
} }
@ -188,32 +120,53 @@ namespace Aurora::IO::FS
bool LinuxAsyncFileStream::BlockingTruncate(AuUInt64 length) bool LinuxAsyncFileStream::BlockingTruncate(AuUInt64 length)
{ {
return ::ftruncate(this->handle_->writeHandle, length) != -1; auto iOptSafe = this->pHandle_->GetOSWriteHandleSafe();
} if (!iOptSafe)
bool LinuxAsyncFileStream::BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters)
{
if (this->handle_->bReadLock)
{ {
return false; return false;
} }
if (this->handle_->pIPCPipe) auto fd = (int)iOptSafe.Value();
if (fd == -1)
{ {
if (this->handle_->pIPCPipe->LIOS_PopOne()) SysPushErrorUninitialized();
return false;
}
return ::ftruncate(fd, length) != -1;
}
bool LinuxAsyncFileStream::BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters)
{
auto iOptSafe = this->pHandle_->GetOSReadHandleSafe();
if (!iOptSafe)
{
return false;
}
auto fd = (int)iOptSafe.Value();
if (fd == -1)
{
SysPushErrorUninitialized();
return false;
}
if (IPC_PIPE)
{
if (IPC_PIPE->LIOS_PopOne())
{ {
parameters.outVariable = 0; parameters.outVariable = 0;
return true; return true;
} }
} }
if (!PosixSetOffset(this->handle_->readHandle, offset)) if (!PosixSetOffset(fd, offset))
{ {
return false; return false;
} }
AuUInt32 read; AuUInt32 read;
if (!PosixRead(this->handle_->readHandle, parameters.ptr, parameters.length, &read)) if (!PosixRead(fd, parameters.ptr, parameters.length, &read))
{ {
return false; return false;
} }
@ -223,18 +176,26 @@ namespace Aurora::IO::FS
bool LinuxAsyncFileStream::BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead &parameters) bool LinuxAsyncFileStream::BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead &parameters)
{ {
if (this->handle_->bWriteLock) auto iOptSafe = this->pHandle_->GetOSWriteHandleSafe();
if (!iOptSafe)
{ {
return false; return false;
} }
if (!PosixSetOffset(this->handle_->writeHandle, offset)) auto fd = (int)iOptSafe.Value();
if (fd == -1)
{
SysPushErrorUninitialized();
return false;
}
if (!PosixSetOffset(fd, offset))
{ {
return false; return false;
} }
AuUInt32 read; AuUInt32 read;
if (!PosixWrite(this->handle_->writeHandle, parameters.ptr, parameters.length, &read)) if (!PosixWrite(fd, parameters.ptr, parameters.length, &read))
{ {
return false; return false;
} }
@ -242,9 +203,9 @@ namespace Aurora::IO::FS
return true; return true;
} }
bool LinuxAsyncFileTransaction::Init(const AuSPtr<FileHandle> &handle) bool LinuxAsyncFileTransaction::Init(const AuSPtr<IIOHandle> &handle)
{ {
this->handle_ = handle; this->pHandle_ = handle;
this->loopSource_ = AuMakeShared<LinuxAsyncFileTransactionLoopSource>(AuSharedFromThis()); this->loopSource_ = AuMakeShared<LinuxAsyncFileTransactionLoopSource>(AuSharedFromThis());
return bool(this->loopSource_); return bool(this->loopSource_);
} }
@ -262,16 +223,16 @@ namespace Aurora::IO::FS
return false; return false;
} }
auto iOptSafe = this->pHandle_->GetOSReadHandleSafe();
auto fd = this->handle_->readHandle; if (!iOptSafe)
if (fd == -1)
{ {
SysPushErrorUninitialized();
return false; return false;
} }
if (this->handle_->bReadLock) auto fd = (int)iOptSafe.Value();
if (fd == -1)
{ {
SysPushErrorUninitialized();
return false; return false;
} }
@ -293,9 +254,9 @@ namespace Aurora::IO::FS
LIOS_Init(AuSharedFromThis()); LIOS_Init(AuSharedFromThis());
SetMemory(memoryView); SetMemory(memoryView);
if (this->handle_->pIPCPipe) if (IPC_PIPE)
{ {
if (this->handle_->pIPCPipe->LIOS_PopOne()) if (IPC_PIPE->LIOS_PopOne())
{ {
LIOS_SendProcess(0, false, errno); LIOS_SendProcess(0, false, errno);
return true; return true;
@ -304,7 +265,7 @@ namespace Aurora::IO::FS
offset += this->uBaseOffset; offset += this->uBaseOffset;
if (!UNIX::LinuxOverlappedSubmitRead(fd, offset, this, this->loopSource_.get(), bool(this->handle_->pIPCPipe))) if (!UNIX::LinuxOverlappedSubmitRead(fd, offset, this, this->loopSource_.get(), bool(IPC_PIPE)))
{ {
LIOS_SendProcess(0, true, errno); LIOS_SendProcess(0, true, errno);
return true; return true;
@ -328,12 +289,13 @@ namespace Aurora::IO::FS
return false; return false;
} }
if (this->handle_->bWriteLock) auto iOptSafe = this->pHandle_->GetOSWriteHandleSafe();
if (!iOptSafe)
{ {
return false; return false;
} }
auto fd = this->handle_->writeHandle; auto fd = (int)iOptSafe.Value();
if (fd == -1) if (fd == -1)
{ {
SysPushErrorUninitialized(); SysPushErrorUninitialized();
@ -398,11 +360,11 @@ namespace Aurora::IO::FS
if (read) if (read)
{ {
if (this->handle_->pIPCPipe) if (IPC_PIPE)
{ {
// Return value intentionally ignored // Return value intentionally ignored
// We just need to poke on read... // We just need to poke on read...
this->handle_->pIPCPipe->LIOS_PopOne(); IPC_PIPE->LIOS_PopOne();
} }
} }
@ -471,9 +433,9 @@ namespace Aurora::IO::FS
return WaitMultiple(files, timeout); return WaitMultiple(files, timeout);
} }
AuSPtr<FileHandle> LinuxAsyncFileTransaction::GetFileHandle() AuSPtr<IIOHandle> LinuxAsyncFileTransaction::GetFileHandle()
{ {
return this->handle_; return this->pHandle_;
} }
AuSPtr<Loop::ILoopSource> LinuxAsyncFileTransaction::NewLoopSource() AuSPtr<Loop::ILoopSource> LinuxAsyncFileTransaction::NewLoopSource()
@ -483,38 +445,35 @@ namespace Aurora::IO::FS
AUKN_SYM IAsyncFileStream *OpenAsyncNew(const AuString &path, EFileOpenMode openMode, bool bDirectIO, EFileAdvisoryLockLevel lock) AUKN_SYM IAsyncFileStream *OpenAsyncNew(const AuString &path, EFileOpenMode openMode, bool bDirectIO, EFileAdvisoryLockLevel lock)
{ {
AuSPtr<FileHandle> fileHandle; auto pHandle = AuIO::IOHandleShared();
LinuxAsyncFileStream *stream; if (!pHandle)
if (path.empty())
{ {
SysPushErrorParam("Empty path"); SysPushErrorMemory();
return {}; return nullptr;
} }
if (!EFileOpenModeIsValid(openMode)) AuIO::IIOHandle::HandleCreate createhandle(path);
{ createhandle.eAdvisoryLevel = lock;
SysPushErrorParam("Invalid open mode"); createhandle.eMode = openMode;
return {}; createhandle.bFailIfNonEmptyFile = false;
} createhandle.bDirectIOMode = bDirectIO;
createhandle.bAsyncHandle = true;
fileHandle = AuMakeShared<FileHandle>(); if (!pHandle->InitFromPath(createhandle))
if (!fileHandle->Init(path, openMode, bDirectIO, lock))
{ {
SysPushErrorNested(); SysPushErrorNested();
return {}; return nullptr;
} }
stream = _new LinuxAsyncFileStream(); auto pStream = _new LinuxAsyncFileStream();
if (!stream) if (!pStream)
{ {
SysPushErrorMem(); SysPushErrorMemory();
return {}; return nullptr;
} }
stream->Init(fileHandle); pStream->Init(pHandle);
return pStream;
return stream;
} }
AUKN_SYM void OpenAsyncRelease(IAsyncFileStream *handle) AUKN_SYM void OpenAsyncRelease(IAsyncFileStream *handle)

View File

@ -17,25 +17,6 @@ namespace Aurora::IO::FS
struct LinuxAsyncFileTransaction; struct LinuxAsyncFileTransaction;
struct LinuxAsyncFileTransactionLoopSource; struct LinuxAsyncFileTransactionLoopSource;
struct FileHandle
{
~FileHandle();
bool Init(const AuString &path, EFileOpenMode openMode, bool directIO, EFileAdvisoryLockLevel lock);
void Init(int read, int write);
int readHandle {-1};
int writeHandle {-1};
AuString path;
bool readOnly;
bool directIO;
IPC::IPCPipeImpl *pIPCPipe {};
bool bNoOwns { false };
bool bWriteLock { false };
bool bReadLock { false };
};
struct LinuxAsyncFileStream : IAsyncFileStream struct LinuxAsyncFileStream : IAsyncFileStream
{ {
AuSPtr<IAsyncTransaction> NewTransaction() override; AuSPtr<IAsyncTransaction> NewTransaction() override;
@ -43,12 +24,12 @@ namespace Aurora::IO::FS
bool BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters) override; bool BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters) override;
bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead &parameters) override; bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead &parameters) override;
void Init(const AuSPtr<FileHandle> &handle); void Init(const AuSPtr<IIOHandle> &handle);
AuSPtr<FileHandle> GetHandle(); AuSPtr<IIOHandle> GetHandle();
private: private:
AuSPtr<FileHandle> handle_; AuSPtr<IIOHandle> pHandle_;
}; };
@ -56,7 +37,7 @@ namespace Aurora::IO::FS
{ {
~LinuxAsyncFileTransaction(); ~LinuxAsyncFileTransaction();
bool Init(const AuSPtr<FileHandle> &handle); bool Init(const AuSPtr<IIOHandle> &handle);
bool StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) override; bool StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) override;
bool StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView) override; bool StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView) override;
@ -78,14 +59,14 @@ namespace Aurora::IO::FS
void Reset() override; void Reset() override;
void DispatchCb(); void DispatchCb();
AuSPtr<FileHandle> GetFileHandle(); AuSPtr<IIOHandle> GetFileHandle();
void SetBaseOffset(AuUInt64 uBaseOffset) override; void SetBaseOffset(AuUInt64 uBaseOffset) override;
virtual void LIOS_Process(AuUInt32 read, bool failure, int err, bool mark) override; virtual void LIOS_Process(AuUInt32 read, bool failure, int err, bool mark) override;
private: private:
AuSPtr<FileHandle> handle_; AuSPtr<IIOHandle> pHandle_;
AuUInt64 lastAbstractOffset_ {}; AuUInt64 lastAbstractOffset_ {};
AuUInt32 lastFinishedStat_ {}; AuUInt32 lastFinishedStat_ {};
AuUInt64 uBaseOffset {}; AuUInt64 uBaseOffset {};

View File

@ -302,8 +302,8 @@ namespace Aurora::IO::FS
AUKN_SYM bool Relink(const AuString &src, const AuString &dest) AUKN_SYM bool Relink(const AuString &src, const AuString &dest)
{ {
auto normalizedDestPath = NormalizePathRet(dest); auto normalizedDestPath = NormalizePathRet(dest);
CreateDirectories(destPathNormalized, true); CreateDirectories(normalizedDestPath, true);
return ::rename(NormalizePathRet(src).c_str(), destPathNormalized.c_str()) != -1; return ::rename(NormalizePathRet(src).c_str(), normalizedDestPath.c_str()) != -1;
} }
#if defined(AURORA_IS_LINUX_DERIVED) #if defined(AURORA_IS_LINUX_DERIVED)
@ -419,9 +419,9 @@ namespace Aurora::IO::FS
#if defined(AURORA_IS_LINUX_DERIVED) #if defined(AURORA_IS_LINUX_DERIVED)
stat.createdNs = AuTime::CTimeNSNormalize(s.st_ctime_nsec); stat.createdNs = AuTime::CTimeNSNormalize(s.st_ctim.tv_nsec);
stat.modifiedNs = AuTime::CTimeNSNormalize(s.st_mtime_nsec); stat.modifiedNs = AuTime::CTimeNSNormalize(s.st_mtim.tv_nsec);
stat.accessedNs = AuTime::CTimeNSNormalize(s.st_atime_nsec); stat.accessedNs = AuTime::CTimeNSNormalize(s.st_atim.tv_nsec);
#else #else
stat.createdNs = AuMSToNS<AuUInt64>(Time::CTimeToMS(s.st_ctime)); stat.createdNs = AuMSToNS<AuUInt64>(Time::CTimeToMS(s.st_ctime));
stat.modifiedNs = AuMSToNS<AuUInt64>(Time::CTimeToMS(s.st_mtime)); stat.modifiedNs = AuMSToNS<AuUInt64>(Time::CTimeToMS(s.st_mtime));

View File

@ -66,8 +66,8 @@ namespace Aurora::IO::FS
timeval timeVals[2]; timeval timeVals[2];
ConvertFileTime(&timeVals[0], auStat.accessed, times.accessedNs); ConvertFileTime(&timeVals[0], auStat.accessedNs, times.accessedNs);
ConvertFileTime(&timeVals[1], auStat.modified, times.modifiedNs); ConvertFileTime(&timeVals[1], auStat.modifiedNs, times.modifiedNs);
bool bRet = ::utimes(pathex.c_str(), timeVals) == 0; bool bRet = ::utimes(pathex.c_str(), timeVals) == 0;
if (!bRet) if (!bRet)

View File

@ -19,7 +19,7 @@ namespace Aurora::IO::FS
AuString buffer; AuString buffer;
auto srcPath = NormalizePathRet(path); auto srcPath = NormalizePathRet(path);
if (pathex.empty()) if (srcPath.empty())
{ {
return {}; return {};
} }
@ -30,7 +30,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
auto length = ::listxattr(srcPath.c_str(), attr.c_str(), buffer.data(), buffer.size(), 0 /*no follow symlinks*/); auto length = ::listxattr(srcPath.c_str(), buffer.data(), buffer.size());
if (length < 0) if (length < 0)
{ {
SysPushErrorIO("Error listing attributes"); SysPushErrorIO("Error listing attributes");
@ -51,12 +51,12 @@ namespace Aurora::IO::FS
AuByteBuffer buffer; AuByteBuffer buffer;
auto srcPath = NormalizePathRet(path); auto srcPath = NormalizePathRet(path);
if (pathex.empty()) if (srcPath.empty())
{ {
return {}; return {};
} }
auto length = ::getxattr(srcPath.c_str(), attr.c_str(), nullptr, 0, 0 /*no follow symlinks*/); auto length = ::getxattr(srcPath.c_str(), attr.c_str(), nullptr, 0);
if (length < 0) if (length < 0)
{ {
SysPushErrorIO("Error reading attribute"); SysPushErrorIO("Error reading attribute");
@ -74,7 +74,7 @@ namespace Aurora::IO::FS
return {}; return {};
} }
length = ::getxattr(srcPath.c_str(), attr.c_str(), buffer.base, length, 0 /*no follow symlinks*/); length = ::getxattr(srcPath.c_str(), attr.c_str(), buffer.base, length);
if (length < 0) if (length < 0)
{ {
SysPushErrorIO("Error reading attribute"); SysPushErrorIO("Error reading attribute");
@ -89,7 +89,7 @@ namespace Aurora::IO::FS
AUKN_SYM bool FileAttrsSet(const AuString &path, const AuString &attr, const Memory::MemoryViewRead &view) AUKN_SYM bool FileAttrsSet(const AuString &path, const AuString &attr, const Memory::MemoryViewRead &view)
{ {
auto srcPath = NormalizePathRet(path); auto srcPath = NormalizePathRet(path);
if (pathex.empty()) if (srcPath.empty())
{ {
return false; return false;
} }
@ -112,7 +112,7 @@ namespace Aurora::IO::FS
AUKN_SYM bool FileAttrsDel(const AuString &path, const AuString &attr) AUKN_SYM bool FileAttrsDel(const AuString &path, const AuString &attr)
{ {
auto srcPath = NormalizePathRet(path); auto srcPath = NormalizePathRet(path);
if (pathex.empty()) if (srcPath.empty())
{ {
return false; return false;
} }

View File

@ -126,57 +126,81 @@ namespace Aurora::IO::FS
Close(); Close();
} }
bool PosixFileStream::Init(int handle, const AuString &path) bool PosixFileStream::Init(AuSPtr<IIOHandle> pHandle)
{ {
AuCtorCode_t code; AuCtorCode_t code;
this->pHandle_ = pHandle;
this->handle_ = handle;
this->path_ = AuTryConstruct<AuString>(code, path);
if (!code)
{
return false;
}
return true; return true;
} }
AuUInt64 PosixFileStream::GetOffset() AuUInt64 PosixFileStream::GetOffset()
{ {
AU_LOCK_GUARD(this->spinlock_); AU_LOCK_GUARD(this->spinlock_);
if (this->handle_ == -1) auto iOptSafe = this->pHandle_->GetOSWriteHandleSafe();
if (!iOptSafe)
{ {
SysPushErrorUninitialized(); iOptSafe = this->pHandle_->GetOSReadHandleSafe();
return 0;
} }
return PosixGetOffset(this->handle_); if (!iOptSafe)
{
return false;
}
auto fd = (int)iOptSafe.Value();
if (fd == -1)
{
SysPushErrorUninitialized();
return false;
}
return PosixGetOffset(fd);
} }
bool PosixFileStream::SetOffset(AuUInt64 offset) bool PosixFileStream::SetOffset(AuUInt64 offset)
{ {
AU_LOCK_GUARD(this->spinlock_); AU_LOCK_GUARD(this->spinlock_);
if (this->handle_ == -1) auto iOptSafe = this->pHandle_->GetOSWriteHandleSafe();
if (!iOptSafe)
{
iOptSafe = this->pHandle_->GetOSReadHandleSafe();
}
if (!iOptSafe)
{ {
SysPushErrorUninitialized(); return false;
return 0;
} }
return PosixSetOffset(this->handle_, offset); auto fd = (int)iOptSafe.Value();
if (fd == -1)
{
SysPushErrorUninitialized();
return false;
}
return PosixSetOffset(fd, offset);
} }
AuUInt64 PosixFileStream::GetLength() AuUInt64 PosixFileStream::GetLength()
{ {
AU_LOCK_GUARD(this->spinlock_); AU_LOCK_GUARD(this->spinlock_);
if (this->handle_ == -1) auto iOptSafe = this->pHandle_->GetOSReadHandleSafe();
if (!iOptSafe)
{
return false;
}
auto fd = (int)iOptSafe.Value();
if (fd == -1)
{ {
SysPushErrorUninitialized(); SysPushErrorUninitialized();
return 0; return false;
} }
return PosixGetLength(this->handle_); return PosixGetLength(fd);
} }
bool PosixFileStream::Read(const Memory::MemoryViewStreamWrite &parameters) bool PosixFileStream::Read(const Memory::MemoryViewStreamWrite &parameters)
@ -185,7 +209,14 @@ namespace Aurora::IO::FS
parameters.outVariable = 0; parameters.outVariable = 0;
if (this->handle_ == -1) if (!this->pHandle_)
{
SysPushErrorUninitialized();
return 0;
}
int fd = this->GetUnixHandle();
if (fd == -1)
{ {
SysPushErrorUninitialized(); SysPushErrorUninitialized();
return 0; return 0;
@ -199,7 +230,7 @@ namespace Aurora::IO::FS
int blockSize = AuMin(kFileCopyBlock, length); int blockSize = AuMin(kFileCopyBlock, length);
if (!PosixRead(handle_, &reinterpret_cast<char *>(parameters.ptr)[offset], blockSize, &read)) if (!PosixRead(fd, &reinterpret_cast<char *>(parameters.ptr)[offset], blockSize, &read))
{ {
SysPushErrorNested("File Error: {}", path_); SysPushErrorNested("File Error: {}", path_);
break; break;
@ -222,7 +253,14 @@ namespace Aurora::IO::FS
{ {
AU_LOCK_GUARD(this->spinlock_); AU_LOCK_GUARD(this->spinlock_);
if (this->handle_ == -1) if (!this->pHandle_)
{
SysPushErrorUninitialized();
return 0;
}
int fd = this->GetUnixHandle();
if (fd == -1)
{ {
SysPushErrorUninitialized(); SysPushErrorUninitialized();
return 0; return 0;
@ -238,9 +276,9 @@ namespace Aurora::IO::FS
int blockSize = AuMin(AuUInt(kFileCopyBlock), length); int blockSize = AuMin(AuUInt(kFileCopyBlock), length);
if (!PosixWrite(this->handle_, &reinterpret_cast<const char *>(parameters.ptr)[offset], blockSize, &written)) if (!PosixWrite(fd, &reinterpret_cast<const char *>(parameters.ptr)[offset], blockSize, &written))
{ {
SysPushErrorNested("File Error: {}", path_); SysPushErrorNested("File Error: {}", this->pHandle_->GetPath());
return false; return false;
} }
@ -265,26 +303,40 @@ namespace Aurora::IO::FS
void PosixFileStream::Close() void PosixFileStream::Close()
{ {
int handle = AuExchange(this->handle_, -1); auto pHandle = this->pHandle_;
if (handle != -1) AuResetMember(this->pHandle_);
{
::close(handle);
}
if (AuExchange(this->bMadeTemporary, false)) if (AuExchange(this->bMadeTemporary, false))
{ {
::unlink(this->path_.c_str()); if (pHandle)
{
::unlink(pHandle->GetPath().c_str());
}
} }
} }
void PosixFileStream::Flush() void PosixFileStream::Flush()
{ {
::fsync(this->handle_); int fd = this->GetUnixHandle();
if (fd == -1)
{
SysPushErrorUninitialized();
return;
}
::fsync(fd);
} }
void PosixFileStream::WriteEoS() void PosixFileStream::WriteEoS()
{ {
::ftruncate(this->handle_, GetOffset()); int fd = this->GetUnixHandle();
if (fd == -1)
{
SysPushErrorUninitialized();
return;
}
::ftruncate(fd, GetOffset());
} }
void PosixFileStream::MakeTemporary() void PosixFileStream::MakeTemporary()
@ -292,70 +344,72 @@ namespace Aurora::IO::FS
this->bMadeTemporary = true; this->bMadeTemporary = true;
} }
int PosixFileStream::GetHandle() int PosixFileStream::GetUnixHandle()
{ {
return this->handle_; return this->pHandle_ ?
(int)this->pHandle_->GetOSWriteHandleSafe().ValueOr(this->pHandle_->GetOSReadHandleSafe().ValueOr((AuUInt)-1)) :
-1;
} }
static IFileStream *OpenNewEx(const AuString &path, EFileOpenMode openMode, EFileAdvisoryLockLevel lock, bool bCheck) AuSPtr<IIOHandle> PosixFileStream::GetHandle()
{ {
auto pathex = NormalizePathRet(path); return this->pHandle_;
}
if (openMode != EFileOpenMode::eRead) AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle)
{
auto pStream = AuMakeShared<PosixFileStream>();
if (!pStream)
{ {
CreateDirectories(pathex, true); SysPushErrorMemory();
return nullptr;
} }
if (bCheck) pStream->Init(pIOHandle);
return pStream;
}
static IFileStream *OpenNewEx(const AuString &path,
EFileOpenMode openMode,
EFileAdvisoryLockLevel lock,
bool bCheck)
{
try
{ {
if (FileExists(path)) auto pHandle = AuIO::IOHandleShared();
if (!pHandle)
{ {
SysPushErrorIO("Couldn't open file: {}. Already exists.", path); SysPushErrorMemory();
return false; return nullptr;
} }
}
auto fileHandle = ::open(pathex.c_str(), AuIO::IIOHandle::HandleCreate createhandle(path);
(openMode == EFileOpenMode::eRead ? O_RDONLY : (O_RDWR | O_CREAT)) | O_CLOEXEC, createhandle.eAdvisoryLevel = lock;
0664); createhandle.eMode = openMode;
createhandle.bFailIfNonEmptyFile = bCheck;
createhandle.bDirectIOMode = false;
createhandle.bAsyncHandle = false;
if (fileHandle < 0) if (!pHandle->InitFromPath(createhandle))
{
SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno);
return nullptr;
}
if (!ApplyDumbAdvisoryLock(fileHandle, lock))
{
SysPushErrorIO("Couldn't open file: {}. File node (not section) is locked.", path);
return nullptr;
}
if (bCheck)
{
if (PosixGetLength(fileHandle))
{ {
SysPushErrorIO("Couldn't open file: {}. Already exists.", path); SysPushErrorNested();
return false; return nullptr;
} }
}
auto stream = _new PosixFileStream(); auto pStream = _new PosixFileStream();
if (!stream) if (!pStream)
{
SysPushErrorMemory();
return nullptr;
}
pStream->Init(pHandle);
return pStream;
}
catch (...)
{ {
::close(fileHandle);
SysPushErrorMem("{}", path);
return nullptr; return nullptr;
} }
if (!stream->Init(fileHandle, pathex))
{
delete stream;
SysPushErrorGeneric("{}", path);
return nullptr;
}
return stream;
} }
AUKN_SYM IFileStream *CreateNew(const AuString &path) AUKN_SYM IFileStream *CreateNew(const AuString &path)

View File

@ -13,6 +13,7 @@ namespace Aurora::IO::FS
{ {
// Code-sharing for async API fallbacks... // Code-sharing for async API fallbacks...
bool PosixSetOffset(int fd, AuUInt64 offset); bool PosixSetOffset(int fd, AuUInt64 offset);
AuUInt64 PosixGetLength(int fd);
bool PosixRead(int fd, void *buf, AuUInt32 count, AuUInt32 *pRead); bool PosixRead(int fd, void *buf, AuUInt32 count, AuUInt32 *pRead);
bool PosixWrite(int fd, const void *buf, AuUInt32 count, AuUInt32 *pWritten); bool PosixWrite(int fd, const void *buf, AuUInt32 count, AuUInt32 *pWritten);
@ -20,7 +21,7 @@ namespace Aurora::IO::FS
{ {
~PosixFileStream(); ~PosixFileStream();
bool Init(int handle, const AuString &path); bool Init(AuSPtr<IIOHandle> pHandle);
AuUInt64 GetOffset() override; AuUInt64 GetOffset() override;
bool SetOffset(AuUInt64 offset) override; bool SetOffset(AuUInt64 offset) override;
@ -31,11 +32,11 @@ namespace Aurora::IO::FS
void Flush() override; void Flush() override;
void WriteEoS() override; void WriteEoS() override;
void MakeTemporary() override; void MakeTemporary() override;
AuSPtr<IIOHandle> GetHandle() override;
int GetUnixHandle();
int GetHandle();
private: private:
AuSPtr<IIOHandle> pHandle_;
int handle_ = -1;
AuString path_; AuString path_;
AuThreadPrimitives::SpinLock spinlock_; AuThreadPrimitives::SpinLock spinlock_;
bool bMadeTemporary {}; bool bMadeTemporary {};

View File

@ -10,6 +10,10 @@
#include "FileTrust.Unix.hpp" #include "FileTrust.Unix.hpp"
#include <sys/xattr.h> #include <sys/xattr.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
namespace Aurora::IO::FS namespace Aurora::IO::FS
{ {

View File

@ -13,6 +13,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <termios.h> #include <termios.h>
#include <Source/IO/AuIOHandle.hpp>
namespace Aurora::IO::IPC namespace Aurora::IO::IPC
{ {
@ -127,14 +128,16 @@ namespace Aurora::IO::IPC
} }
#endif #endif
this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>();
this->fsHandle_ = AuIO::IOHandleShared();
SysAssert(this->fsHandle_);
this->fsStream_ = AuMakeShared<IO::FS::LinuxAsyncFileStream>(); this->fsStream_ = AuMakeShared<IO::FS::LinuxAsyncFileStream>();
this->fsHandle_->pIPCPipe = this; AuStaticCast<AFileHandle>(this->fsHandle_)->pIPCPipe = this;
this->fsHandle_->Init(fds2[0], fds2[1]); this->fsHandle_->InitFromPairMove(fds2[0], fds2[1]);
this->fsStream_->Init(this->fsHandle_); this->fsStream_->Init(this->fsHandle_);
} }
AuSPtr<Loop::ILoopSource> IPCPipeImpl::AsReadChannelIsOpen() AuSPtr<Loop::ILoopSource> IPCPipeImpl::AsReadChannelIsOpen()
@ -152,6 +155,11 @@ namespace Aurora::IO::IPC
return this->fsStream_->NewTransaction(); return this->fsStream_->NewTransaction();
} }
AuSPtr<IO::IIOHandle> IPCPipeImpl::GetCurrentSharedDuplexHandles()
{
return this->fsHandle_;
}
bool IPCPipeImpl::Read(const Memory::MemoryViewStreamWrite &write, bool nonblock) bool IPCPipeImpl::Read(const Memory::MemoryViewStreamWrite &write, bool nonblock)
{ {
auto handle = fds[0]; auto handle = fds[0];

View File

@ -53,7 +53,8 @@ namespace Aurora::IO::IPC
#endif #endif
virtual AuSPtr<IO::IAsyncTransaction> NewAsyncTransaction() override; virtual AuSPtr<IO::IAsyncTransaction> NewAsyncTransaction() override;
virtual AuSPtr<IO::IIOHandle> GetCurrentSharedDuplexHandles() override;
virtual AuSPtr<Loop::ILoopSource> AsReadChannelIsOpen() override; virtual AuSPtr<Loop::ILoopSource> AsReadChannelIsOpen() override;
virtual AuSPtr<Loop::ILoopSource> AsReadChannelHasData() override; virtual AuSPtr<Loop::ILoopSource> AsReadChannelHasData() override;
@ -84,7 +85,7 @@ namespace Aurora::IO::IPC
int fds[2] {-1, -1}; int fds[2] {-1, -1};
int secondary[2] {-1, -1}; int secondary[2] {-1, -1};
AuSPtr<IO::FS::FileHandle> fsHandle_; AuSPtr<IO::IIOHandle> fsHandle_;
AuSPtr<IO::FS::LinuxAsyncFileStream> fsStream_; AuSPtr<IO::FS::LinuxAsyncFileStream> fsStream_;
void SendTerminateSignal(); void SendTerminateSignal();

View File

@ -34,7 +34,16 @@ namespace Aurora::IO::Net
Socket::Socket(struct NetInterface *pInterface, Socket::Socket(struct NetInterface *pInterface,
struct NetWorker *pWorker, struct NetWorker *pWorker,
const AuSPtr<ISocketDriver> &pSocketDriver, const AuSPtr<ISocketDriver> &pSocketDriver,
const NetEndpoint &endpoint) : const AuPair<NetHostname, AuUInt16> &endpoint,
AuNet::ETransportProtocol eProtocol) :
SocketBase(pInterface, pWorker, pSocketDriver, endpoint, eProtocol)
{
}
Socket::Socket(struct NetInterface *pInterface,
struct NetWorker *pWorker,
const AuSPtr<ISocketDriver> &pSocketDriver,
const NetEndpoint &endpoint) :
SocketBase(pInterface, pWorker, pSocketDriver, endpoint) SocketBase(pInterface, pWorker, pSocketDriver, endpoint)
{ {
} }
@ -55,14 +64,48 @@ namespace Aurora::IO::Net
void Socket::CloseSocket() void Socket::CloseSocket()
{ {
if (this->osHandle_ && this->osHandle_ = 0;
this->osHandle_ != -1) AuResetMember(this->osHandleOwner_);
}
void Socket::RenewSocket()
{
if (!this->SendPreestablish())
{ {
::close(this->osHandle_); SysPushErrorIO("Preestablish drop");
this->osHandle_ = 0; return;
}
if (this->bHasRemoteMany_ && this->connectMany_.ips.size())
{
this->remoteEndpoint_ = this->connectMany_.ips[0];
}
this->CloseSocket();
this->osHandle_ = ::socket(
IPToDomain(this->remoteEndpoint_),
TransportToPlatformType(this->remoteEndpoint_),
0
);
if (this->osHandle_ == -1)
{
this->SendErrorNoStream(GetLastNetError());
return;
}
this->osHandleOwner_ = AuIO::IOHandleShared();
this->osHandleOwner_->InitFromPairMove((int)this->osHandle_, (int)this->osHandle_);
if (!this->PrepareConnectOperations())
{
this->bForceFailConstruct_ = true;
return;
} }
} }
void Socket::FinishConstructAsync() void Socket::FinishConstructAsync()
{ {
if (!this->SendPreestablish()) if (!this->SendPreestablish())
@ -83,13 +126,13 @@ namespace Aurora::IO::Net
return; return;
} }
this->osHandleOwner_->InitFromPairMove((int)this->osHandle_, (int)this->osHandle_);
if (!this->PrepareConnectOperations()) if (!this->PrepareConnectOperations())
{ {
this->bForceFailConstruct_ = true; this->bForceFailConstruct_ = true;
return; return;
} }
this->osHandleOwner_->Init((int)this->osHandle_, (int)this->osHandle_);
} }
bool Socket::PrepareConnectOperations() bool Socket::PrepareConnectOperations()

View File

@ -29,6 +29,12 @@ namespace Aurora::IO::Net
const AuSPtr<ISocketDriver> &pSocketDriver, const AuSPtr<ISocketDriver> &pSocketDriver,
AuUInt osHandle); AuUInt osHandle);
Socket(struct NetInterface *pInterface,
struct NetWorker *pWorker,
const AuSPtr<ISocketDriver> &pSocketDriver,
const AuPair<NetHostname, AuUInt16> &endpoint,
AuNet::ETransportProtocol eProtocol);
Socket(struct NetInterface *pInterface, Socket(struct NetInterface *pInterface,
struct NetWorker *pWorker, struct NetWorker *pWorker,
const AuSPtr<ISocketDriver> &pSocketDriver, const AuSPtr<ISocketDriver> &pSocketDriver,
@ -61,6 +67,7 @@ namespace Aurora::IO::Net
virtual void Shutdown(bool bNow) override; virtual void Shutdown(bool bNow) override;
virtual void CloseSocket() override; virtual void CloseSocket() override;
virtual void RenewSocket() override;
bool MakeCloseonexec(); bool MakeCloseonexec();
}; };

View File

@ -113,6 +113,8 @@ namespace Aurora::IO::UNIX
{ {
static bool LinuxOverlappedSubmit(int fd, int op, AuUInt offset, ASubmittable *context, AuLoop::ILSEvent *optEvent); static bool LinuxOverlappedSubmit(int fd, int op, AuUInt offset, ASubmittable *context, AuLoop::ILSEvent *optEvent);
static void IoTlsRedo();
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// ASubmittable // ASubmittable
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -155,6 +157,8 @@ namespace Aurora::IO::UNIX
{ {
SysPushErrorCatch("IO Callback threw an exception"); SysPushErrorCatch("IO Callback threw an exception");
} }
IoTlsRedo();
} }
UNIX::SendIOBuffers(); UNIX::SendIOBuffers();
@ -274,6 +278,7 @@ namespace Aurora::IO::UNIX
aio_context_t context {}; aio_context_t context {};
AuList<iocb*> submitPendingArray; AuList<iocb*> submitPendingArray;
AuUInt32 dwIoSubmits; AuUInt32 dwIoSubmits;
bool bPollHit {};
~TLSIO() ~TLSIO()
{ {
@ -298,6 +303,17 @@ namespace Aurora::IO::UNIX
return handle->bInitialized ? handle : nullptr; return handle->bInitialized ? handle : nullptr;
} }
void IoTlsRedo()
{
auto pTLS = GetTls();
if (!pTLS)
{
return;
}
pTLS->bPollHit = true;
}
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// TLS IO IMPL // TLS IO IMPL
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -594,7 +610,7 @@ namespace Aurora::IO::UNIX
} }
} }
} while (timeout); } while (timeout || AuExchange(io->bPollHit, false));
return dwApcsSent; return dwApcsSent;
} }
@ -730,7 +746,7 @@ namespace Aurora::IO::UNIX
} }
} }
} while (timeout ? !bEpollTriggered : false); } while ((timeout ? !bEpollTriggered : false) || AuExchange(io->bPollHit, false));
io_event finalEpollEvent {}; io_event finalEpollEvent {};
if ((bEpollTriggered) || if ((bEpollTriggered) ||

View File

@ -39,7 +39,7 @@ namespace Aurora::Process
if (key.empty()) if (key.empty())
{ {
SysPushErrorArg("Missing key"); SysPushErrorArg("Missing key");
return false; return {};
} }
auto pValue = ::getenv(key.c_str()); auto pValue = ::getenv(key.c_str());

View File

@ -156,7 +156,6 @@ namespace Aurora::Process
AuString file; AuString file;
AuIOFS::GetFileFromPath(file, path); AuIOFS::GetFileFromPath(file, path);
auto object = AuIOFS::OpenReadUnique(path); auto object = AuIOFS::OpenReadUnique(path);
if (!object) if (!object)
{ {
@ -169,6 +168,7 @@ namespace Aurora::Process
if (!object->Read(AuMemoryViewStreamWrite(AuMemoryViewWrite(&header, sizeof(header)), read))) if (!object->Read(AuMemoryViewStreamWrite(AuMemoryViewWrite(&header, sizeof(header)), read)))
{ {
SysPushErrorIO(); SysPushErrorIO();
continue;
} }
AuList<Elf_Shdr> elfSections; AuList<Elf_Shdr> elfSections;
@ -188,10 +188,15 @@ namespace Aurora::Process
continue; continue;
} }
auto &strtab = elfSections[header.e_shstrndx]; auto &strtab = elfSections[header.e_shstrndx];
AuList<AuUInt8> strHeap; AuList<AuUInt8> strHeap;
if (strtab.sh_size > 80 * 1024 * 1024)
{
SysPushErrorMem();
continue;
}
if (!AuTryResize(strHeap, strtab.sh_size)) if (!AuTryResize(strHeap, strtab.sh_size))
{ {
SysPushErrorMem(); SysPushErrorMem();
@ -211,6 +216,11 @@ namespace Aurora::Process
Sections modSections; Sections modSections;
for (const auto & section : elfSections) for (const auto & section : elfSections)
{ {
if (section.sh_name > strHeap.size())
{
continue;
}
auto len = strnlen((const char *)strHeap.data() + section.sh_name, strHeap.size() - section.sh_name); auto len = strnlen((const char *)strHeap.data() + section.sh_name, strHeap.size() - section.sh_name);
AuString sectionName((const char *)strHeap.data() + section.sh_name, len); AuString sectionName((const char *)strHeap.data() + section.sh_name, len);
AuUInt fileOffset = section.sh_offset; AuUInt fileOffset = section.sh_offset;

View File

@ -95,7 +95,7 @@ namespace Aurora::Process
return false; return false;
} }
return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength} }); return AuMemory::SwapLock::Lock({ { this->uAddress, this->uLength_ } });
} }
bool ProcessSectionFileMapView::UnlockSwap() bool ProcessSectionFileMapView::UnlockSwap()
@ -105,6 +105,6 @@ namespace Aurora::Process
return false; return false;
} }
return AuMemory::SwapLock::Unlock({ { this->uAddress, this->uLength} }); return AuMemory::SwapLock::Unlock({ { this->uAddress, this->uLength_ } });
} }
} }

View File

@ -62,17 +62,16 @@ namespace Aurora::Process
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel sectionLock) AuFS::EFileAdvisoryLockLevel sectionLock)
{ {
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety); return this->MapFileByPathEx(0, str, uOffset, uLength, mode, sectionLock);
return file ? this->MapFileByObject(file, uOffset, uLength, mode, sectionLock) : AuSPtr<IProcessSectionMapView> {};
} }
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObject(const AuSPtr<AuFS::IFileStream> &stream, AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObject(const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel processLockLevel) AuFS::EFileAdvisoryLockLevel processLockLevel)
{ {
return this->MapFileByObjectEx(0, stream, uOffset, uLength, mode, processLockLevel); return this->MapFileByObjectEx(0, pIOHandle, uOffset, uLength, mode, processLockLevel);
} }
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapIPCMemory(const AuString &handleString, AuSPtr<IProcessSectionMapView> ProcessSectionView::MapIPCMemory(const AuString &handleString,
@ -144,18 +143,37 @@ namespace Aurora::Process
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel)
{ {
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety);
return file ? this->MapFileByObjectEx(viewOffset, file, uOffset, uLength, mode, processLockLevel) : AuSPtr<IProcessSectionMapView> {}; auto pHandle = AuIO::IOHandleShared();
if (!pHandle)
{
SysPushErrorMemory();
return nullptr;
}
AuIO::IIOHandle::HandleCreate createhandle(str);
createhandle.eAdvisoryLevel = AuFS::EFileAdvisoryLockLevel::eNoSafety;
createhandle.eMode = mode;
createhandle.bFailIfNonEmptyFile = false;
createhandle.bDirectIOMode = false;
createhandle.bAsyncHandle = false;
if (!pHandle->InitFromPath(createhandle))
{
return nullptr;
}
return this->MapFileByObjectEx(viewOffset, pHandle, uOffset, uLength, mode, processLockLevel);
} }
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObjectEx(AuUInt viewOffset, AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObjectEx(AuUInt viewOffset,
const AuSPtr<Aurora::IO::FS::IFileStream> &pStream, const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel)
{ {
if (!pStream) if (!pIOHandle)
{ {
return {}; return {};
} }
@ -166,8 +184,7 @@ namespace Aurora::Process
return {}; return {};
} }
auto ok = AuStaticCast<AuFS::PosixFileStream>(pStream); int fd = ::dup(pIOHandle->GetOSHandle());
int fd = ::dup(ok->GetHandle());
if (fd == -1) if (fd == -1)
{ {
SysPushErrorIO(); SysPushErrorIO();

View File

@ -23,7 +23,7 @@ namespace Aurora::Process
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel sectionLock) override; AuFS::EFileAdvisoryLockLevel sectionLock) override;
AuSPtr<IProcessSectionMapView> MapFileByObject(const AuSPtr<Aurora::IO::FS::IFileStream> &stream, AuSPtr<IProcessSectionMapView> MapFileByObject(const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 offset, AuUInt64 offset,
AuUInt length, AuUInt length,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
@ -46,7 +46,7 @@ namespace Aurora::Process
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) override; Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) override;
AuSPtr<IProcessSectionMapView> MapFileByObjectEx(AuUInt viewOffset, AuSPtr<IProcessSectionMapView> MapFileByObjectEx(AuUInt viewOffset,
const AuSPtr<Aurora::IO::FS::IFileStream> &pStream, const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,

View File

@ -89,22 +89,21 @@ namespace Aurora::Process
} }
AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByPath(const AuString &str, AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByPath(const AuString &str,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel sectionLock) AuFS::EFileAdvisoryLockLevel sectionLock)
{ {
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety); return this->MapFileByPathEx(-1, str, uOffset, uLength, mode, sectionLock);
return file ? this->MapFileByObject(file, uOffset, uLength, mode, sectionLock) : AuSPtr<IProcessSectionMapView> {};
} }
AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByObject(const AuSPtr<AuFS::IFileStream> &stream, AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByObject(const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel processLockLevel) AuFS::EFileAdvisoryLockLevel processLockLevel)
{ {
return this->MapFileByObjectEx(-1, stream, uOffset, uLength, mode, processLockLevel); return this->MapFileByObjectEx(-1, pIOHandle, uOffset, uLength, mode, processLockLevel);
} }
AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapIPCMemory(const AuString &handleString, AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapIPCMemory(const AuString &handleString,
@ -170,24 +169,42 @@ namespace Aurora::Process
} }
AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByPathEx(AuUInt viewOffset, AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByPathEx(AuUInt viewOffset,
const AuString &str, const AuString &str,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel)
{ {
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety); auto pHandle = AuIO::IOHandleShared();
return file ? this->MapFileByObjectEx(viewOffset, file, uOffset, uLength, mode, processLockLevel) : AuSPtr<IProcessSectionMapView> {}; if (!pHandle)
{
SysPushErrorMemory();
return nullptr;
}
AuIO::IIOHandle::HandleCreate createhandle(str);
createhandle.eAdvisoryLevel = AuFS::EFileAdvisoryLockLevel::eNoSafety;
createhandle.eMode = mode;
createhandle.bFailIfNonEmptyFile = false;
createhandle.bDirectIOMode = false;
createhandle.bAsyncHandle = false;
if (!pHandle->InitFromPath(createhandle))
{
return nullptr;
}
return this->MapFileByObjectEx(viewOffset, pHandle, uOffset, uLength, mode, processLockLevel);
} }
AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByObjectEx(AuUInt viewOffset, AuSPtr<IProcessSectionMapView> ProcessSectionViewReserved::MapFileByObjectEx(AuUInt viewOffset,
const AuSPtr<Aurora::IO::FS::IFileStream> &pStream, const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel)
{ {
if (!pStream) if (!pIOHandle)
{ {
return {}; return {};
} }
@ -204,8 +221,7 @@ namespace Aurora::Process
return {}; return {};
} }
auto ok = AuStaticCast<AuFS::PosixFileStream>(pStream); int fd = ::dup(pIOHandle->GetOSHandle());
int fd = ::dup(ok->GetHandle());
if (fd == -1) if (fd == -1)
{ {
SysPushErrorIO(); SysPushErrorIO();

View File

@ -30,7 +30,7 @@ namespace Aurora::Process
AuFS::EFileOpenMode mode, AuFS::EFileOpenMode mode,
AuFS::EFileAdvisoryLockLevel sectionLock) override; AuFS::EFileAdvisoryLockLevel sectionLock) override;
AuSPtr<IProcessSectionMapView> MapFileByObject(const AuSPtr<Aurora::IO::FS::IFileStream> &stream, AuSPtr<IProcessSectionMapView> MapFileByObject(const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 offset, AuUInt64 offset,
AuUInt length, AuUInt length,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,
@ -53,7 +53,7 @@ namespace Aurora::Process
Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) override; Aurora::IO::FS::EFileAdvisoryLockLevel processLockLevel) override;
AuSPtr<IProcessSectionMapView> MapFileByObjectEx(AuUInt viewOffset, AuSPtr<IProcessSectionMapView> MapFileByObjectEx(AuUInt viewOffset,
const AuSPtr<Aurora::IO::FS::IFileStream> &pStream, const AuSPtr<IO::IIOHandle> &pIOHandle,
AuUInt64 uOffset, AuUInt64 uOffset,
AuUInt uLength, AuUInt uLength,
Aurora::IO::FS::EFileOpenMode mode, Aurora::IO::FS::EFileOpenMode mode,

View File

@ -154,7 +154,7 @@ namespace Aurora::Processes
{ {
if (::kill(this->pidt_, SIGTERM) == 0) if (::kill(this->pidt_, SIGTERM) == 0)
{ {
return this->finished_->Lock(500); return this->finished_->LockMS(500);
} }
} }
@ -283,6 +283,9 @@ namespace Aurora::Processes
fds[0] = ::open("/dev/null", O_RDWR); fds[0] = ::open("/dev/null", O_RDWR);
fds[1] = ::open("/dev/null", O_RDWR); fds[1] = ::open("/dev/null", O_RDWR);
break; break;
case EStreamForward::eNewConsoleWindow:
SysPushErrorGeneric("AuProcesses is not the right place for PTY support. At least not in this form (this level of abstraction only cares for pipes).");
break;
} }
return true; return true;
@ -310,7 +313,7 @@ namespace Aurora::Processes
if ((this->startup_.fwdIn == EStreamForward::eAsyncPipe) || if ((this->startup_.fwdIn == EStreamForward::eAsyncPipe) ||
(this->startup_.fwdOut == EStreamForward::eAsyncPipe)) (this->startup_.fwdOut == EStreamForward::eAsyncPipe))
{ {
this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>(); this->fsHandle_ = AuIO::IOHandleShared();
if (!this->fsHandle_) if (!this->fsHandle_)
{ {
return false; return false;
@ -322,13 +325,13 @@ namespace Aurora::Processes
return false; return false;
} }
this->fsHandle_->Init(this->pipeStdOut_[0], this->pipeStdIn_[1]); this->fsHandle_->InitFromPairMove(this->pipeStdOut_[0], this->pipeStdIn_[1]);
this->fsStream_->Init(this->fsHandle_); this->fsStream_->Init(this->fsHandle_);
} }
if (this->startup_.fwdErr == EStreamForward::eAsyncPipe) if (this->startup_.fwdErr == EStreamForward::eAsyncPipe)
{ {
this->fsErrorHandle_ = AuMakeShared<IO::FS::FileHandle>(); this->fsErrorHandle_ = AuIO::IOHandleShared();
if (!this->fsErrorHandle_) if (!this->fsErrorHandle_)
{ {
return false; return false;
@ -340,7 +343,7 @@ namespace Aurora::Processes
return false; return false;
} }
this->fsErrorHandle_->Init(this->pipeStdErr_[0], -1); this->fsErrorHandle_->InitFromPairMove(this->pipeStdErr_[0], -1);
this->fsErrorStream_->Init(this->fsErrorHandle_); this->fsErrorStream_->Init(this->fsErrorHandle_);
} }

View File

@ -66,10 +66,10 @@ namespace Aurora::Processes
AuSPtr<IO::Loop::ILSEvent> loopSource_; AuSPtr<IO::Loop::ILSEvent> loopSource_;
AuSPtr<IO::FS::FileHandle> fsHandle_; AuSPtr<IO::IIOHandle> fsHandle_;
AuSPtr<ProcessPipeFileStream> fsStream_; AuSPtr<ProcessPipeFileStream> fsStream_;
AuSPtr<IO::FS::FileHandle> fsErrorHandle_; AuSPtr<IO::IIOHandle> fsErrorHandle_;
AuSPtr<ProcessPipeFileStream> fsErrorStream_; AuSPtr<ProcessPipeFileStream> fsErrorStream_;
AuThreadPrimitives::EventShared_t finished_; AuThreadPrimitives::EventShared_t finished_;

View File

@ -175,7 +175,7 @@ namespace Aurora::RNG
acc = a = b = c = 0; acc = a = b = c = 0;
bits = 8; bits = 8;
void *pASLRSeed = &RngTimeBased; void *pASLRSeed = (void *)&RngTimeBased;
for (AU_ITERATE_N(uOffsetInByteStream, uLen)) for (AU_ITERATE_N(uOffsetInByteStream, uLen))
{ {

View File

@ -13,6 +13,12 @@
#include <timeapi.h> #include <timeapi.h>
#endif #endif
#if defined(AURORA_IS_LINUX_DERIVED)
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
#endif
#include <Time/Time.hpp> #include <Time/Time.hpp>
#define HACK_NO_INVALID_ACCESS_LEAK_SHARED_REF_ON_DESTROYED_THREAD #define HACK_NO_INVALID_ACCESS_LEAK_SHARED_REF_ON_DESTROYED_THREAD
@ -27,6 +33,13 @@ namespace Aurora::Threading
#endif #endif
#if defined(AURORA_IS_LINUX_DERIVED) #if defined(AURORA_IS_LINUX_DERIVED)
static int futex(uint32_t *uaddr, int futex_op, uint32_t val,
const struct timespec *timeout,
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, const struct timespec *timeout) static int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout)
{ {
if (timeout) if (timeout)
@ -466,17 +479,17 @@ namespace Aurora::Threading
static bool RunOSWaitOnAddressNoTimed(const void *pTargetAddress, static bool RunOSWaitOnAddressNoTimed(const void *pTargetAddress,
const void *pCompareAddress, const void *pCompareAddress,
AuUInt8 dwWordSize) AuUInt8 uWordSize)
{ {
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
return pWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, dwWordSize, INFINITE); return pWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, INFINITE);
#endif #endif
#if defined(AURORA_IS_LINUX_DERIVED) #if defined(AURORA_IS_LINUX_DERIVED)
int ret {}; int ret {};
#if defined(AU_CPU_ENDIAN_BIG) #if defined(AU_CPU_ENDIAN_BIG)
if (dwWordSize == 8) if (uWordSize == 8)
{ {
pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4; pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4;
pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4; pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4;
@ -679,7 +692,7 @@ namespace Aurora::Threading
auto uCurrent = *(AuUInt32 *)pCompareAddress; auto uCurrent = *(AuUInt32 *)pCompareAddress;
struct timespec tspec; struct timespec tspec;
Time::auabsns2ts(&tspec, uAbsTimeAltClock ? uAbsTimeAltClock.value() : uAbsTimeSteadyClock); Time::monoabsns2ts(&tspec, uAbsTimeAltClock ? uAbsTimeAltClock.value() : uAbsTimeSteadyClock);
do do
{ {

View File

@ -13,7 +13,8 @@
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
ConditionVariableImpl::ConditionVariableImpl(const AuSPtr<IConditionMutex> &mutex) : mutex_(std::dynamic_pointer_cast<IConditionMutexEx>(mutex)) ConditionVariableImpl::ConditionVariableImpl(const AuSPtr<IConditionMutex> &pMutex) :
mutex_(AuStaticCast<UnixConditionMutex>(pMutex))
{ {
pthread_condattr_t attr; pthread_condattr_t attr;
@ -41,14 +42,20 @@ namespace Aurora::Threading::Primitives
bool ConditionVariableImpl::WaitForSignalNS(AuUInt64 qwTimeout) bool ConditionVariableImpl::WaitForSignalNS(AuUInt64 qwTimeout)
{ {
auto mutex = reinterpret_cast<pthread_mutex_t*>(this->mutex_->GetOSHandle()); return WaitForSignalNsEx(this->mutex_, qwTimeout);
}
bool ConditionVariableImpl::WaitForSignalNsEx(const std::shared_ptr<UnixConditionMutex> &pMutex,
AuUInt64 qwTimeout)
{
auto mutex = reinterpret_cast<pthread_mutex_t*>(pMutex->GetOSHandle());
if (gRuntimeRunLevel >= 5) if (gRuntimeRunLevel >= 5)
{ {
return true; return true;
} }
if (timeout == 0) if (qwTimeout == 0)
{ {
int ret {}; int ret {};
do do
@ -65,7 +72,7 @@ namespace Aurora::Threading::Primitives
else else
{ {
struct timespec tspec; struct timespec tspec;
Time::auabsns2ts(&tspec, AuTime::CurrentClockNS() + qwTimeout); Time::monoabsns2ts(&tspec, AuTime::SteadyClockNS() + qwTimeout);
int ret {}; int ret {};

View File

@ -8,23 +8,33 @@
#pragma once #pragma once
#if !defined(_AURUNTIME_GENERICCV) #if !defined(_AURUNTIME_GENERICCV)
#include "AuConditionMutex.Unix.hpp"
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
struct ConditionVariableImpl : IConditionVariable struct ConditionVariableImpl final : IConditionVariable
{ {
ConditionVariableImpl(const AuSPtr<IConditionMutex> &mutex); ConditionVariableImpl(const AuSPtr<IConditionMutex> &mutex);
~ConditionVariableImpl(); ~ConditionVariableImpl();
AuSPtr<IConditionMutex> GetMutex() override; AuSPtr<IConditionMutex> GetMutex() override;
bool WaitForSignal(AuUInt32 timeout) override; bool WaitForSignal(AuUInt32 timeout) override;
bool WaitForSignalNS(AuUInt64 timeout) override; bool WaitForSignalNsEx(const std::shared_ptr<UnixConditionMutex> &pMutex, AuUInt64 timeout);
bool WaitForSignalNS(AuUInt64 qwTimeout) override;
void Signal() override; void Signal() override;
void Broadcast() override; void Broadcast() override;
// TODO: ...
pthread_cond_t pthreadCv_; pthread_cond_t pthreadCv_;
private: private:
AuSPtr<IConditionMutexEx> mutex_; AuSPtr<UnixConditionMutex> mutex_;
}; };
struct CondVarDummy : IConditionVariable
{
pthread_cond_t pthreadCv_;
};
static const auto kSizeOfDummyCondVar = sizeof(CondVarDummy);
} }
#endif #endif

View File

@ -17,6 +17,9 @@
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
#define barrier() __asm__ __volatile__("sfence": : :"memory")
#define compilerReorderBarrier() __asm__ __volatile__("": : :"memory")
static int futex(uint32_t *uaddr, int futex_op, uint32_t val, static int futex(uint32_t *uaddr, int futex_op, uint32_t val,
const struct timespec *timeout, const struct timespec *timeout,
uint32_t *uaddr2, uint32_t val3) uint32_t *uaddr2, uint32_t val3)
@ -24,26 +27,26 @@ namespace Aurora::Threading::Primitives
return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
} }
static int futex_wait(uint32_t *addr, uint32_t expected) static int futex_wait(volatile uint32_t *addr, uint32_t expected)
{ {
return futex(addr, FUTEX_WAIT, expected, 0, 0, 0); return futex((uint32_t *)addr, FUTEX_WAIT, expected, 0, 0, 0);
} }
static int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout) static int futex_wait(volatile uint32_t *addr, uint32_t expected, const struct timespec *timeout)
{ {
if (timeout) if (timeout)
{ {
return futex(addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); return futex((uint32_t *)addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY);
} }
else else
{ {
return futex(addr, FUTEX_WAIT, expected, timeout, 0, 0); return futex((uint32_t *)addr, FUTEX_WAIT, expected, timeout, 0, 0);
} }
} }
static int futex_wake(uint32_t *addr, uint32_t nthreads) static int futex_wake(volatile uint32_t *addr, uint32_t nthreads)
{ {
return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0); return futex((uint32_t *)addr, FUTEX_WAKE, nthreads, 0, 0, 0);
} }
MutexImpl::MutexImpl() MutexImpl::MutexImpl()
@ -70,8 +73,7 @@ namespace Aurora::Threading::Primitives
{ {
return DoTryIf([=]() return DoTryIf([=]()
{ {
auto old = this->value_; return AuAtomicTestAndSet(&this->state_, 0) == 0;
return (old == 0 && AuAtomicCompareExchange<AuUInt32>(&this->value_, 1, old) == old);
}); });
} }
@ -90,29 +92,36 @@ namespace Aurora::Threading::Primitives
return true; return true;
} }
AuAtomicAdd(&this->dwSleeping_, 1u);
//redundant: 8.2.3.8
//barrier();
struct timespec tspec; struct timespec tspec;
if (uTimeout != 0) if (uTimeout != 0)
{ {
uStart = AuTime::SteadyClockNS(); uStart = AuTime::SteadyClockNS();
uEnd = uStart + uTimeout; uEnd = uStart + uTimeout;
Time::auabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
auto state = this->value_; auto state = this->state_;
while (!(state == 0 && AuAtomicCompareExchange<AuUInt32>(&this->value_, 1, state) == state)) while (!(state == 0 &&
AuAtomicCompareExchange<AuUInt32>(&this->state_, 1, state) == state))
{ {
if (uTimeout != 0) if (uTimeout != 0)
{ {
if (Time::SteadyClockNS() >= uEnd) if (Time::SteadyClockNS() >= uEnd)
{ {
AuAtomicSub(&this->dwSleeping_, 1u);
return false; return false;
} }
int ret {}; int ret {};
do do
{ {
ret = futex_wait(&this->value_, state, &tspec); ret = futex_wait(&this->state_, state, &tspec);
} }
while (ret == EINTR); while (ret == EINTR);
} }
@ -123,7 +132,7 @@ namespace Aurora::Threading::Primitives
do do
{ {
if ((ret = futex_wait(&this->value_, state)) == 0) if ((ret = futex_wait(&this->state_, state)) == 0)
{ {
bStatus = true; bStatus = true;
break; break;
@ -141,13 +150,14 @@ namespace Aurora::Threading::Primitives
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret) RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
} }
state = this->value_; state = this->state_;
} }
AuAtomicSub(&this->dwSleeping_, 1u);
return true; return true;
} }
void MutexImpl::Lock() void MutexImpl::SlowLock()
{ {
auto status = LockMS(0); auto status = LockMS(0);
SysAssert(status, "Couldn't lock mutex"); SysAssert(status, "Couldn't lock mutex");
@ -155,16 +165,20 @@ namespace Aurora::Threading::Primitives
void MutexImpl::Unlock() void MutexImpl::Unlock()
{ {
this->value_ = 0; __sync_lock_release(&this->state_);
futex_wake(&this->value_, 1); compilerReorderBarrier();
if (this->dwSleeping_)
{
futex_wake(&this->state_, 1);
}
} }
AUKN_SYM IWaitable *MutexNew() AUKN_SYM IHyperWaitable *MutexNew()
{ {
return _new MutexImpl(); return _new MutexImpl();
} }
AUKN_SYM void MutexRelease(IWaitable *pMutex) AUKN_SYM void MutexRelease(IHyperWaitable *pMutex)
{ {
AuSafeDelete<MutexImpl *>(pMutex); AuSafeDelete<MutexImpl *>(pMutex);
} }

View File

@ -9,7 +9,7 @@
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
struct MutexImpl : IWaitable struct MutexImpl : IHyperWaitable
{ {
MutexImpl(); MutexImpl();
~MutexImpl(); ~MutexImpl();
@ -17,12 +17,11 @@ namespace Aurora::Threading::Primitives
bool HasOSHandle(AuMach &mach) override; bool HasOSHandle(AuMach &mach) override;
bool TryLock() override; bool TryLock() override;
bool HasLockImplementation() override; bool HasLockImplementation() override;
void Lock() override; void SlowLock() override;
bool LockMS(AuUInt64 timeout) override; bool LockMS(AuUInt64 timeout) override;
bool LockNS(AuUInt64 timeout) override; bool LockNS(AuUInt64 timeout) override;
void Unlock() override; void Unlock() override;
private: private:
AuUInt32 value_ {}; AuUInt32 dwSleeping_ {};
}; };
} }

View File

@ -14,6 +14,9 @@
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
#define barrier() __asm__ __volatile__("sfence": : :"memory")
#define compilerReorderBarrier() __asm__ __volatile__("": : :"memory")
MutexImpl::MutexImpl() MutexImpl::MutexImpl()
{ {
pthread_condattr_t attr; pthread_condattr_t attr;
@ -68,6 +71,8 @@ namespace Aurora::Threading::Primitives
return true; return true;
} }
AuAtomicAdd(&this->dwSleeping_, 1u);
auto mutex = reinterpret_cast<pthread_mutex_t*>(this->mutex_.GetOSHandle()); auto mutex = reinterpret_cast<pthread_mutex_t*>(this->mutex_.GetOSHandle());
struct timespec tspec; struct timespec tspec;
@ -76,7 +81,7 @@ namespace Aurora::Threading::Primitives
uStart = AuTime::SteadyClockNS(); uStart = AuTime::SteadyClockNS();
uEnd = uStart + uTimeout; uEnd = uStart + uTimeout;
Time::auabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
int ret {}; int ret {};
@ -93,6 +98,7 @@ namespace Aurora::Threading::Primitives
{ {
if (Time::SteadyClockNS() >= uEnd) if (Time::SteadyClockNS() >= uEnd)
{ {
AuAtomicSub(&this->dwSleeping_, 1u);
return false; return false;
} }
@ -120,6 +126,7 @@ namespace Aurora::Threading::Primitives
} }
} }
AuAtomicSub(&this->dwSleeping_, 1u);
return true; return true;
} }
@ -131,12 +138,20 @@ namespace Aurora::Threading::Primitives
void MutexImpl::Unlock() void MutexImpl::Unlock()
{ {
__sync_lock_release(&this->value_);
compilerReorderBarrier();
if (this->dwSleeping_)
{ {
AU_LOCK_GUARD(this->mutex_); {
this->value_ = 0; // Still required to barrier the mutually exclusive part of the condvar
AU_LOCK_GUARD(this->mutex_);
//this->value_ = 0;
}
auto ret = ::pthread_cond_signal(&this->pthreadCv_);
SysAssert(ret == 0, "Couldn't wake any mutex waiter");
} }
auto ret = ::pthread_cond_signal(&this->pthreadCv_);
SysAssert(ret == 0, "Couldn't wake any mutex waiter");
} }
AUKN_SYM IWaitable *MutexNew() AUKN_SYM IWaitable *MutexNew()

View File

@ -26,8 +26,8 @@ namespace Aurora::Threading::Primitives
auline bool TryLockNoSpin(); auline bool TryLockNoSpin();
private: private:
AuInt32 value_ {};
pthread_cond_t pthreadCv_ {}; pthread_cond_t pthreadCv_ {};
UnixConditionMutex mutex_; UnixConditionMutex mutex_;
AuUInt32 dwSleeping_ {};
}; };
} }

View File

@ -97,7 +97,7 @@ namespace Aurora::Threading::Primitives
uStart = AuTime::SteadyClockNS(); uStart = AuTime::SteadyClockNS();
uEnd = uStart + uTimeout; uEnd = uStart + uTimeout;
Time::auabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
auto old = this->value_; auto old = this->value_;

View File

@ -78,7 +78,7 @@ namespace Aurora::Threading::Primitives
uStart = AuTime::SteadyClockNS(); uStart = AuTime::SteadyClockNS();
uEnd = uStart + uTimeout; uEnd = uStart + uTimeout;
Time::auabsns2ts(&tspec, uEnd); Time::monoabsns2ts(&tspec, uEnd);
} }
while (!this->TryLock()) while (!this->TryLock())

View File

@ -457,9 +457,11 @@ namespace Aurora::Threading::Threads
auto ret = SpawnThread([this]() auto ret = SpawnThread([this]()
{ {
while ((!this->handle_) || while ((!this->handle_) ||
#if defined(INVALID_HANDLE_VALUE) #if defined(INVALID_HANDLE_VALUE)
(this->handle_ == INVALID_HANDLE_VALUE) (this->handle_ == INVALID_HANDLE_VALUE)
#endif #else
0
#endif
) )
{ {
AuThreading::ContextYield(); AuThreading::ContextYield();
@ -693,6 +695,11 @@ namespace Aurora::Threading::Threads
#elif defined(AURORA_HAS_PTHREADS) #elif defined(AURORA_HAS_PTHREADS)
if (!this->handle_)
{
return;
}
pthread_setname_np(this->handle_, this->name_.c_str()); pthread_setname_np(this->handle_, this->name_.c_str());
#endif #endif
@ -1022,7 +1029,12 @@ namespace Aurora::Threading::Threads
return; return;
#elif defined(AURORA_HAS_PTHREADS) #elif defined(AURORA_HAS_PTHREADS)
if (!this->handle_)
{
return;
}
auto mask2 = mask.And(this->throttleMask_); auto mask2 = mask.And(this->throttleMask_);
if (mask2.CpuBitCount() == 0) if (mask2.CpuBitCount() == 0)

View File

@ -63,6 +63,10 @@ using high_res_clock = std::chrono::high_resolution_clock;
#endif #endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <sys/resource.h>
#endif
using sys_clock = std::chrono::system_clock; using sys_clock = std::chrono::system_clock;
using steady_clock = std::chrono::steady_clock; using steady_clock = std::chrono::steady_clock;

View File

@ -84,12 +84,19 @@ namespace Aurora::Time
ts->tv_nsec = remainderNS; ts->tv_nsec = remainderNS;
} }
static void monoabsns2ts(struct timespec *ts, unsigned long long ns)
{
auto remainderNS = (AuUInt64)ns % (AuUInt64)1'000'000'000;
ts->tv_sec = ns / 1'000'000'000ull;
ts->tv_nsec = remainderNS;
}
static void auabsns2ts(struct timespec *ts, unsigned long long ns) static void auabsns2ts(struct timespec *ts, unsigned long long ns)
{ {
auto baseNS = ns + AuMSToNS<AuUInt64>(999'080'100'000); auto baseNS = ns + AuMSToNS<AuUInt64>(999'080'100'000);
auto remainderNS = (AuUInt64)baseNS % (AuUInt64)1'000'000'000; auto remainderNS = (AuUInt64)baseNS % (AuUInt64)1'000'000'000;
ts->tv_sec += baseNS / 1'000'000'000ull; ts->tv_sec = baseNS / 1'000'000'000ull;
ts->tv_nsec = remainderNS; ts->tv_nsec = remainderNS;
} }