mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 08:51:28 +12:00
rsx: Avoid semaphore acquire deadlock
This commit is contained in:
parent
3d632a3774
commit
6362942928
9 changed files with 59 additions and 61 deletions
|
@ -301,10 +301,15 @@ void D3D12GSRender::on_exit()
|
||||||
return GSRender::on_exit();
|
return GSRender::on_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12GSRender::do_local_task(bool)
|
void D3D12GSRender::do_local_task(rsx::FIFO_state state)
|
||||||
{
|
{
|
||||||
//TODO
|
if (state != rsx::FIFO_state::lock_wait)
|
||||||
m_frame->clear_wm_events();
|
{
|
||||||
|
//TODO
|
||||||
|
m_frame->clear_wm_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rsx::thread::do_local_task(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12GSRender::do_method(u32 cmd, u32 arg)
|
bool D3D12GSRender::do_method(u32 cmd, u32 arg)
|
||||||
|
|
|
@ -173,7 +173,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual void on_init_thread() override;
|
virtual void on_init_thread() override;
|
||||||
virtual void on_exit() 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 bool do_method(u32 cmd, u32 arg) override;
|
||||||
virtual void end() override;
|
virtual void end() override;
|
||||||
virtual void flip(int buffer) 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())
|
if (!work_queue.empty())
|
||||||
{
|
{
|
||||||
std::lock_guard<shared_mutex> lock(queue_guard);
|
std::lock_guard<shared_mutex> lock(queue_guard);
|
||||||
|
@ -1605,13 +1603,23 @@ void GLGSRender::do_local_task(bool idle)
|
||||||
q.cv.notify_one();
|
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!
|
//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
|
//Only call when there are no waiters
|
||||||
m_gl_texture_cache.do_update();
|
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 (m_overlay_manager)
|
||||||
{
|
{
|
||||||
if (!in_begin_end && native_ui_flip_request.load())
|
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);
|
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)
|
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;
|
bool do_method(u32 id, u32 arg) override;
|
||||||
void flip(int buffer) 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;
|
bool on_access_violation(u32 address, bool is_writing) override;
|
||||||
void on_invalidate_memory_range(u32 address_base, u32 size) override;
|
void on_invalidate_memory_range(u32 address_base, u32 size) override;
|
||||||
|
|
|
@ -513,7 +513,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
//Execute backend-local tasks first
|
//Execute backend-local tasks first
|
||||||
do_local_task(performance_counters.state != FIFO_state::running);
|
do_local_task(performance_counters.state);
|
||||||
|
|
||||||
//Update sub-units
|
//Update sub-units
|
||||||
zcull_ctrl->update(this);
|
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())
|
if (!m_invalidated_memory_ranges.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace rsx
|
||||||
empty = 1, // PUT == GET
|
empty = 1, // PUT == GET
|
||||||
spinning = 2, // Puller continuously jumps to self addr (synchronization technique)
|
spinning = 2, // Puller continuously jumps to self addr (synchronization technique)
|
||||||
nop = 3, // Puller is processing a NOP command
|
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);
|
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
|
* 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:
|
public:
|
||||||
virtual std::string get_name() const override;
|
virtual std::string get_name() const override;
|
||||||
|
@ -545,6 +545,11 @@ namespace rsx
|
||||||
*/
|
*/
|
||||||
void on_notify_memory_unmapped(u32 address_base, u32 size);
|
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.
|
* Copy rtt values to buffer.
|
||||||
* TODO: It's more efficient to combine multiple call of this function into one.
|
* 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)
|
if (target_cb)
|
||||||
target_cb->wait();
|
target_cb->wait();
|
||||||
|
|
||||||
if (is_rsxthr)
|
|
||||||
m_last_flushable_cb = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_queue_ref)
|
if (has_queue_ref)
|
||||||
|
@ -1858,7 +1855,6 @@ void VKGSRender::copy_render_targets_to_dma_location()
|
||||||
|
|
||||||
vk::leave_uninterruptible();
|
vk::leave_uninterruptible();
|
||||||
|
|
||||||
m_last_flushable_cb = m_current_cb_index;
|
|
||||||
flush_command_queue();
|
flush_command_queue();
|
||||||
|
|
||||||
m_flush_draw_buffers = false;
|
m_flush_draw_buffers = false;
|
||||||
|
@ -1884,7 +1880,6 @@ void VKGSRender::flush_command_queue(bool hard_sync)
|
||||||
cb.poke();
|
cb.poke();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_flushable_cb = -1;
|
|
||||||
m_flush_requests.clear_pending_flag();
|
m_flush_requests.clear_pending_flag();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1904,9 +1899,6 @@ void VKGSRender::flush_command_queue(bool hard_sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_command_buffer->reset();
|
m_current_command_buffer->reset();
|
||||||
|
|
||||||
if (m_last_flushable_cb == m_current_cb_index)
|
|
||||||
m_last_flushable_cb = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open_command_buffer();
|
open_command_buffer();
|
||||||
|
@ -2089,7 +2081,7 @@ void VKGSRender::process_swap_request(frame_context_t *ctx, bool free_resources)
|
||||||
ctx->swap_command_buffer = nullptr;
|
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())
|
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.clear_pending_flag();
|
||||||
m_flush_requests.consumer_wait();
|
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!
|
//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
|
//Only call when there are no waiters
|
||||||
m_texture_cache.do_update();
|
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];
|
// Critical check finished
|
||||||
|
return;
|
||||||
if (cb->pending)
|
|
||||||
cb->poke();
|
|
||||||
|
|
||||||
if (!cb->pending)
|
|
||||||
m_last_flushable_cb = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -2208,8 +2197,6 @@ void VKGSRender::do_local_task(bool idle)
|
||||||
flip((s32)current_display_buffer);
|
flip((s32)current_display_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rsx::thread::do_local_task(idle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKGSRender::do_method(u32 cmd, u32 arg)
|
bool VKGSRender::do_method(u32 cmd, u32 arg)
|
||||||
|
|
|
@ -351,7 +351,6 @@ private:
|
||||||
|
|
||||||
u8 m_draw_buffers_count = 0;
|
u8 m_draw_buffers_count = 0;
|
||||||
bool m_flush_draw_buffers = false;
|
bool m_flush_draw_buffers = false;
|
||||||
std::atomic<int> m_last_flushable_cb = {-1 };
|
|
||||||
|
|
||||||
shared_mutex m_flush_queue_mutex;
|
shared_mutex m_flush_queue_mutex;
|
||||||
flush_request_task m_flush_requests;
|
flush_request_task m_flush_requests;
|
||||||
|
@ -420,7 +419,7 @@ protected:
|
||||||
bool do_method(u32 id, u32 arg) override;
|
bool do_method(u32 id, u32 arg) override;
|
||||||
void flip(int buffer) 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;
|
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;
|
void notify_tile_unbound(u32 tile) override;
|
||||||
|
|
||||||
|
|
|
@ -78,35 +78,31 @@ namespace rsx
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto tdr = (u64)g_cfg.video.driver_recovery_timeout;
|
if (const auto tdr = (u64)g_cfg.video.driver_recovery_timeout)
|
||||||
if (tdr == 0)
|
|
||||||
{
|
{
|
||||||
//No timeout
|
if (Emu.IsPaused())
|
||||||
std::this_thread::yield();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Emu.IsPaused())
|
|
||||||
{
|
|
||||||
while (Emu.IsPaused())
|
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
while (Emu.IsPaused())
|
||||||
}
|
{
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
}
|
||||||
|
|
||||||
//Reset
|
// Reset
|
||||||
start = get_system_time();
|
start = get_system_time();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if ((get_system_time() - start) > tdr)
|
|
||||||
{
|
{
|
||||||
//If longer than driver timeout force exit
|
if ((get_system_time() - start) > tdr)
|
||||||
LOG_ERROR(RSX, "nv406e::semaphore_acquire has timed out. semaphore_address=0x%X", addr);
|
{
|
||||||
break;
|
// 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);
|
rsx->performance_counters.idle_time += (get_system_time() - start);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue