mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00:00
Implement util/fifo_mutex.hpp
Prototype. Uses 2 bytes. Added minor fix to slow_mutex.hpp as well.
This commit is contained in:
parent
5227e65808
commit
8a5620592b
@ -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" />
|
||||
|
@ -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
70
rpcs3/util/fifo_mutex.hpp
Normal 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();
|
||||
}
|
||||
}
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user