mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
SPU: Self-notifying SPU waiters
This commit is contained in:
parent
cfe1eca185
commit
fc62733d65
|
|
@ -6094,6 +6094,9 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static atomic_t<u8> s_is_reservation_data_checking_thread = false;
|
||||||
|
bool is_reservation_data_checking_thread = false;
|
||||||
|
|
||||||
const bool is_LR_wait = raddr && mask1 & SPU_EVENT_LR;
|
const bool is_LR_wait = raddr && mask1 & SPU_EVENT_LR;
|
||||||
|
|
||||||
auto& history = eventstat_wait_time[(raddr % SPU_LS_SIZE) / 128];
|
auto& history = eventstat_wait_time[(raddr % SPU_LS_SIZE) / 128];
|
||||||
|
|
@ -6118,6 +6121,16 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
u8& val = history.front();
|
u8& val = history.front();
|
||||||
val = static_cast<u8>(std::min<u32>(val + 1, u8{umax}));
|
val = static_cast<u8>(std::min<u32>(val + 1, u8{umax}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s_is_reservation_data_checking_thread)// && std::find(raddr_busy_wait_addr.begin(), raddr_busy_wait_addr.end(), raddr) != raddr_busy_wait_addr.end())
|
||||||
|
{
|
||||||
|
if (s_is_reservation_data_checking_thread.compare_and_swap_test(0, 1))
|
||||||
|
{
|
||||||
|
eventstat_busy_waiting_switch = 1;
|
||||||
|
is_reservation_data_checking_thread = true;
|
||||||
|
eventstat_raddr = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -6145,11 +6158,15 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
|
|
||||||
if (is_stopped(old))
|
if (is_stopped(old))
|
||||||
{
|
{
|
||||||
if (cache_line_waiter_index != umax)
|
if (is_reservation_data_checking_thread)
|
||||||
{
|
{
|
||||||
g_spu_waiters_by_value[cache_line_waiter_index].release(0);
|
s_is_reservation_data_checking_thread = 0;
|
||||||
|
|
||||||
|
// Check again other reservations in other threads
|
||||||
|
lv2_obj::notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deregister_cache_line_waiter(cache_line_waiter_index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6169,6 +6186,14 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
}
|
}
|
||||||
else if (!cmp_rdata(rdata, *resrv_mem))
|
else if (!cmp_rdata(rdata, *resrv_mem))
|
||||||
{
|
{
|
||||||
|
if (vm::reservation_acquire(raddr) == rtime)
|
||||||
|
{
|
||||||
|
// Confirm change in data only, register address for busy waiting
|
||||||
|
std::rotate(raddr_busy_wait_addr.rbegin(), raddr_busy_wait_addr.rbegin() + 1, raddr_busy_wait_addr.rend());
|
||||||
|
raddr_busy_wait_addr[0] = raddr;
|
||||||
|
vm::reservation_update(raddr);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify threads manually, memory data has likely changed and broke the reservation for others
|
// Notify threads manually, memory data has likely changed and broke the reservation for others
|
||||||
if (vm::reservation_notifier_count(raddr, rtime) && vm::reservation_acquire(raddr) == rtime)
|
if (vm::reservation_notifier_count(raddr, rtime) && vm::reservation_acquire(raddr) == rtime)
|
||||||
{
|
{
|
||||||
|
|
@ -6198,7 +6223,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
// Don't be stubborn, force operating sleep if too much time has passed
|
// Don't be stubborn, force operating sleep if too much time has passed
|
||||||
const u64 time_since = get_system_time() - eventstat_evaluate_time;
|
const u64 time_since = get_system_time() - eventstat_evaluate_time;
|
||||||
|
|
||||||
if (time_since >= (utils::get_thread_count() >= 9 ? 50'000 : 3000))
|
if (!is_reservation_data_checking_thread && time_since >= (utils::get_thread_count() >= 9 ? 50'000 : 3000))
|
||||||
{
|
{
|
||||||
spu_log.trace("SPU RdEventStat wait for 0x%x failed", raddr);
|
spu_log.trace("SPU RdEventStat wait for 0x%x failed", raddr);
|
||||||
history.front() = 2;
|
history.front() = 2;
|
||||||
|
|
@ -6357,6 +6382,12 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
}
|
}
|
||||||
else if (!cmp_rdata(_this->rdata, *_this->resrv_mem))
|
else if (!cmp_rdata(_this->rdata, *_this->resrv_mem))
|
||||||
{
|
{
|
||||||
|
if (vm::reservation_acquire(raddr) == _this->rtime)
|
||||||
|
{
|
||||||
|
std::rotate(_this->raddr_busy_wait_addr.rbegin(), _this->raddr_busy_wait_addr.rbegin() + 1, _this->raddr_busy_wait_addr.rend());
|
||||||
|
_this->raddr_busy_wait_addr[0] = raddr;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify threads manually, memory data has likely changed and broke the reservation for others
|
// Notify threads manually, memory data has likely changed and broke the reservation for others
|
||||||
if (vm::reservation_notifier_count(raddr, _this->rtime) >= 2 && vm::reservation_acquire(raddr) == _this->rtime)
|
if (vm::reservation_notifier_count(raddr, _this->rtime) >= 2 && vm::reservation_acquire(raddr) == _this->rtime)
|
||||||
{
|
{
|
||||||
|
|
@ -6408,11 +6439,19 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
thread_ctrl::wait_on(state, old, 100);
|
thread_ctrl::wait_on(state, old, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_reservation_data_checking_thread)
|
||||||
|
{
|
||||||
|
s_is_reservation_data_checking_thread = 0;
|
||||||
|
|
||||||
|
// Check again other reservations in other threads
|
||||||
|
lv2_obj::notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
deregister_cache_line_waiter(cache_line_waiter_index);
|
deregister_cache_line_waiter(cache_line_waiter_index);
|
||||||
|
|
||||||
wakeup_delay();
|
const auto old = +state;
|
||||||
|
|
||||||
if (is_paused(state - cpu_flag::suspend))
|
if (is_paused(old - cpu_flag::suspend))
|
||||||
{
|
{
|
||||||
if (!raddr && old_raddr)
|
if (!raddr && old_raddr)
|
||||||
{
|
{
|
||||||
|
|
@ -6422,6 +6461,10 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||||
raddr = 0;
|
raddr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!is_stopped(old))
|
||||||
|
{
|
||||||
|
wakeup_delay();
|
||||||
|
}
|
||||||
|
|
||||||
check_state();
|
check_state();
|
||||||
return events.events & mask1;
|
return events.events & mask1;
|
||||||
|
|
|
||||||
|
|
@ -824,6 +824,7 @@ public:
|
||||||
u8 cpu_work_iteration_count = 0;
|
u8 cpu_work_iteration_count = 0;
|
||||||
|
|
||||||
std::array<v128, 0x4000> stack_mirror; // Return address information
|
std::array<v128, 0x4000> stack_mirror; // Return address information
|
||||||
|
std::array<u32, 8> raddr_busy_wait_addr{}; // Return address information
|
||||||
|
|
||||||
const char* current_func{}; // Current STOP or RDCH blocking function
|
const char* current_func{}; // Current STOP or RDCH blocking function
|
||||||
u64 start_time{}; // Starting time of STOP or RDCH bloking function
|
u64 start_time{}; // Starting time of STOP or RDCH bloking function
|
||||||
|
|
|
||||||
|
|
@ -2337,6 +2337,7 @@ void lv2_obj::notify_all() noexcept
|
||||||
{
|
{
|
||||||
if (notifies[i])
|
if (notifies[i])
|
||||||
{
|
{
|
||||||
|
vm::reservation_update(notifies[i]);
|
||||||
vm::reservation_notifier_notify(notifies[i], notifies_time[i]);
|
vm::reservation_notifier_notify(notifies[i], notifies_time[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue