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).
This commit is contained in:
commit
61442d6afb
@ -59,6 +59,7 @@ set(SRCS
|
|||||||
hle/kernel/timer.cpp
|
hle/kernel/timer.cpp
|
||||||
hle/kernel/vm_manager.cpp
|
hle/kernel/vm_manager.cpp
|
||||||
hle/kernel/wait_object.cpp
|
hle/kernel/wait_object.cpp
|
||||||
|
hle/lock.cpp
|
||||||
hle/romfs.cpp
|
hle/romfs.cpp
|
||||||
hle/service/ac/ac.cpp
|
hle/service/ac/ac.cpp
|
||||||
hle/service/ac/ac_i.cpp
|
hle/service/ac/ac_i.cpp
|
||||||
@ -256,6 +257,7 @@ set(HEADERS
|
|||||||
hle/kernel/timer.h
|
hle/kernel/timer.h
|
||||||
hle/kernel/vm_manager.h
|
hle/kernel/vm_manager.h
|
||||||
hle/kernel/wait_object.h
|
hle/kernel/wait_object.h
|
||||||
|
hle/lock.h
|
||||||
hle/result.h
|
hle/result.h
|
||||||
hle/romfs.h
|
hle/romfs.h
|
||||||
hle/service/ac/ac.h
|
hle/service/ac/ac.h
|
||||||
|
@ -132,4 +132,4 @@ void Init(u32 system_mode);
|
|||||||
/// Shutdown the kernel
|
/// Shutdown the kernel
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
} // namespace
|
} // namespace Kernel
|
||||||
|
11
src/core/hle/lock.cpp
Normal file
11
src/core/hle/lock.cpp
Normal file
@ -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
src/core/hle/lock.h
Normal file
18
src/core/hle/lock.h
Normal file
@ -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
|
@ -31,6 +31,7 @@
|
|||||||
#include "core/hle/kernel/timer.h"
|
#include "core/hle/kernel/timer.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
#include "core/hle/kernel/vm_manager.h"
|
||||||
#include "core/hle/kernel/wait_object.h"
|
#include "core/hle/kernel/wait_object.h"
|
||||||
|
#include "core/hle/lock.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
@ -1188,7 +1189,7 @@ struct FunctionDef {
|
|||||||
Func* func;
|
Func* func;
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
static const FunctionDef SVC_Table[] = {
|
static const FunctionDef SVC_Table[] = {
|
||||||
{0x00, nullptr, "Unknown"},
|
{0x00, nullptr, "Unknown"},
|
||||||
@ -1332,6 +1333,9 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
|
|||||||
void CallSVC(u32 immediate) {
|
void CallSVC(u32 immediate) {
|
||||||
MICROPROFILE_SCOPE(Kernel_SVC);
|
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);
|
const FunctionDef* info = GetSVCInfo(immediate);
|
||||||
if (info) {
|
if (info) {
|
||||||
if (info->func) {
|
if (info->func) {
|
||||||
@ -1342,4 +1346,4 @@ void CallSVC(u32 immediate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace SVC
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
#include "core/hle/lock.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/memory_setup.h"
|
#include "core/memory_setup.h"
|
||||||
#include "core/mmio.h"
|
#include "core/mmio.h"
|
||||||
@ -181,6 +182,9 @@ T Read(const VAddr vaddr) {
|
|||||||
return value;
|
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];
|
PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PageType::Unmapped:
|
case PageType::Unmapped:
|
||||||
@ -219,6 +223,9 @@ void Write(const VAddr vaddr, const T data) {
|
|||||||
return;
|
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];
|
PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PageType::Unmapped:
|
case PageType::Unmapped:
|
||||||
@ -746,4 +753,4 @@ boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
|
|||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace Memory
|
||||||
|
Loading…
Reference in New Issue
Block a user