[*] Begin resolving 8 months of Linux neglect
This commit is contained in:
parent
7100c807c8
commit
1f173a8799
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -10,12 +10,11 @@
|
|||||||
|
|
||||||
namespace Aurora::Debug
|
namespace Aurora::Debug
|
||||||
{
|
{
|
||||||
void PlatformHandleFatal(bool fatal)
|
void PlatformHandleFatal(bool fatal, bool bNoExit)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InitUNIX()
|
void InitUNIX()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
174
Source/IO/AuIOHandle.Unix.cpp
Normal file
174
Source/IO/AuIOHandle.Unix.cpp
Normal 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)
|
||||||
|
}
|
13
Source/IO/AuIOHandle.Unix.hpp
Normal file
13
Source/IO/AuIOHandle.Unix.hpp
Normal 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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -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:
|
||||||
|
@ -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 ¶meters)
|
|
||||||
{
|
|
||||||
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 ¶meters)
|
||||||
|
{
|
||||||
|
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 ¶meters)
|
bool LinuxAsyncFileStream::BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead ¶meters)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
@ -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 ¶meters) override;
|
bool BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite ¶meters) override;
|
||||||
bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead ¶meters) override;
|
bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead ¶meters) 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 {};
|
||||||
|
@ -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));
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 ¶meters)
|
bool PosixFileStream::Read(const Memory::MemoryViewStreamWrite ¶meters)
|
||||||
@ -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)
|
||||||
|
@ -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 {};
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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];
|
||||||
|
@ -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();
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
@ -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) ||
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
|
@ -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_ } });
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_;
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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 {};
|
||||||
|
|
||||||
|
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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_ {};
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -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()
|
||||||
|
@ -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_ {};
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -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_;
|
||||||
|
@ -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())
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user