mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
SMutex eliminated
This commit is contained in:
parent
0fb092f2a5
commit
b2de24db73
48 changed files with 768 additions and 907 deletions
|
|
@ -30,7 +30,7 @@ public:
|
|||
{
|
||||
//wait until there's actually something to get
|
||||
//throwing an exception might be better, blocking here is a little awkward
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
size_t ret = mGet;
|
||||
mGet = moveGet();
|
||||
|
|
@ -45,7 +45,7 @@ public:
|
|||
{
|
||||
//if this is reached a lot it's time to increase the buffer size
|
||||
//or implement dynamic re-sizing
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
mBuffer[mPut] = std::forward(putEle);
|
||||
mPut = movePut();
|
||||
|
|
@ -94,7 +94,7 @@ public:
|
|||
{
|
||||
//if this is reached a lot it's time to increase the buffer size
|
||||
//or implement dynamic re-sizing
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
if (mPut + length <= mBuffer.size())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
bool SM_IsAborted()
|
||||
{
|
||||
return Emu.IsStopped();
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
bool SM_IsAborted();
|
||||
|
||||
enum SMutexResult
|
||||
{
|
||||
SMR_OK = 0, // succeeded (lock, trylock, unlock)
|
||||
SMR_FAILED, // failed (trylock, unlock)
|
||||
SMR_DEADLOCK, // mutex reached deadlock (lock, trylock)
|
||||
SMR_SIGNAL = SMR_DEADLOCK, // unlock can be used for signaling specific thread
|
||||
SMR_PERMITTED, // not owner of the mutex (unlock)
|
||||
SMR_ABORT, // emulator has been stopped (lock, trylock, unlock)
|
||||
SMR_DESTROYED, // mutex has been destroyed (lock, trylock, unlock)
|
||||
SMR_TIMEOUT, // timed out (lock)
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
const u64 free_value = 0,
|
||||
const u64 dead_value = 0xffffffffffffffffull
|
||||
>
|
||||
class SMutexBase
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(atomic_le_t<T>), "Invalid SMutexBase type");
|
||||
T owner;
|
||||
typedef atomic_le_t<T> AT;
|
||||
|
||||
public:
|
||||
static const T GetFreeValue()
|
||||
{
|
||||
static const u64 value = free_value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
static const T GetDeadValue()
|
||||
{
|
||||
static const u64 value = dead_value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
owner = GetFreeValue();
|
||||
}
|
||||
|
||||
void finalize()
|
||||
{
|
||||
owner = GetDeadValue();
|
||||
}
|
||||
|
||||
__forceinline T GetOwner() const
|
||||
{
|
||||
return (T&)owner;
|
||||
}
|
||||
|
||||
SMutexResult trylock(T tid)
|
||||
{
|
||||
if (SM_IsAborted())
|
||||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(GetFreeValue(), tid);
|
||||
|
||||
if (old != GetFreeValue())
|
||||
{
|
||||
if (old == tid)
|
||||
{
|
||||
return SMR_DEADLOCK;
|
||||
}
|
||||
if (old == GetDeadValue())
|
||||
{
|
||||
return SMR_DESTROYED;
|
||||
}
|
||||
return SMR_FAILED;
|
||||
}
|
||||
|
||||
return SMR_OK;
|
||||
}
|
||||
|
||||
SMutexResult unlock(T tid, T to = GetFreeValue())
|
||||
{
|
||||
if (SM_IsAborted())
|
||||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(tid, to);
|
||||
|
||||
if (old != tid)
|
||||
{
|
||||
if (old == GetFreeValue())
|
||||
{
|
||||
return SMR_FAILED;
|
||||
}
|
||||
if (old == GetDeadValue())
|
||||
{
|
||||
return SMR_DESTROYED;
|
||||
}
|
||||
|
||||
return SMR_PERMITTED;
|
||||
}
|
||||
|
||||
return SMR_OK;
|
||||
}
|
||||
|
||||
SMutexResult lock(T tid, u64 timeout = 0)
|
||||
{
|
||||
u64 counter = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (SMutexResult res = trylock(tid))
|
||||
{
|
||||
case SMR_FAILED: break;
|
||||
default: return res;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
if (timeout && counter++ > timeout)
|
||||
{
|
||||
return SMR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef SMutexBase<u32> SMutex;
|
||||
|
|
@ -38,7 +38,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,10 +160,10 @@ public:
|
|||
// register waiter
|
||||
waiter_reg_t waiter(*this, signal_id);
|
||||
|
||||
// check condition or if emulator is stopped
|
||||
// check the condition or if the emulator is stopped
|
||||
while (!waiter_func() && !is_stopped(signal_id))
|
||||
{
|
||||
// initialize waiter (only first time)
|
||||
// initialize waiter (only once)
|
||||
waiter.init();
|
||||
// wait for 1 ms or until signal arrived
|
||||
waiter.thread->WaitForAnySignal(1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue