mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-17 01:21:05 +00:00
SPU: Allow special channel storage in channel busy waiting period
Move code to SPUThread.cpp.
This commit is contained in:
parent
48382564d1
commit
07f0ba213e
@ -4083,11 +4083,6 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||||||
do_mfc();
|
do_mfc();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 10 && channel.get_count() == 0; i++)
|
|
||||||
{
|
|
||||||
busy_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
const s64 out = channel.pop_wait(*this);
|
const s64 out = channel.pop_wait(*this);
|
||||||
|
|
||||||
if (state & cpu_flag::wait)
|
if (state & cpu_flag::wait)
|
||||||
@ -4119,11 +4114,6 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||||||
do_mfc();
|
do_mfc();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 10 && ch_in_mbox.get_count() == 0; i++)
|
|
||||||
{
|
|
||||||
busy_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto [old_count, out] = ch_in_mbox.pop_wait(*this);
|
const auto [old_count, out] = ch_in_mbox.pop_wait(*this);
|
||||||
|
|
||||||
if (old_count)
|
if (old_count)
|
||||||
@ -5427,6 +5417,191 @@ spu_thread::priority_t::operator s32() const
|
|||||||
return _this->group->prio;
|
return _this->group->prio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s64 spu_channel::pop_wait(cpu_thread& spu, bool pop)
|
||||||
|
{
|
||||||
|
u64 old = data.fetch_op([&](u64& data)
|
||||||
|
{
|
||||||
|
if (data & bit_count) [[likely]]
|
||||||
|
{
|
||||||
|
if (pop)
|
||||||
|
{
|
||||||
|
data = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = bit_wait;
|
||||||
|
jostling_value.release(bit_wait);
|
||||||
|
return true;
|
||||||
|
}).first;
|
||||||
|
|
||||||
|
if (old & bit_count)
|
||||||
|
{
|
||||||
|
return static_cast<u32>(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
busy_wait();
|
||||||
|
|
||||||
|
if (!(data & bit_wait))
|
||||||
|
{
|
||||||
|
return static_cast<u32>(jostling_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
thread_ctrl::wait_on(data, bit_wait);
|
||||||
|
old = data;
|
||||||
|
|
||||||
|
if (!(old & bit_wait))
|
||||||
|
{
|
||||||
|
return static_cast<u32>(jostling_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spu.is_stopped())
|
||||||
|
{
|
||||||
|
// Abort waiting and test if a value has been received
|
||||||
|
if (u64 v = jostling_value.exchange(0); !(v & bit_wait))
|
||||||
|
{
|
||||||
|
return static_cast<u32>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(data.bit_test_reset(off_wait));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waiting for channel push state availability, actually pushing if specified
|
||||||
|
bool spu_channel::push_wait(cpu_thread& spu, u32 value, bool push)
|
||||||
|
{
|
||||||
|
u64 state{};
|
||||||
|
data.fetch_op([&](u64& data)
|
||||||
|
{
|
||||||
|
if (data & bit_count) [[unlikely]]
|
||||||
|
{
|
||||||
|
jostling_value.release(push ? value : static_cast<u32>(data));
|
||||||
|
data |= bit_wait;
|
||||||
|
}
|
||||||
|
else if (push)
|
||||||
|
{
|
||||||
|
data = bit_count | value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = data;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if (!(state & bit_wait))
|
||||||
|
{
|
||||||
|
if (!push)
|
||||||
|
{
|
||||||
|
data &= ~bit_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
busy_wait();
|
||||||
|
state = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!(state & bit_wait))
|
||||||
|
{
|
||||||
|
if (!push)
|
||||||
|
{
|
||||||
|
data &= ~bit_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spu.is_stopped())
|
||||||
|
{
|
||||||
|
data &= ~bit_wait;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_ctrl::wait_on(data, state);
|
||||||
|
state = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, u32> spu_channel_4_t::pop_wait(cpu_thread& spu)
|
||||||
|
{
|
||||||
|
auto old = values.fetch_op([&](sync_var_t& data)
|
||||||
|
{
|
||||||
|
if (data.count != 0)
|
||||||
|
{
|
||||||
|
data.waiting = 0;
|
||||||
|
data.count--;
|
||||||
|
|
||||||
|
data.value0 = data.value1;
|
||||||
|
data.value1 = data.value2;
|
||||||
|
data.value2 = this->value3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.waiting = 1;
|
||||||
|
jostling_value.release(bit_wait);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (old.count)
|
||||||
|
{
|
||||||
|
return {old.count, old.value0};
|
||||||
|
}
|
||||||
|
|
||||||
|
old.waiting = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
busy_wait();
|
||||||
|
|
||||||
|
if (!atomic_storage<u8>::load(values.raw().waiting))
|
||||||
|
{
|
||||||
|
return {1, static_cast<u32>(jostling_value)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
thread_ctrl::wait_on(values, old);
|
||||||
|
old = values;
|
||||||
|
|
||||||
|
if (!old.waiting)
|
||||||
|
{
|
||||||
|
// Count of 1 because a value has been inserted and popped in the same step.
|
||||||
|
return {1, static_cast<u32>(jostling_value)};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spu.is_stopped())
|
||||||
|
{
|
||||||
|
// Abort waiting and test if a value has been received
|
||||||
|
if (u64 v = jostling_value.exchange(0); !(v & bit_wait))
|
||||||
|
{
|
||||||
|
return {1, static_cast<u32>(v)};
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(atomic_storage<u8>::exchange(values.raw().waiting, 0));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<spu_channel>::format(std::string& out, u64 arg)
|
void fmt_class_string<spu_channel>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
|
@ -297,102 +297,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Waiting for channel pop state availability, actually popping if specified
|
// Waiting for channel pop state availability, actually popping if specified
|
||||||
s64 pop_wait(cpu_thread& spu, bool pop = true)
|
s64 pop_wait(cpu_thread& spu, bool pop = true);
|
||||||
{
|
|
||||||
u64 old = data.fetch_op([&](u64& data)
|
|
||||||
{
|
|
||||||
if (data & bit_count) [[likely]]
|
|
||||||
{
|
|
||||||
if (pop)
|
|
||||||
{
|
|
||||||
data = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = bit_wait;
|
|
||||||
jostling_value.release(bit_wait);
|
|
||||||
return true;
|
|
||||||
}).first;
|
|
||||||
|
|
||||||
if (old & bit_count)
|
|
||||||
{
|
|
||||||
return static_cast<u32>(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
thread_ctrl::wait_on(data, bit_wait);
|
|
||||||
old = data;
|
|
||||||
|
|
||||||
if (!(old & bit_wait))
|
|
||||||
{
|
|
||||||
return static_cast<u32>(jostling_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spu.is_stopped())
|
|
||||||
{
|
|
||||||
// Abort waiting and test if a value has been received
|
|
||||||
if (u64 v = jostling_value.exchange(0); !(v & bit_wait))
|
|
||||||
{
|
|
||||||
return static_cast<u32>(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure(data.bit_test_reset(off_wait));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Waiting for channel push state availability, actually pushing if specified
|
// Waiting for channel push state availability, actually pushing if specified
|
||||||
bool push_wait(cpu_thread& spu, u32 value, bool push = true)
|
bool push_wait(cpu_thread& spu, u32 value, bool push = true);
|
||||||
{
|
|
||||||
u64 state;
|
|
||||||
data.fetch_op([&](u64& data)
|
|
||||||
{
|
|
||||||
if (data & bit_count) [[unlikely]]
|
|
||||||
{
|
|
||||||
jostling_value.release(push ? value : static_cast<u32>(data));
|
|
||||||
data |= bit_wait;
|
|
||||||
}
|
|
||||||
else if (push)
|
|
||||||
{
|
|
||||||
data = bit_count | value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = data;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!(state & bit_wait))
|
|
||||||
{
|
|
||||||
if (!push)
|
|
||||||
{
|
|
||||||
data &= ~bit_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spu.is_stopped())
|
|
||||||
{
|
|
||||||
data &= ~bit_wait;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_ctrl::wait_on(data, state);
|
|
||||||
state = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_value(u32 value, bool count = true)
|
void set_value(u32 value, bool count = true)
|
||||||
{
|
{
|
||||||
@ -504,59 +412,7 @@ struct spu_channel_4_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns [previous count, value] (if aborted 0 count is returned)
|
// Returns [previous count, value] (if aborted 0 count is returned)
|
||||||
std::pair<u32, u32> pop_wait(cpu_thread& spu)
|
std::pair<u32, u32> pop_wait(cpu_thread& spu);
|
||||||
{
|
|
||||||
u32 out_value = 0;
|
|
||||||
auto old = values.fetch_op([&](sync_var_t& data)
|
|
||||||
{
|
|
||||||
if (data.count != 0)
|
|
||||||
{
|
|
||||||
data.waiting = 0;
|
|
||||||
data.count--;
|
|
||||||
out_value = data.value0;
|
|
||||||
|
|
||||||
data.value0 = data.value1;
|
|
||||||
data.value1 = data.value2;
|
|
||||||
data.value2 = this->value3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data.waiting = 1;
|
|
||||||
jostling_value.release(bit_wait);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (old.count)
|
|
||||||
{
|
|
||||||
return {old.count, out_value};
|
|
||||||
}
|
|
||||||
|
|
||||||
old.waiting = 1;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
thread_ctrl::wait_on(values, old);
|
|
||||||
old = values;
|
|
||||||
|
|
||||||
if (!old.waiting)
|
|
||||||
{
|
|
||||||
// Count of 1 because a value has been inserted and popped in the same step.
|
|
||||||
return {1, static_cast<u32>(jostling_value)};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spu.is_stopped())
|
|
||||||
{
|
|
||||||
// Abort waiting and test if a value has been received
|
|
||||||
if (u64 v = jostling_value.exchange(0); !(v & bit_wait))
|
|
||||||
{
|
|
||||||
return {1, static_cast<u32>(v)};
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure(atomic_storage<u8>::exchange(values.raw().waiting, 0));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns current queue size without modification
|
// returns current queue size without modification
|
||||||
uint try_read(u32 (&out)[4]) const
|
uint try_read(u32 (&out)[4]) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user