Linux: use futex_waitv syscall for atomic waiting

In order to make this possible, some unnecessary features were removed.
This commit is contained in:
Ivan Chikish 2023-07-31 23:57:26 +03:00 committed by Ivan
parent 831a9fe012
commit d34287b2cc
51 changed files with 441 additions and 574 deletions

View file

@ -2418,7 +2418,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
}
}
if (++i < 10)
if (true || ++i < 10)
{
busy_wait(500);
}
@ -2426,7 +2426,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
{
// Wait
_cpu->state += cpu_flag::wait + cpu_flag::temp;
bits->wait(old, wmask);
// bits->wait(old, wmask);
_cpu->check_state();
}
}())
@ -2542,7 +2542,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
v &= ~wmask;
});
bits->notify_all(wmask);
// bits->notify_all(wmask);
if (size == size0)
{
@ -3588,7 +3588,7 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
{
if (raddr)
{
vm::reservation_notifier(addr).notify_all(-128);
vm::reservation_notifier(addr).notify_all();
raddr = 0;
}
@ -3775,7 +3775,7 @@ void spu_thread::do_putlluc(const spu_mfc_cmd& args)
}
do_cell_atomic_128_store(addr, _ptr<spu_rdata_t>(args.lsa & 0x3ff80));
vm::reservation_notifier(addr).notify_all(-128);
vm::reservation_notifier(addr).notify_all();
}
bool spu_thread::do_mfc(bool can_escape, bool must_finish)
@ -4908,7 +4908,11 @@ s64 spu_thread::get_ch_value(u32 ch)
}
}
#ifdef __linux__
const bool reservation_busy_waiting = false;
#else
const bool reservation_busy_waiting = ((utils::get_tsc() >> 8) % 100 + ((raddr == spurs_addr) ? 50 : 0)) < g_cfg.core.spu_reservation_busy_waiting_percentage;
#endif
for (; !events.count; events = get_events(mask1 & ~SPU_EVENT_LR, true, true))
{
@ -4930,8 +4934,11 @@ s64 spu_thread::get_ch_value(u32 ch)
if (raddr && (mask1 & ~SPU_EVENT_TM) == SPU_EVENT_LR)
{
// Don't busy-wait with TSX - memory is sensitive
if (!reservation_busy_waiting)
if (g_use_rtm || !reservation_busy_waiting)
{
#ifdef __linux__
vm::reservation_notifier(raddr).wait(rtime, atomic_wait_timeout{50'000});
#else
if (raddr - spurs_addr <= 0x80 && !g_cfg.core.spu_accurate_reservations && mask1 == SPU_EVENT_LR)
{
atomic_wait_engine::set_one_time_use_wait_callback(+[](u64) -> bool
@ -4944,7 +4951,7 @@ s64 spu_thread::get_ch_value(u32 ch)
// Wait without timeout, in this situation we have notifications for all writes making it possible
// Abort notifications are handled specially for performance reasons
vm::reservation_notifier(raddr).wait(rtime, -128);
vm::reservation_notifier(raddr).wait(rtime);
continue;
}
@ -4976,7 +4983,8 @@ s64 spu_thread::get_ch_value(u32 ch)
return true;
});
vm::reservation_notifier(raddr).wait(rtime, -128, atomic_wait_timeout{80'000});
vm::reservation_notifier(raddr).wait(rtime, atomic_wait_timeout{80'000});
#endif
}
else
{
@ -5464,7 +5472,7 @@ extern void resume_spu_thread_group_from_waiting(spu_thread& spu)
{
group->run_state = SPU_THREAD_GROUP_STATUS_SUSPENDED;
spu.state += cpu_flag::signal;
spu.state.notify_one(cpu_flag::signal);
spu.state.notify_one();
return;
}
@ -5482,7 +5490,7 @@ extern void resume_spu_thread_group_from_waiting(spu_thread& spu)
thread->state -= cpu_flag::suspend;
}
thread->state.notify_one(cpu_flag::suspend + cpu_flag::signal);
thread->state.notify_one();
}
}
}
@ -6244,7 +6252,7 @@ s64 spu_channel::pop_wait(cpu_thread& spu, bool pop)
while (true)
{
thread_ctrl::wait_on(data, bit_wait);
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(&data)[1], u32{bit_wait >> 32});
old = data;
if (!(old & bit_wait))
@ -6325,7 +6333,7 @@ bool spu_channel::push_wait(cpu_thread& spu, u32 value, bool push)
return false;
}
thread_ctrl::wait_on(data, state);
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(&data)[1], u32(state >> 32));
state = data;
}
}
@ -6369,7 +6377,7 @@ std::pair<u32, u32> spu_channel_4_t::pop_wait(cpu_thread& spu)
while (true)
{
thread_ctrl::wait_on(values, old);
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(&values)[0], u32(u64(std::bit_cast<u128>(old))));
old = values;
if (!old.waiting)