kernel/thread: Change owner_process to std::weak_ptr (#5325)

* kernel/thread: Change owner_process to std::weak_ptr

Previously this leaked almost all kernel objects. In short, Threads own Processes which own HandleTables which own maps of Objects which include Threads.

Changing this to weak_ptr at least got the camera interfaces to destruct properly. Did not really check the other objects though, and I think there are probably more leaks.

* hle/kernel: Lock certain objects while deserializing

When deserializing other kernel objects, these objects (`MemoryRegion`s and `VMManager`s) can possibly get modified. To avoid inconsistent state caused by destructor side-effects, we may as well simply lock them until loading is fully completed.

* Fix silly typo

Somehow this didn't break?!
This commit is contained in:
Pengfei Zhu
2020-11-15 19:59:45 +08:00
committed by GitHub
parent 80c9f9abbb
commit de3d7cf49f
13 changed files with 121 additions and 31 deletions

View File

@@ -45,6 +45,8 @@ VMManager::VMManager(Memory::MemorySystem& memory)
VMManager::~VMManager() = default;
void VMManager::Reset() {
ASSERT(!is_locked);
vma_map.clear();
// Initialize the map with a single free region covering the entire managed space.
@@ -67,6 +69,7 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, MemoryRef memory,
u32 size, MemoryState state) {
ASSERT(!is_locked);
// Find the first Free VMA.
VMAHandle vma_handle = std::find_if(vma_map.begin(), vma_map.end(), [&](const auto& vma) {
@@ -96,6 +99,7 @@ ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size,
ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, MemoryRef memory,
u32 size, MemoryState state) {
ASSERT(!is_locked);
ASSERT(memory.GetPtr() != nullptr);
// This is the appropriately sized VMA that will turn into our allocation.
@@ -115,6 +119,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, Memory
ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
MemoryState state,
Memory::MMIORegionPointer mmio_handler) {
ASSERT(!is_locked);
// This is the appropriately sized VMA that will turn into our allocation.
CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
VirtualMemoryArea& final_vma = vma_handle->second;
@@ -133,6 +139,10 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u3
ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expected_state,
VMAPermission expected_perms, MemoryState new_state,
VMAPermission new_perms) {
if (is_locked) {
return RESULT_SUCCESS;
}
VAddr target_end = target + size;
VMAIter begin_vma = StripIterConstness(FindVMA(target));
VMAIter i_end = vma_map.lower_bound(target_end);
@@ -167,6 +177,8 @@ ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expe
}
VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
ASSERT(!is_locked);
VirtualMemoryArea& vma = vma_handle->second;
vma.type = VMAType::Free;
vma.permissions = VMAPermission::None;
@@ -181,6 +193,8 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
}
ResultCode VMManager::UnmapRange(VAddr target, u32 size) {
ASSERT(!is_locked);
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
const VAddr target_end = target + size;
@@ -196,6 +210,8 @@ ResultCode VMManager::UnmapRange(VAddr target, u32 size) {
}
VMManager::VMAHandle VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) {
ASSERT(!is_locked);
VMAIter iter = StripIterConstness(vma_handle);
VirtualMemoryArea& vma = iter->second;
@@ -206,6 +222,8 @@ VMManager::VMAHandle VMManager::Reprotect(VMAHandle vma_handle, VMAPermission ne
}
ResultCode VMManager::ReprotectRange(VAddr target, u32 size, VMAPermission new_perms) {
ASSERT(!is_locked);
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
const VAddr target_end = target + size;
@@ -231,6 +249,10 @@ void VMManager::LogLayout(Log::Level log_level) const {
}
}
void VMManager::Unlock() {
is_locked = false;
}
VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
// This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
// non-const access to its container.