Implement util/fifo_mutex.hpp

Prototype. Uses 2 bytes.
Added minor fix to slow_mutex.hpp as well.
This commit is contained in:
Nekotekina 2020-12-31 20:04:16 +03:00
parent 5227e65808
commit 8a5620592b
4 changed files with 81 additions and 2 deletions

View File

@ -498,6 +498,8 @@
<ClInclude Include="util\fixed_typemap.hpp" />
<ClInclude Include="util\auto_typemap.hpp" />
<ClInclude Include="util\init_mutex.hpp" />
<ClInclude Include="util\slow_mutex.hpp" />
<ClInclude Include="util\fifo_mutex.hpp" />
<ClInclude Include="util\logs.hpp" />
<ClInclude Include="..\Utilities\dyn_lib.hpp" />
<ClInclude Include="..\Utilities\File.h" />

View File

@ -1831,6 +1831,12 @@
<ClInclude Include="util\init_mutex.hpp">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="util\slow_mutex.hpp">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="util\fifo_mutex.hpp">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="util\logs.hpp">
<Filter>Utilities</Filter>
</ClInclude>

70
rpcs3/util/fifo_mutex.hpp Normal file
View File

@ -0,0 +1,70 @@
#pragma once
#include "util/types.hpp"
#include "util/atomic.hpp"
#include <mutex>
// Mutex that tries to maintain the order of acquisition
class fifo_mutex
{
// Low 8 bits are incremented on acquisition, high 8 bits are incremented on release
atomic_t<u16> m_value{0};
public:
constexpr fifo_mutex() noexcept = default;
void lock() noexcept
{
const u16 val = m_value.fetch_op([](u16& val)
{
val = (val & 0xff00) | ((val + 1) & 0xff);
});
if (val >> 8 != (val & 0xff)) [[unlikely]]
{
// TODO: implement busy waiting along with moving to cpp file
m_value.wait<atomic_wait::op_ne>(((val + 1) & 0xff) << 8, 0xff00);
}
}
bool try_lock() noexcept
{
const u16 val = m_value.load();
if (val >> 8 == (val & 0xff))
{
if (m_value.compare_and_swap(val, ((val + 1) & 0xff) | (val & 0xff00)))
{
return true;
}
}
return false;
}
void unlock() noexcept
{
const u16 val = m_value.add_fetch(0x100);
if (val >> 8 != (val & 0xff))
{
m_value.notify_one();
}
}
bool is_free() const noexcept
{
const u16 val = m_value.load();
return (val >> 8) == (val & 0xff);
}
void lock_unlock() noexcept
{
if (!is_free())
{
lock();
unlock();
}
}
};

View File

@ -1,6 +1,7 @@
#pragma once
#include "atomic.hpp"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include "Utilities/StrFmt.h"
#include <mutex>
@ -79,7 +80,7 @@ public:
}
}
bool is_free() noexcept
bool is_free() const noexcept
{
return !m_value;
}