early-access version 1377
This commit is contained in:
parent
33ac7b8575
commit
4f60301798
@ -1,7 +1,7 @@
|
|||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1376.
|
This is the source code for early-access 1377.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
@ -97,6 +97,9 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
|||||||
#define R_UNLESS(expr, res) \
|
#define R_UNLESS(expr, res) \
|
||||||
{ \
|
{ \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
|
if (res.IsError()) { \
|
||||||
|
LOG_CRITICAL(Kernel, "Failed with error {}", res.raw); \
|
||||||
|
} \
|
||||||
return res; \
|
return res; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
@ -251,16 +251,10 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) {
|
void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jit->ChangeProcessorID(new_core_id);
|
jit->ChangeProcessorID(new_core_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
|
void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Dynarmic::A32::Context context;
|
Dynarmic::A32::Context context;
|
||||||
jit->SaveContext(context);
|
jit->SaveContext(context);
|
||||||
ctx.cpu_registers = context.Regs();
|
ctx.cpu_registers = context.Regs();
|
||||||
@ -270,9 +264,6 @@ void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
|
void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Dynarmic::A32::Context context;
|
Dynarmic::A32::Context context;
|
||||||
context.Regs() = ctx.cpu_registers;
|
context.Regs() = ctx.cpu_registers;
|
||||||
context.ExtRegs() = ctx.extension_registers;
|
context.ExtRegs() = ctx.extension_registers;
|
||||||
@ -282,9 +273,6 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_32::PrepareReschedule() {
|
void ARM_Dynarmic_32::PrepareReschedule() {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jit->HaltExecution();
|
jit->HaltExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,16 +290,10 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) {
|
void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jit->ChangeProcessorID(new_core_id);
|
jit->ChangeProcessorID(new_core_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
|
void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ctx.cpu_registers = jit->GetRegisters();
|
ctx.cpu_registers = jit->GetRegisters();
|
||||||
ctx.sp = jit->GetSP();
|
ctx.sp = jit->GetSP();
|
||||||
ctx.pc = jit->GetPC();
|
ctx.pc = jit->GetPC();
|
||||||
@ -311,9 +305,6 @@ void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
|
void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jit->SetRegisters(ctx.cpu_registers);
|
jit->SetRegisters(ctx.cpu_registers);
|
||||||
jit->SetSP(ctx.sp);
|
jit->SetSP(ctx.sp);
|
||||||
jit->SetPC(ctx.pc);
|
jit->SetPC(ctx.pc);
|
||||||
@ -325,9 +316,6 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Dynarmic_64::PrepareReschedule() {
|
void ARM_Dynarmic_64::PrepareReschedule() {
|
||||||
if (!jit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jit->HaltExecution();
|
jit->HaltExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ public:
|
|||||||
explicit KAbstractSchedulerLock(KernelCore& kernel_) : kernel{kernel_} {}
|
explicit KAbstractSchedulerLock(KernelCore& kernel_) : kernel{kernel_} {}
|
||||||
|
|
||||||
bool IsLockedByCurrentThread() const {
|
bool IsLockedByCurrentThread() const {
|
||||||
return this->owner_thread == GetCurrentThreadPointer(kernel);
|
return owner_thread == GetCurrentThreadPointer(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lock() {
|
void Lock() {
|
||||||
if (this->IsLockedByCurrentThread()) {
|
if (IsLockedByCurrentThread()) {
|
||||||
// If we already own the lock, we can just increment the count.
|
// If we already own the lock, we can just increment the count.
|
||||||
ASSERT(lock_count > 0);
|
ASSERT(lock_count > 0);
|
||||||
lock_count++;
|
lock_count++;
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Unlock() {
|
void Unlock() {
|
||||||
ASSERT(this->IsLockedByCurrentThread());
|
ASSERT(IsLockedByCurrentThread());
|
||||||
ASSERT(lock_count > 0);
|
ASSERT(lock_count > 0);
|
||||||
|
|
||||||
// Release an instance of the lock.
|
// Release an instance of the lock.
|
||||||
|
@ -101,11 +101,12 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
|
|||||||
UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type));
|
UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
thread_type_for_debugging = type;
|
||||||
|
|
||||||
// Set the ideal core ID and affinity mask.
|
// Set the ideal core ID and affinity mask.
|
||||||
virtual_ideal_core_id = virt_core;
|
virtual_ideal_core_id = virt_core;
|
||||||
physical_ideal_core_id = phys_core;
|
physical_ideal_core_id = phys_core;
|
||||||
virtual_affinity_mask = (static_cast<u64>(1) << virt_core);
|
virtual_affinity_mask = 1ULL << virt_core;
|
||||||
physical_affinity_mask.SetAffinity(phys_core, true);
|
physical_affinity_mask.SetAffinity(phys_core, true);
|
||||||
|
|
||||||
// Set the thread state.
|
// Set the thread state.
|
||||||
@ -353,7 +354,7 @@ void KThread::Unpin() {
|
|||||||
// Enable core migration.
|
// Enable core migration.
|
||||||
ASSERT(num_core_migration_disables == 1);
|
ASSERT(num_core_migration_disables == 1);
|
||||||
{
|
{
|
||||||
--num_core_migration_disables;
|
num_core_migration_disables--;
|
||||||
|
|
||||||
// Restore our original state.
|
// Restore our original state.
|
||||||
const KAffinityMask old_mask = physical_affinity_mask;
|
const KAffinityMask old_mask = physical_affinity_mask;
|
||||||
@ -494,8 +495,8 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
|
|||||||
|
|
||||||
// Update the pinned waiter list.
|
// Update the pinned waiter list.
|
||||||
{
|
{
|
||||||
bool retry_update = false;
|
bool retry_update{};
|
||||||
bool thread_is_pinned = false;
|
bool thread_is_pinned{};
|
||||||
do {
|
do {
|
||||||
// Lock the scheduler.
|
// Lock the scheduler.
|
||||||
KScopedSchedulerLock sl{kernel};
|
KScopedSchedulerLock sl{kernel};
|
||||||
@ -507,7 +508,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
|
|||||||
retry_update = false;
|
retry_update = false;
|
||||||
|
|
||||||
// Check if the thread is currently running.
|
// Check if the thread is currently running.
|
||||||
bool thread_is_current = false;
|
bool thread_is_current{};
|
||||||
s32 thread_core;
|
s32 thread_core;
|
||||||
for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES);
|
for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES);
|
||||||
++thread_core) {
|
++thread_core) {
|
||||||
@ -683,8 +684,8 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
|
|||||||
|
|
||||||
// If the thread is now paused, update the pinned waiter list.
|
// If the thread is now paused, update the pinned waiter list.
|
||||||
if (activity == Svc::ThreadActivity::Paused) {
|
if (activity == Svc::ThreadActivity::Paused) {
|
||||||
bool thread_is_pinned = false;
|
bool thread_is_pinned{};
|
||||||
bool thread_is_current;
|
bool thread_is_current{};
|
||||||
do {
|
do {
|
||||||
// Lock the scheduler.
|
// Lock the scheduler.
|
||||||
KScopedSchedulerLock sl{kernel};
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
@ -534,6 +534,10 @@ public:
|
|||||||
return wait_reason_for_debugging;
|
return wait_reason_for_debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ThreadType GetThreadTypeForDebugging() const {
|
||||||
|
return thread_type_for_debugging;
|
||||||
|
}
|
||||||
|
|
||||||
void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
|
void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
|
||||||
wait_objects_for_debugging.clear();
|
wait_objects_for_debugging.clear();
|
||||||
wait_objects_for_debugging.reserve(objects.size());
|
wait_objects_for_debugging.reserve(objects.size());
|
||||||
@ -721,6 +725,7 @@ private:
|
|||||||
std::vector<KSynchronizationObject*> wait_objects_for_debugging;
|
std::vector<KSynchronizationObject*> wait_objects_for_debugging;
|
||||||
VAddr mutex_wait_address_for_debugging{};
|
VAddr mutex_wait_address_for_debugging{};
|
||||||
ThreadWaitReasonForDebugging wait_reason_for_debugging{};
|
ThreadWaitReasonForDebugging wait_reason_for_debugging{};
|
||||||
|
ThreadType thread_type_for_debugging{};
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -211,9 +211,8 @@ struct KernelCore::Impl {
|
|||||||
KThread* GetHostDummyThread() {
|
KThread* GetHostDummyThread() {
|
||||||
const thread_local auto thread =
|
const thread_local auto thread =
|
||||||
KThread::Create(
|
KThread::Create(
|
||||||
Core::System::GetInstance(), ThreadType::Main,
|
system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0,
|
||||||
std::string{"DummyThread:" + GetHostThreadId()}, 0, KThread::DefaultThreadPriority,
|
KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr,
|
||||||
0, static_cast<u32>(3), 0, nullptr,
|
|
||||||
[]([[maybe_unused]] void* arg) { UNREACHABLE(); }, nullptr)
|
[]([[maybe_unused]] void* arg) { UNREACHABLE(); }, nullptr)
|
||||||
.Unwrap();
|
.Unwrap();
|
||||||
return thread.get();
|
return thread.get();
|
||||||
@ -272,7 +271,7 @@ struct KernelCore::Impl {
|
|||||||
constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
|
constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
|
||||||
|
|
||||||
// Initialize memory manager
|
// Initialize memory manager
|
||||||
memory_manager = std::make_unique<Memory::MemoryManager>(system.Kernel());
|
memory_manager = std::make_unique<Memory::MemoryManager>();
|
||||||
memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
|
memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
|
||||||
layout.Application().StartAddress(),
|
layout.Application().StartAddress(),
|
||||||
layout.Application().EndAddress());
|
layout.Application().EndAddress());
|
||||||
|
@ -41,9 +41,6 @@ std::size_t MemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u6
|
|||||||
return total_metadata_size;
|
return total_metadata_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryManager::MemoryManager(KernelCore& kernel)
|
|
||||||
: pool_lock_0{kernel}, pool_lock_1{kernel}, pool_lock_2{kernel}, pool_lock_3{kernel} {}
|
|
||||||
|
|
||||||
void MemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) {
|
void MemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) {
|
||||||
ASSERT(pool < Pool::Count);
|
ASSERT(pool < Pool::Count);
|
||||||
managers[static_cast<std::size_t>(pool)].Initialize(pool, start_address, end_address);
|
managers[static_cast<std::size_t>(pool)].Initialize(pool, start_address, end_address);
|
||||||
@ -58,7 +55,7 @@ VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align
|
|||||||
|
|
||||||
// Lock the pool that we're allocating from
|
// Lock the pool that we're allocating from
|
||||||
const auto pool_index{static_cast<std::size_t>(pool)};
|
const auto pool_index{static_cast<std::size_t>(pool)};
|
||||||
KScopedLightLock lk{PoolLock(pool_index)};
|
std::lock_guard lock{pool_locks[pool_index]};
|
||||||
|
|
||||||
// Choose a heap based on our page size request
|
// Choose a heap based on our page size request
|
||||||
const s32 heap_index{PageHeap::GetAlignedBlockIndex(num_pages, align_pages)};
|
const s32 heap_index{PageHeap::GetAlignedBlockIndex(num_pages, align_pages)};
|
||||||
@ -93,7 +90,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa
|
|||||||
|
|
||||||
// Lock the pool that we're allocating from
|
// Lock the pool that we're allocating from
|
||||||
const auto pool_index{static_cast<std::size_t>(pool)};
|
const auto pool_index{static_cast<std::size_t>(pool)};
|
||||||
KScopedLightLock lk{PoolLock(pool_index)};
|
std::lock_guard lock{pool_locks[pool_index]};
|
||||||
|
|
||||||
// Choose a heap based on our page size request
|
// Choose a heap based on our page size request
|
||||||
const s32 heap_index{PageHeap::GetBlockIndex(num_pages)};
|
const s32 heap_index{PageHeap::GetBlockIndex(num_pages)};
|
||||||
@ -160,7 +157,7 @@ ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages,
|
|||||||
|
|
||||||
// Lock the pool that we're freeing from
|
// Lock the pool that we're freeing from
|
||||||
const auto pool_index{static_cast<std::size_t>(pool)};
|
const auto pool_index{static_cast<std::size_t>(pool)};
|
||||||
KScopedLightLock lk{PoolLock(pool_index)};
|
std::lock_guard lock{pool_locks[pool_index]};
|
||||||
|
|
||||||
// TODO (bunnei): Support multiple managers
|
// TODO (bunnei): Support multiple managers
|
||||||
Impl& chosen_manager{managers[pool_index]};
|
Impl& chosen_manager{managers[pool_index]};
|
||||||
|
@ -7,16 +7,10 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/k_light_lock.h"
|
|
||||||
#include "core/hle/kernel/memory/page_heap.h"
|
#include "core/hle/kernel/memory/page_heap.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KernelCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
|
||||||
class PageLinkedList;
|
class PageLinkedList;
|
||||||
@ -43,7 +37,7 @@ public:
|
|||||||
Mask = (0xF << Shift),
|
Mask = (0xF << Shift),
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryManager(KernelCore& kernel);
|
MemoryManager() = default;
|
||||||
|
|
||||||
constexpr std::size_t GetSize(Pool pool) const {
|
constexpr std::size_t GetSize(Pool pool) const {
|
||||||
return managers[static_cast<std::size_t>(pool)].GetSize();
|
return managers[static_cast<std::size_t>(pool)].GetSize();
|
||||||
@ -95,24 +89,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KLightLock pool_lock_0;
|
std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
|
||||||
KLightLock pool_lock_1;
|
|
||||||
KLightLock pool_lock_2;
|
|
||||||
KLightLock pool_lock_3;
|
|
||||||
|
|
||||||
KLightLock& PoolLock(std::size_t index) {
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
return pool_lock_0;
|
|
||||||
case 1:
|
|
||||||
return pool_lock_1;
|
|
||||||
case 2:
|
|
||||||
return pool_lock_2;
|
|
||||||
}
|
|
||||||
ASSERT(index == 3);
|
|
||||||
return pool_lock_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<Impl, MaxManagerCount> managers;
|
std::array<Impl, MaxManagerCount> managers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PageTable::PageTable(Core::System& system) : general_lock{system.Kernel()}, system{system} {}
|
PageTable::PageTable(Core::System& system) : system{system} {}
|
||||||
|
|
||||||
ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type,
|
ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type,
|
||||||
bool enable_aslr, VAddr code_addr, std::size_t code_size,
|
bool enable_aslr, VAddr code_addr, std::size_t code_size,
|
||||||
@ -272,7 +272,7 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t
|
|||||||
|
|
||||||
ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state,
|
ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state,
|
||||||
MemoryPermission perm) {
|
MemoryPermission perm) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const u64 size{num_pages * PageSize};
|
const u64 size{num_pages * PageSize};
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemorySt
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
if (!size) {
|
if (!size) {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
@ -394,7 +394,7 @@ void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
std::size_t mapped_size{};
|
std::size_t mapped_size{};
|
||||||
const VAddr end_addr{addr + size};
|
const VAddr end_addr{addr + size};
|
||||||
@ -444,7 +444,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const VAddr end_addr{addr + size};
|
const VAddr end_addr{addr + size};
|
||||||
ResultCode result{RESULT_SUCCESS};
|
ResultCode result{RESULT_SUCCESS};
|
||||||
@ -481,7 +481,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const VAddr end_addr{addr + size};
|
const VAddr end_addr{addr + size};
|
||||||
ResultCode result{RESULT_SUCCESS};
|
ResultCode result{RESULT_SUCCESS};
|
||||||
@ -517,7 +517,7 @@ ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState src_state{};
|
MemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
@ -555,7 +555,7 @@ ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState src_state{};
|
MemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
@ -620,7 +620,7 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis
|
|||||||
|
|
||||||
ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
|
ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
|
||||||
MemoryPermission perm) {
|
MemoryPermission perm) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const std::size_t num_pages{page_linked_list.GetNumPages()};
|
const std::size_t num_pages{page_linked_list.GetNumPages()};
|
||||||
const std::size_t size{num_pages * PageSize};
|
const std::size_t size{num_pages * PageSize};
|
||||||
@ -642,7 +642,7 @@ ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, Mem
|
|||||||
|
|
||||||
ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) {
|
ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) {
|
||||||
|
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState prev_state{};
|
MemoryState prev_state{};
|
||||||
MemoryPermission prev_perm{};
|
MemoryPermission prev_perm{};
|
||||||
@ -688,7 +688,7 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo
|
|||||||
}
|
}
|
||||||
|
|
||||||
MemoryInfo PageTable::QueryInfoImpl(VAddr addr) {
|
MemoryInfo PageTable::QueryInfoImpl(VAddr addr) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
return block_manager->FindBlock(addr).GetMemoryInfo();
|
return block_manager->FindBlock(addr).GetMemoryInfo();
|
||||||
}
|
}
|
||||||
@ -703,7 +703,7 @@ MemoryInfo PageTable::QueryInfo(VAddr addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) {
|
ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
MemoryState state{};
|
||||||
MemoryAttribute attribute{};
|
MemoryAttribute attribute{};
|
||||||
@ -721,7 +721,7 @@ ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, Memory
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
|
ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
MemoryState state{};
|
||||||
|
|
||||||
@ -739,7 +739,7 @@ ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
|
|||||||
|
|
||||||
ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
|
ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
|
||||||
MemoryAttribute value) {
|
MemoryAttribute value) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
MemoryState state{};
|
||||||
MemoryPermission perm{};
|
MemoryPermission perm{};
|
||||||
@ -760,7 +760,7 @@ ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAtt
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
|
ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
heap_capacity = new_heap_capacity;
|
heap_capacity = new_heap_capacity;
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -777,7 +777,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
|||||||
|
|
||||||
// Increase the heap size
|
// Increase the heap size
|
||||||
{
|
{
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const u64 delta{size - previous_heap_size};
|
const u64 delta{size - previous_heap_size};
|
||||||
|
|
||||||
@ -813,7 +813,7 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s
|
|||||||
bool is_map_only, VAddr region_start,
|
bool is_map_only, VAddr region_start,
|
||||||
std::size_t region_num_pages, MemoryState state,
|
std::size_t region_num_pages, MemoryState state,
|
||||||
MemoryPermission perm, PAddr map_addr) {
|
MemoryPermission perm, PAddr map_addr) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
@ -844,7 +844,7 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryPermission perm{};
|
MemoryPermission perm{};
|
||||||
if (const ResultCode result{CheckMemoryState(
|
if (const ResultCode result{CheckMemoryState(
|
||||||
@ -867,7 +867,7 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryPermission perm{};
|
MemoryPermission perm{};
|
||||||
if (const ResultCode result{CheckMemoryState(
|
if (const ResultCode result{CheckMemoryState(
|
||||||
@ -937,7 +937,7 @@ VAddr PageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages
|
|||||||
|
|
||||||
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
|
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
|
||||||
OperationType operation) {
|
OperationType operation) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
ASSERT(Common::IsAligned(addr, PageSize));
|
ASSERT(Common::IsAligned(addr, PageSize));
|
||||||
ASSERT(num_pages > 0);
|
ASSERT(num_pages > 0);
|
||||||
@ -962,7 +962,7 @@ ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinke
|
|||||||
|
|
||||||
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
|
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
|
||||||
OperationType operation, PAddr map_addr) {
|
OperationType operation, PAddr map_addr) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
ASSERT(num_pages > 0);
|
ASSERT(num_pages > 0);
|
||||||
ASSERT(Common::IsAligned(addr, PageSize));
|
ASSERT(Common::IsAligned(addr, PageSize));
|
||||||
@ -1123,7 +1123,7 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission*
|
|||||||
MemoryPermission perm_mask, MemoryPermission perm,
|
MemoryPermission perm_mask, MemoryPermission perm,
|
||||||
MemoryAttribute attr_mask, MemoryAttribute attr,
|
MemoryAttribute attr_mask, MemoryAttribute attr,
|
||||||
MemoryAttribute ignore_attr) {
|
MemoryAttribute ignore_attr) {
|
||||||
KScopedLightLock lk{general_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
// Get information about the first block
|
// Get information about the first block
|
||||||
const VAddr last_addr{addr + size - 1};
|
const VAddr last_addr{addr + size - 1};
|
||||||
|
@ -111,7 +111,7 @@ private:
|
|||||||
perm, attr_mask, attr, ignore_attr);
|
perm, attr_mask, attr, ignore_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
KLightLock general_lock;
|
std::recursive_mutex page_table_lock;
|
||||||
std::unique_ptr<MemoryBlockManager> block_manager;
|
std::unique_ptr<MemoryBlockManager> block_manager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -138,7 +138,7 @@ std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const {
|
|||||||
|
|
||||||
void Process::IncrementThreadCount() {
|
void Process::IncrementThreadCount() {
|
||||||
ASSERT(num_threads >= 0);
|
ASSERT(num_threads >= 0);
|
||||||
++num_created_threads;
|
num_created_threads++;
|
||||||
|
|
||||||
if (const auto count = ++num_threads; count > peak_num_threads) {
|
if (const auto count = ++num_threads; count > peak_num_threads) {
|
||||||
peak_num_threads = count;
|
peak_num_threads = count;
|
||||||
@ -443,7 +443,7 @@ bool Process::IsSignaled() const {
|
|||||||
Process::Process(Core::System& system)
|
Process::Process(Core::System& system)
|
||||||
: KSynchronizationObject{system.Kernel()},
|
: KSynchronizationObject{system.Kernel()},
|
||||||
page_table{std::make_unique<Memory::PageTable>(system)}, handle_table{system.Kernel()},
|
page_table{std::make_unique<Memory::PageTable>(system)}, handle_table{system.Kernel()},
|
||||||
address_arbiter{system}, condition_var{system}, system{system} {}
|
address_arbiter{system}, condition_var{system}, state_lock{system.Kernel()}, system{system} {}
|
||||||
|
|
||||||
Process::~Process() = default;
|
Process::~Process() = default;
|
||||||
|
|
||||||
|
@ -348,6 +348,10 @@ public:
|
|||||||
void PinCurrentThread();
|
void PinCurrentThread();
|
||||||
void UnpinCurrentThread();
|
void UnpinCurrentThread();
|
||||||
|
|
||||||
|
KLightLock& GetStateLock() {
|
||||||
|
return state_lock;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Thread-local storage management
|
// Thread-local storage management
|
||||||
|
|
||||||
@ -472,6 +476,8 @@ private:
|
|||||||
|
|
||||||
KThread* exception_thread{};
|
KThread* exception_thread{};
|
||||||
|
|
||||||
|
KLightLock state_lock;
|
||||||
|
|
||||||
/// System context
|
/// System context
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
@ -1450,11 +1450,14 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
|||||||
Svc::ResultInvalidPriority);
|
Svc::ResultInvalidPriority);
|
||||||
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
|
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
|
||||||
|
|
||||||
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1));
|
ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1));
|
||||||
|
|
||||||
CASCADE_RESULT(std::shared_ptr<KThread> thread,
|
std::shared_ptr<KThread> thread;
|
||||||
KThread::Create(system, ThreadType::User, "", entry_point, priority, arg,
|
{
|
||||||
core_id, stack_bottom, &process));
|
KScopedLightLock lk{process.GetStateLock()};
|
||||||
|
CASCADE_RESULT(thread, KThread::Create(system, ThreadType::User, "", entry_point, priority,
|
||||||
|
arg, core_id, stack_bottom, &process));
|
||||||
|
}
|
||||||
|
|
||||||
const auto new_thread_handle = process.GetHandleTable().Create(thread);
|
const auto new_thread_handle = process.GetHandleTable().Create(thread);
|
||||||
if (new_thread_handle.Failed()) {
|
if (new_thread_handle.Failed()) {
|
||||||
|
@ -93,8 +93,10 @@ std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList()
|
|||||||
std::size_t row = 0;
|
std::size_t row = 0;
|
||||||
auto add_threads = [&](const std::vector<std::shared_ptr<Kernel::KThread>>& threads) {
|
auto add_threads = [&](const std::vector<std::shared_ptr<Kernel::KThread>>& threads) {
|
||||||
for (std::size_t i = 0; i < threads.size(); ++i) {
|
for (std::size_t i = 0; i < threads.size(); ++i) {
|
||||||
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i]));
|
if (threads[i]->GetThreadTypeForDebugging() == Kernel::ThreadType::User) {
|
||||||
item_list.back()->row = row;
|
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i]));
|
||||||
|
item_list.back()->row = row;
|
||||||
|
}
|
||||||
++row;
|
++row;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -148,6 +150,10 @@ QString WaitTreeCallstack::GetText() const {
|
|||||||
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
|
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
|
||||||
std::vector<std::unique_ptr<WaitTreeItem>> list;
|
std::vector<std::unique_ptr<WaitTreeItem>> list;
|
||||||
|
|
||||||
|
if (thread.GetThreadTypeForDebugging() != Kernel::ThreadType::User) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) {
|
if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user