Преглед изворни кода

Merge pull request #2839 from Subv/global_kernel_lock

Kernel/HLE: Use a mutex  to synchronize access to the HLE kernel state between the cpu thread and any other possible threads that might touch the kernel (network thread, etc).
James Rowe пре 9 година
родитељ
комит
61442d6afb
6 измењених фајлова са 46 додато и 4 уклоњено
  1. 2 0
      src/core/CMakeLists.txt
  2. 1 1
      src/core/hle/kernel/kernel.h
  3. 11 0
      src/core/hle/lock.cpp
  4. 18 0
      src/core/hle/lock.h
  5. 6 2
      src/core/hle/svc.cpp
  6. 8 1
      src/core/memory.cpp

+ 2 - 0
src/core/CMakeLists.txt

@@ -59,6 +59,7 @@ set(SRCS
             hle/kernel/timer.cpp
             hle/kernel/vm_manager.cpp
             hle/kernel/wait_object.cpp
+            hle/lock.cpp
             hle/romfs.cpp
             hle/service/ac/ac.cpp
             hle/service/ac/ac_i.cpp
@@ -256,6 +257,7 @@ set(HEADERS
             hle/kernel/timer.h
             hle/kernel/vm_manager.h
             hle/kernel/wait_object.h
+            hle/lock.h
             hle/result.h
             hle/romfs.h
             hle/service/ac/ac.h

+ 1 - 1
src/core/hle/kernel/kernel.h

@@ -132,4 +132,4 @@ void Init(u32 system_mode);
 /// Shutdown the kernel
 void Shutdown();
 
-} // namespace
+} // namespace Kernel

+ 11 - 0
src/core/hle/lock.cpp

@@ -0,0 +1,11 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <core/hle/lock.h>
+
+namespace HLE {
+std::mutex g_hle_lock;
+}

+ 18 - 0
src/core/hle/lock.h

@@ -0,0 +1,18 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <mutex>
+
+namespace HLE {
+/*
+ * Synchronizes access to the internal HLE kernel structures, it is acquired when a guest
+ * application thread performs a syscall. It should be acquired by any host threads that read or
+ * modify the HLE kernel state. Note: Any operation that directly or indirectly reads from or writes
+ * to the emulated memory is not protected by this mutex, and should be avoided in any threads other
+ * than the CPU thread.
+ */
+extern std::mutex g_hle_lock;
+} // namespace HLE

+ 6 - 2
src/core/hle/svc.cpp

@@ -31,6 +31,7 @@
 #include "core/hle/kernel/timer.h"
 #include "core/hle/kernel/vm_manager.h"
 #include "core/hle/kernel/wait_object.h"
+#include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
 
@@ -1188,7 +1189,7 @@ struct FunctionDef {
     Func* func;
     const char* name;
 };
-}
+} // namespace
 
 static const FunctionDef SVC_Table[] = {
     {0x00, nullptr, "Unknown"},
@@ -1332,6 +1333,9 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
 void CallSVC(u32 immediate) {
     MICROPROFILE_SCOPE(Kernel_SVC);
 
+    // Lock the global kernel mutex when we enter the kernel HLE.
+    std::lock_guard<std::mutex> lock(HLE::g_hle_lock);
+
     const FunctionDef* info = GetSVCInfo(immediate);
     if (info) {
         if (info->func) {
@@ -1342,4 +1346,4 @@ void CallSVC(u32 immediate) {
     }
 }
 
-} // namespace
+} // namespace SVC

+ 8 - 1
src/core/memory.cpp

@@ -9,6 +9,7 @@
 #include "common/logging/log.h"
 #include "common/swap.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/lock.h"
 #include "core/memory.h"
 #include "core/memory_setup.h"
 #include "core/mmio.h"
@@ -181,6 +182,9 @@ T Read(const VAddr vaddr) {
         return value;
     }
 
+    // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state
+    std::lock_guard<std::mutex> lock(HLE::g_hle_lock);
+
     PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
     switch (type) {
     case PageType::Unmapped:
@@ -219,6 +223,9 @@ void Write(const VAddr vaddr, const T data) {
         return;
     }
 
+    // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state
+    std::lock_guard<std::mutex> lock(HLE::g_hle_lock);
+
     PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
     switch (type) {
     case PageType::Unmapped:
@@ -746,4 +753,4 @@ boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
     return boost::none;
 }
 
-} // namespace
+} // namespace Memory