mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-07 03:40:07 +00:00
rsx: Avoid semaphore acquire deadlock
This commit is contained in:
parent
3d632a3774
commit
6362942928
@ -301,10 +301,15 @@ void D3D12GSRender::on_exit()
|
||||
return GSRender::on_exit();
|
||||
}
|
||||
|
||||
void D3D12GSRender::do_local_task(bool)
|
||||
void D3D12GSRender::do_local_task(rsx::FIFO_state state)
|
||||
{
|
||||
//TODO
|
||||
m_frame->clear_wm_events();
|
||||
if (state != rsx::FIFO_state::lock_wait)
|
||||
{
|
||||
//TODO
|
||||
m_frame->clear_wm_events();
|
||||
}
|
||||
|
||||
rsx::thread::do_local_task(state);
|
||||
}
|
||||
|
||||
bool D3D12GSRender::do_method(u32 cmd, u32 arg)
|
||||
|
@ -173,7 +173,7 @@ private:
|
||||
protected:
|
||||
virtual void on_init_thread() override;
|
||||
virtual void on_exit() override;
|
||||
virtual void do_local_task(bool idle) override;
|
||||
virtual void do_local_task(rsx::FIFO_state state) override;
|
||||
virtual bool do_method(u32 cmd, u32 arg) override;
|
||||
virtual void end() override;
|
||||
virtual void flip(int buffer) override;
|
||||
|
@ -1582,10 +1582,8 @@ void GLGSRender::on_invalidate_memory_range(u32 address_base, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void GLGSRender::do_local_task(bool idle)
|
||||
void GLGSRender::do_local_task(rsx::FIFO_state state)
|
||||
{
|
||||
m_frame->clear_wm_events();
|
||||
|
||||
if (!work_queue.empty())
|
||||
{
|
||||
std::lock_guard<shared_mutex> lock(queue_guard);
|
||||
@ -1605,13 +1603,23 @@ void GLGSRender::do_local_task(bool idle)
|
||||
q.cv.notify_one();
|
||||
}
|
||||
}
|
||||
else if (!in_begin_end)
|
||||
else if (!in_begin_end && state != rsx::FIFO_state::lock_wait)
|
||||
{
|
||||
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
||||
//Only call when there are no waiters
|
||||
m_gl_texture_cache.do_update();
|
||||
}
|
||||
|
||||
rsx::thread::do_local_task(state);
|
||||
|
||||
if (state == rsx::FIFO_state::lock_wait)
|
||||
{
|
||||
// Critical check finished
|
||||
return;
|
||||
}
|
||||
|
||||
m_frame->clear_wm_events();
|
||||
|
||||
if (m_overlay_manager)
|
||||
{
|
||||
if (!in_begin_end && native_ui_flip_request.load())
|
||||
@ -1620,8 +1628,6 @@ void GLGSRender::do_local_task(bool idle)
|
||||
flip((s32)current_display_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
rsx::thread::do_local_task(idle);
|
||||
}
|
||||
|
||||
work_item& GLGSRender::post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data)
|
||||
|
@ -381,7 +381,7 @@ protected:
|
||||
bool do_method(u32 id, u32 arg) override;
|
||||
void flip(int buffer) override;
|
||||
|
||||
void do_local_task(bool idle) override;
|
||||
void do_local_task(rsx::FIFO_state state) override;
|
||||
|
||||
bool on_access_violation(u32 address, bool is_writing) override;
|
||||
void on_invalidate_memory_range(u32 address_base, u32 size) override;
|
||||
|
@ -513,7 +513,7 @@ namespace rsx
|
||||
}
|
||||
|
||||
//Execute backend-local tasks first
|
||||
do_local_task(performance_counters.state != FIFO_state::running);
|
||||
do_local_task(performance_counters.state);
|
||||
|
||||
//Update sub-units
|
||||
zcull_ctrl->update(this);
|
||||
@ -1290,9 +1290,9 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void thread::do_local_task(bool /*idle*/)
|
||||
void thread::do_local_task(FIFO_state state)
|
||||
{
|
||||
if (!in_begin_end)
|
||||
if (!in_begin_end && state != FIFO_state::lock_wait)
|
||||
{
|
||||
if (!m_invalidated_memory_ranges.empty())
|
||||
{
|
||||
|
@ -87,6 +87,7 @@ namespace rsx
|
||||
empty = 1, // PUT == GET
|
||||
spinning = 2, // Puller continuously jumps to self addr (synchronization technique)
|
||||
nop = 3, // Puller is processing a NOP command
|
||||
lock_wait = 4 // Puller is processing a lock acquire
|
||||
};
|
||||
|
||||
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size);
|
||||
@ -417,9 +418,8 @@ namespace rsx
|
||||
|
||||
/**
|
||||
* Execute a backend local task queue
|
||||
* Idle argument checks that the FIFO queue is in an idle state
|
||||
*/
|
||||
virtual void do_local_task(bool idle);
|
||||
virtual void do_local_task(FIFO_state state);
|
||||
|
||||
public:
|
||||
virtual std::string get_name() const override;
|
||||
@ -545,6 +545,11 @@ namespace rsx
|
||||
*/
|
||||
void on_notify_memory_unmapped(u32 address_base, u32 size);
|
||||
|
||||
/**
|
||||
* Notify to check internal state during semaphore wait
|
||||
*/
|
||||
void on_semaphore_acquire_wait() { do_local_task(FIFO_state::lock_wait); }
|
||||
|
||||
/**
|
||||
* Copy rtt values to buffer.
|
||||
* TODO: It's more efficient to combine multiple call of this function into one.
|
||||
|
@ -857,9 +857,6 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
|
||||
if (target_cb)
|
||||
target_cb->wait();
|
||||
|
||||
if (is_rsxthr)
|
||||
m_last_flushable_cb = -1;
|
||||
}
|
||||
|
||||
if (has_queue_ref)
|
||||
@ -1858,7 +1855,6 @@ void VKGSRender::copy_render_targets_to_dma_location()
|
||||
|
||||
vk::leave_uninterruptible();
|
||||
|
||||
m_last_flushable_cb = m_current_cb_index;
|
||||
flush_command_queue();
|
||||
|
||||
m_flush_draw_buffers = false;
|
||||
@ -1884,7 +1880,6 @@ void VKGSRender::flush_command_queue(bool hard_sync)
|
||||
cb.poke();
|
||||
}
|
||||
|
||||
m_last_flushable_cb = -1;
|
||||
m_flush_requests.clear_pending_flag();
|
||||
}
|
||||
else
|
||||
@ -1904,9 +1899,6 @@ void VKGSRender::flush_command_queue(bool hard_sync)
|
||||
}
|
||||
|
||||
m_current_command_buffer->reset();
|
||||
|
||||
if (m_last_flushable_cb == m_current_cb_index)
|
||||
m_last_flushable_cb = -1;
|
||||
}
|
||||
|
||||
open_command_buffer();
|
||||
@ -2089,7 +2081,7 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources)
|
||||
ctx->swap_command_buffer = nullptr;
|
||||
}
|
||||
|
||||
void VKGSRender::do_local_task(bool idle)
|
||||
void VKGSRender::do_local_task(rsx::FIFO_state state)
|
||||
{
|
||||
if (m_flush_requests.pending())
|
||||
{
|
||||
@ -2102,22 +2094,19 @@ void VKGSRender::do_local_task(bool idle)
|
||||
m_flush_requests.clear_pending_flag();
|
||||
m_flush_requests.consumer_wait();
|
||||
}
|
||||
else if (!in_begin_end)
|
||||
else if (!in_begin_end && state != rsx::FIFO_state::lock_wait)
|
||||
{
|
||||
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
||||
//Only call when there are no waiters
|
||||
m_texture_cache.do_update();
|
||||
}
|
||||
|
||||
if (m_last_flushable_cb > -1)
|
||||
rsx::thread::do_local_task(state);
|
||||
|
||||
if (state == rsx::FIFO_state::lock_wait)
|
||||
{
|
||||
auto cb = &m_primary_cb_list[m_last_flushable_cb];
|
||||
|
||||
if (cb->pending)
|
||||
cb->poke();
|
||||
|
||||
if (!cb->pending)
|
||||
m_last_flushable_cb = -1;
|
||||
// Critical check finished
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -2208,8 +2197,6 @@ void VKGSRender::do_local_task(bool idle)
|
||||
flip((s32)current_display_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
rsx::thread::do_local_task(idle);
|
||||
}
|
||||
|
||||
bool VKGSRender::do_method(u32 cmd, u32 arg)
|
||||
|
@ -351,7 +351,6 @@ private:
|
||||
|
||||
u8 m_draw_buffers_count = 0;
|
||||
bool m_flush_draw_buffers = false;
|
||||
std::atomic<int> m_last_flushable_cb = {-1 };
|
||||
|
||||
shared_mutex m_flush_queue_mutex;
|
||||
flush_request_task m_flush_requests;
|
||||
@ -420,7 +419,7 @@ protected:
|
||||
bool do_method(u32 id, u32 arg) override;
|
||||
void flip(int buffer) override;
|
||||
|
||||
void do_local_task(bool idle) override;
|
||||
void do_local_task(rsx::FIFO_state state) override;
|
||||
bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override;
|
||||
void notify_tile_unbound(u32 tile) override;
|
||||
|
||||
|
@ -78,35 +78,31 @@ namespace rsx
|
||||
if (Emu.IsStopped())
|
||||
return;
|
||||
|
||||
const auto tdr = (u64)g_cfg.video.driver_recovery_timeout;
|
||||
if (tdr == 0)
|
||||
if (const auto tdr = (u64)g_cfg.video.driver_recovery_timeout)
|
||||
{
|
||||
//No timeout
|
||||
std::this_thread::yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
while (Emu.IsPaused())
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
while (Emu.IsPaused())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
//Reset
|
||||
start = get_system_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((get_system_time() - start) > tdr)
|
||||
// Reset
|
||||
start = get_system_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
//If longer than driver timeout force exit
|
||||
LOG_ERROR(RSX, "nv406e::semaphore_acquire has timed out. semaphore_address=0x%X", addr);
|
||||
break;
|
||||
if ((get_system_time() - start) > tdr)
|
||||
{
|
||||
// If longer than driver timeout force exit
|
||||
LOG_ERROR(RSX, "nv406e::semaphore_acquire has timed out. semaphore_address=0x%X", addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
rsx->on_semaphore_acquire_wait();
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
rsx->performance_counters.idle_time += (get_system_time() - start);
|
||||
|
Loading…
x
Reference in New Issue
Block a user