/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: LSMutex.Linux.cpp Date: 2021-10-1 Date: 2022-4-4 Author: Reece ***/ #include #include "LSMutex.hpp" #include "LSFromFdNonblocking.hpp" namespace Aurora::IO::Loop { LSMutex::LSMutex() { Init(); } LSMutex::LSMutex(int handle) { this->handle = handle; } LSMutex::~LSMutex() { if ((!this->bOwns) && (!this->bNoAutoRel /*must the remote grug clean up the IPC mutex? lets not hit a double unlock assert...*/)) { SysPushErrorIO("Mutex owned by calling process during destruction... Forcefully unlocking..."); Unlock(); } if ((this->handle != 0) && (this->handle != -1)) { ::close(AuExchange(this->handle, -1)); } } bool LSMutex::OnTrigger(AuUInt handle) { return IsSignaledNonblocking(); } void LSMutex::Init() { handle = ::eventfd(1, EFD_NONBLOCK); } bool LSMutex::Unlock() { AuUInt64 plsNoOverflow {1}; bool ok = ::write(this->handle, &plsNoOverflow, sizeof(plsNoOverflow)) == 8; if (ok) { this->bOwns = false; } return ok; } bool LSMutex::IsSignaled() { return IsSignaledFromNonblockingImpl(this, this, &LSMutex::IsSignaledNonblocking); } bool LSMutex::WaitOn(AuUInt32 timeout) { return LSHandle::WaitOn(timeout); } bool LSMutex::IsSignaledNonblocking() { AuUInt64 oldSemaphoreValue {}; auto read = ::read(this->handle, &oldSemaphoreValue, sizeof(oldSemaphoreValue)); auto ok = read == 8; SysAssertDbg(!ok || oldSemaphoreValue == 1, "Double unlock caught"); if (!ok) { // TODO: Might hook here } else { this->bOwns = true; } return ok; } ELoopSource LSMutex::GetType() { return ELoopSource::eSourceMutex; } AUKN_SYM AuSPtr NewLSMutex() { auto mutex = AuMakeShared(); if (!mutex) { return {}; } if (!mutex->HasValidHandle()) { return {}; } return mutex; } }