mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-10 07:14:21 +00:00
rsx: Avoid acquiring the vm lock; deadlock evasion
- A possible deadlock is still present if rsx is trying to get a super_ptr whilst the vm lock holder is in an access violation This patch makes this scenario very unlikely since each block need only be touched once
This commit is contained in:
parent
741ee9ac41
commit
38191c3013
@ -1373,6 +1373,24 @@ namespace rsx
|
||||
for (const auto& range : m_invalidated_memory_ranges)
|
||||
{
|
||||
on_invalidate_memory_range(range.first, range.second);
|
||||
|
||||
// Clean the main memory super_ptr cache if invalidated
|
||||
const auto range_end = range.first + range.second;
|
||||
for (auto It = main_super_memory_block.begin(); It != main_super_memory_block.end();)
|
||||
{
|
||||
const auto mem_start = It->first;
|
||||
const auto mem_end = mem_start + It->second.size();
|
||||
const bool overlaps = (mem_start < range_end && range.first < mem_end);
|
||||
|
||||
if (overlaps)
|
||||
{
|
||||
It = main_super_memory_block.erase(It);
|
||||
}
|
||||
else
|
||||
{
|
||||
It++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_invalidated_memory_ranges.clear();
|
||||
|
@ -382,7 +382,8 @@ namespace rsx
|
||||
GcmZcullInfo zculls[limits::zculls_count];
|
||||
|
||||
// Super memory map (mapped block with r/w permissions)
|
||||
std::pair<u32, std::shared_ptr<u8>> super_memory_map;
|
||||
std::pair<u32, std::shared_ptr<u8>> local_super_memory_block;
|
||||
std::unordered_map<u32, rsx::weak_ptr> main_super_memory_block;
|
||||
|
||||
bool capture_current_frame = false;
|
||||
void capture_frame(const std::string &name);
|
||||
|
@ -3113,9 +3113,6 @@ bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
|
||||
//Verify enough memory exists before attempting to handle data transfer
|
||||
check_heap_status();
|
||||
|
||||
//Stop all parallel operations until this is finished
|
||||
std::lock_guard<shared_mutex> lock(m_secondary_cb_guard);
|
||||
|
||||
if (m_texture_cache.blit(src, dst, interpolate, m_rtts, *m_current_command_buffer))
|
||||
{
|
||||
m_samplers_dirty.store(true);
|
||||
|
@ -354,7 +354,8 @@ namespace rsx
|
||||
|
||||
void flush_io(u32 offset = 0, u32 len = 0) const
|
||||
{
|
||||
locked_memory_ptr.flush(offset, len);
|
||||
const auto write_length = len ? len : (cpu_address_range - offset);
|
||||
locked_memory_ptr.flush(offset, write_length);
|
||||
}
|
||||
|
||||
std::pair<u32, u32> get_confirmed_range() const
|
||||
|
@ -80,15 +80,15 @@ namespace rsx
|
||||
{
|
||||
verify(HERE), g_current_renderer;
|
||||
|
||||
if (!g_current_renderer->super_memory_map.first)
|
||||
if (!g_current_renderer->local_super_memory_block.first)
|
||||
{
|
||||
auto block = vm::get(vm::any, 0xC0000000);
|
||||
if (block)
|
||||
{
|
||||
g_current_renderer->super_memory_map.first = block->used();
|
||||
g_current_renderer->super_memory_map.second = vm::get_super_ptr<u8>(0xC0000000, g_current_renderer->super_memory_map.first - 1);
|
||||
g_current_renderer->local_super_memory_block.first = block->used();
|
||||
g_current_renderer->local_super_memory_block.second = vm::get_super_ptr<u8>(0xC0000000, g_current_renderer->local_super_memory_block.first - 1);
|
||||
|
||||
if (!g_current_renderer->super_memory_map.second)
|
||||
if (!g_current_renderer->local_super_memory_block.second)
|
||||
{
|
||||
//Disjoint allocation?
|
||||
LOG_ERROR(RSX, "Could not initialize contiguous RSX super-memory");
|
||||
@ -100,18 +100,30 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
if (g_current_renderer->super_memory_map.second)
|
||||
if (g_current_renderer->local_super_memory_block.second)
|
||||
{
|
||||
if (addr >= 0xC0000000 && (addr + len) <= (0xC0000000 + g_current_renderer->super_memory_map.first))
|
||||
if (addr >= 0xC0000000 && (addr + len) <= (0xC0000000 + g_current_renderer->local_super_memory_block.first))
|
||||
{
|
||||
//RSX local
|
||||
return { g_current_renderer->super_memory_map.second.get() + (addr - 0xC0000000) };
|
||||
return { g_current_renderer->local_super_memory_block.second.get() + (addr - 0xC0000000) };
|
||||
}
|
||||
}
|
||||
|
||||
const auto cached = g_current_renderer->main_super_memory_block.find(addr);
|
||||
if (cached != g_current_renderer->main_super_memory_block.end())
|
||||
{
|
||||
const auto& _ptr = cached->second;
|
||||
if (_ptr.size() >= len)
|
||||
{
|
||||
return _ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto result = vm::get_super_ptr<u8>(addr, len - 1))
|
||||
{
|
||||
return { result };
|
||||
weak_ptr _ptr = { result, len };
|
||||
auto &ret = g_current_renderer->main_super_memory_block[addr] = std::move(_ptr);
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
//Probably allocated as split blocks. Try to grab separate chunks
|
||||
@ -137,7 +149,9 @@ namespace rsx
|
||||
next = region.first + region.second->size();
|
||||
if (next >= limit)
|
||||
{
|
||||
return { blocks };
|
||||
weak_ptr _ptr = { blocks };
|
||||
auto &ret = g_current_renderer->main_super_memory_block[addr] = std::move(_ptr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,9 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
weak_ptr(std::shared_ptr<u8>& block)
|
||||
weak_ptr(std::shared_ptr<u8>& block, u32 size)
|
||||
{
|
||||
_blocks.push_back({ block, 0 });
|
||||
_blocks.push_back({ block, size });
|
||||
_ptr = block.get();
|
||||
}
|
||||
|
||||
@ -195,6 +195,11 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
u32 size() const
|
||||
{
|
||||
return contiguous ? _blocks[0].second : (u32)io_cache.size();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (_ptr != nullptr || _blocks.size() > 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user