summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam <byteslice@airmail.cc>2024-01-29 03:58:18 +0100
committerLiam <byteslice@airmail.cc>2024-02-09 15:20:53 +0100
commit06fd7f2012a6087c4b1fc76842faad44cd097bde (patch)
treed6ae4cf063aeea2f01b264de6206464ce5b08494
parentvideo_core: defensively program around unmapped device pointers (diff)
downloadyuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar.gz
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar.bz2
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar.lz
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar.xz
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.tar.zst
yuzu-06fd7f2012a6087c4b1fc76842faad44cd097bde.zip
-rw-r--r--src/core/hle/service/nvdrv/core/container.cpp7
-rw-r--r--src/core/hle/service/nvdrv/core/container.h1
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp8
3 files changed, 13 insertions, 3 deletions
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp
index e89cca6f2..9edce03f6 100644
--- a/src/core/hle/service/nvdrv/core/container.cpp
+++ b/src/core/hle/service/nvdrv/core/container.cpp
@@ -49,6 +49,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
continue;
}
if (session.process == process) {
+ session.ref_count++;
return session.id;
}
}
@@ -66,6 +67,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
}
auto& session = impl->sessions[new_id];
session.is_active = true;
+ session.ref_count = 1;
// Optimization
if (process->IsApplication()) {
auto& page_table = process->GetPageTable().GetBasePageTable();
@@ -114,8 +116,11 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
void Container::CloseSession(SessionId session_id) {
std::scoped_lock lk(impl->session_guard);
- impl->file.UnmapAllHandles(session_id);
auto& session = impl->sessions[session_id.id];
+ if (--session.ref_count > 0) {
+ return;
+ }
+ impl->file.UnmapAllHandles(session_id);
auto& smmu = impl->host1x.MemoryManager();
if (session.has_preallocated_area) {
const DAddr region_start = session.mapper->GetRegionStart();
diff --git a/src/core/hle/service/nvdrv/core/container.h b/src/core/hle/service/nvdrv/core/container.h
index b4d3938a8..f159ced09 100644
--- a/src/core/hle/service/nvdrv/core/container.h
+++ b/src/core/hle/service/nvdrv/core/container.h
@@ -46,6 +46,7 @@ struct Session {
bool has_preallocated_area{};
std::unique_ptr<HeapMapper> mapper{};
bool is_active{};
+ s32 ref_count{};
};
class Container {
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index bc1c033c6..453cb5831 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -333,9 +333,13 @@ void NvMap::UnmapAllHandles(NvCore::SessionId session_id) {
}();
for (auto& [id, handle] : handles_copy) {
- if (handle->session_id.id == session_id.id) {
- FreeHandle(id, false);
+ {
+ std::scoped_lock lk{handle->mutex};
+ if (handle->session_id.id != session_id.id || handle->dupes <= 0) {
+ continue;
+ }
}
+ FreeHandle(id, false);
}
}