From 57534777d43c9bc186adff80f52c585ed2d46733 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 20 Oct 2020 18:05:59 -0400 Subject: Common: Move OSThreads into core Common shouldn't be depending on APIs in Core (in this, case depending on the PowerPC namespace). Because of the poor separation here, this moves OSThread functionality into core, so that it resolves the implicit dependency on core. --- Source/Core/Common/CMakeLists.txt | 2 - Source/Core/Common/Common.vcxproj | 2 - Source/Core/Common/Common.vcxproj.filters | 6 - Source/Core/Common/Debug/OSThread.cpp | 204 ----------------------- Source/Core/Common/Debug/OSThread.h | 154 ------------------ Source/Core/Core/CMakeLists.txt | 2 + Source/Core/Core/Core.vcxproj | 2 + Source/Core/Core/Core.vcxproj.filters | 22 ++- Source/Core/Core/Debugger/OSThread.cpp | 208 ++++++++++++++++++++++++ Source/Core/Core/Debugger/OSThread.h | 154 ++++++++++++++++++ Source/Core/Core/Debugger/PPCDebugInterface.cpp | 6 +- 11 files changed, 383 insertions(+), 379 deletions(-) delete mode 100644 Source/Core/Common/Debug/OSThread.cpp delete mode 100644 Source/Core/Common/Debug/OSThread.h create mode 100644 Source/Core/Core/Debugger/OSThread.cpp create mode 100644 Source/Core/Core/Debugger/OSThread.h (limited to 'Source') diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 9592043954..cadb12163d 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -34,8 +34,6 @@ add_library(common Crypto/ec.h Debug/MemoryPatches.cpp Debug/MemoryPatches.h - Debug/OSThread.cpp - Debug/OSThread.h Debug/Threads.h Debug/Watches.cpp Debug/Watches.h diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 47e8957fe4..c45edb1b59 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -48,7 +48,6 @@ - @@ -191,7 +190,6 @@ - diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 6ae672b770..0db5b561d0 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -273,9 +273,6 @@ Debug - - Debug - Debug @@ -365,9 +362,6 @@ Debug - - Debug - GL\GLInterface diff --git a/Source/Core/Common/Debug/OSThread.cpp b/Source/Core/Common/Debug/OSThread.cpp deleted file mode 100644 index 809e5adccd..0000000000 --- a/Source/Core/Common/Debug/OSThread.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2020 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/Debug/OSThread.h" - -#include -#include - -#include "Core/PowerPC/MMU.h" - -// Context offsets based on the following functions: -// - OSSaveContext -// - OSSaveFPUContext -// - OSDumpContext -// - OSClearContext -// - OSExceptionVector -void Common::Debug::OSContext::Read(u32 addr) -{ - for (std::size_t i = 0; i < gpr.size(); i++) - gpr[i] = PowerPC::HostRead_U32(addr + u32(i * sizeof(int))); - cr = PowerPC::HostRead_U32(addr + 0x80); - lr = PowerPC::HostRead_U32(addr + 0x84); - ctr = PowerPC::HostRead_U32(addr + 0x88); - xer = PowerPC::HostRead_U32(addr + 0x8C); - for (std::size_t i = 0; i < fpr.size(); i++) - fpr[i] = PowerPC::HostRead_F64(addr + 0x90 + u32(i * sizeof(double))); - fpscr = PowerPC::HostRead_U64(addr + 0x190); - srr0 = PowerPC::HostRead_U32(addr + 0x198); - srr1 = PowerPC::HostRead_U32(addr + 0x19c); - dummy = PowerPC::HostRead_U16(addr + 0x1a0); - state = static_cast(PowerPC::HostRead_U16(addr + 0x1a2)); - for (std::size_t i = 0; i < gqr.size(); i++) - gqr[i] = PowerPC::HostRead_U32(addr + 0x1a4 + u32(i * sizeof(int))); - psf_padding = 0; - for (std::size_t i = 0; i < psf.size(); i++) - psf[i] = PowerPC::HostRead_F64(addr + 0x1c8 + u32(i * sizeof(double))); -} - -// Mutex offsets based on the following functions: -// - OSInitMutex -// - OSLockMutex -// - __OSUnlockAllMutex -void Common::Debug::OSMutex::Read(u32 addr) -{ - thread_queue.head = PowerPC::HostRead_U32(addr); - thread_queue.tail = PowerPC::HostRead_U32(addr + 0x4); - owner_addr = PowerPC::HostRead_U32(addr + 0x8); - lock_count = PowerPC::HostRead_U32(addr + 0xc); - link.next = PowerPC::HostRead_U32(addr + 0x10); - link.prev = PowerPC::HostRead_U32(addr + 0x14); -} - -// Thread offsets based on the following functions: -// - OSCreateThread -// - OSIsThreadTerminated -// - OSJoinThread -// - OSSuspendThread -// - OSSetPriority -// - OSExitThread -// - OSLockMutex -// - __OSUnlockAllMutex -// - __OSThreadInit -// - OSSetThreadSpecific -// - SOInit (for errno) -void Common::Debug::OSThread::Read(u32 addr) -{ - context.Read(addr); - state = PowerPC::HostRead_U16(addr + 0x2c8); - is_detached = PowerPC::HostRead_U16(addr + 0x2ca); - suspend = PowerPC::HostRead_U32(addr + 0x2cc); - effective_priority = PowerPC::HostRead_U32(addr + 0x2d0); - base_priority = PowerPC::HostRead_U32(addr + 0x2d4); - exit_code_addr = PowerPC::HostRead_U32(addr + 0x2d8); - - queue_addr = PowerPC::HostRead_U32(addr + 0x2dc); - queue_link.next = PowerPC::HostRead_U32(addr + 0x2e0); - queue_link.prev = PowerPC::HostRead_U32(addr + 0x2e4); - - join_queue.head = PowerPC::HostRead_U32(addr + 0x2e8); - join_queue.tail = PowerPC::HostRead_U32(addr + 0x2ec); - - mutex_addr = PowerPC::HostRead_U32(addr + 0x2f0); - mutex_queue.head = PowerPC::HostRead_U32(addr + 0x2f4); - mutex_queue.tail = PowerPC::HostRead_U32(addr + 0x2f8); - - thread_link.next = PowerPC::HostRead_U32(addr + 0x2fc); - thread_link.prev = PowerPC::HostRead_U32(addr + 0x300); - - stack_addr = PowerPC::HostRead_U32(addr + 0x304); - stack_end = PowerPC::HostRead_U32(addr + 0x308); - error = PowerPC::HostRead_U32(addr + 0x30c); - specific[0] = PowerPC::HostRead_U32(addr + 0x310); - specific[1] = PowerPC::HostRead_U32(addr + 0x314); -} - -bool Common::Debug::OSThread::IsValid() const -{ - return PowerPC::HostIsRAMAddress(stack_end) && PowerPC::HostRead_U32(stack_end) == STACK_MAGIC; -} - -Common::Debug::OSThreadView::OSThreadView(u32 addr) -{ - m_address = addr; - m_thread.Read(addr); -} - -const Common::Debug::OSThread& Common::Debug::OSThreadView::Data() const -{ - return m_thread; -} - -Common::Debug::PartialContext Common::Debug::OSThreadView::GetContext() const -{ - PartialContext context; - - if (!IsValid()) - return context; - - context.gpr = m_thread.context.gpr; - context.cr = m_thread.context.cr; - context.lr = m_thread.context.lr; - context.ctr = m_thread.context.ctr; - context.xer = m_thread.context.xer; - context.fpr = m_thread.context.fpr; - context.fpscr = m_thread.context.fpscr; - context.srr0 = m_thread.context.srr0; - context.srr1 = m_thread.context.srr1; - context.dummy = m_thread.context.dummy; - context.state = static_cast(m_thread.context.state); - context.gqr = m_thread.context.gqr; - context.psf = m_thread.context.psf; - - return context; -} - -u32 Common::Debug::OSThreadView::GetAddress() const -{ - return m_address; -} - -u16 Common::Debug::OSThreadView::GetState() const -{ - return m_thread.state; -} - -bool Common::Debug::OSThreadView::IsSuspended() const -{ - return m_thread.suspend > 0; -} - -bool Common::Debug::OSThreadView::IsDetached() const -{ - return m_thread.is_detached != 0; -} - -s32 Common::Debug::OSThreadView::GetBasePriority() const -{ - return m_thread.base_priority; -} - -s32 Common::Debug::OSThreadView::GetEffectivePriority() const -{ - return m_thread.effective_priority; -} - -u32 Common::Debug::OSThreadView::GetStackStart() const -{ - return m_thread.stack_addr; -} - -u32 Common::Debug::OSThreadView::GetStackEnd() const -{ - return m_thread.stack_end; -} - -std::size_t Common::Debug::OSThreadView::GetStackSize() const -{ - return GetStackStart() - GetStackEnd(); -} - -s32 Common::Debug::OSThreadView::GetErrno() const -{ - return m_thread.error; -} - -std::string Common::Debug::OSThreadView::GetSpecific() const -{ - std::string specific; - - for (u32 addr : m_thread.specific) - { - if (!PowerPC::HostIsRAMAddress(addr)) - break; - specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(addr)); - } - - return specific; -} - -bool Common::Debug::OSThreadView::IsValid() const -{ - return m_thread.IsValid(); -} diff --git a/Source/Core/Common/Debug/OSThread.h b/Source/Core/Common/Debug/OSThread.h deleted file mode 100644 index 7a588c670e..0000000000 --- a/Source/Core/Common/Debug/OSThread.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2020 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Common/Debug/Threads.h" - -namespace Common::Debug -{ -template -struct OSQueue -{ - u32 head; - u32 tail; -}; -template -struct OSLink -{ - u32 next; - u32 prev; -}; - -struct OSMutex; -struct OSThread; - -using OSThreadQueue = OSQueue; -using OSThreadLink = OSLink; - -using OSMutexQueue = OSQueue; -using OSMutexLink = OSLink; - -struct OSContext -{ - enum class State : u16 - { - HasFPU = 1, - HasException = 2, - }; - std::array gpr; - u32 cr; - u32 lr; - u32 ctr; - u32 xer; - std::array fpr; - u64 fpscr; - u32 srr0; - u32 srr1; - u16 dummy; - State state; - std::array gqr; - u32 psf_padding; - std::array psf; - - void Read(u32 addr); -}; - -static_assert(std::is_trivially_copyable_v); -static_assert(std::is_standard_layout_v); -static_assert(offsetof(OSContext, cr) == 0x80); -static_assert(offsetof(OSContext, fpscr) == 0x190); -static_assert(offsetof(OSContext, gqr) == 0x1a4); -static_assert(offsetof(OSContext, psf) == 0x1c8); - -struct OSThread -{ - OSContext context; - - u16 state; // Thread state (ready, running, waiting, moribund) - u16 is_detached; // Is thread detached - s32 suspend; // Suspended if greater than zero - s32 effective_priority; // Effective priority - s32 base_priority; // Base priority - u32 exit_code_addr; // Exit value address - - u32 queue_addr; // Address of the queue the thread is on - OSThreadLink queue_link; // Used to traverse the thread queue - // OSSleepThread uses it to insert the current thread at the end of the thread queue - - OSThreadQueue join_queue; // Threads waiting to be joined - - u32 mutex_addr; // Mutex waiting - OSMutexQueue mutex_queue; // Mutex owned - - OSThreadLink thread_link; // Link containing all active threads - - // The STACK_MAGIC is written at stack_end - u32 stack_addr; - u32 stack_end; - - s32 error; // errno value - std::array specific; // Pointers to data (can be used to store thread names) - - static constexpr u32 STACK_MAGIC = 0xDEADBABE; - void Read(u32 addr); - bool IsValid() const; -}; - -static_assert(std::is_trivially_copyable_v); -static_assert(std::is_standard_layout_v); -static_assert(offsetof(OSThread, state) == 0x2c8); -static_assert(offsetof(OSThread, mutex_addr) == 0x2f0); -static_assert(offsetof(OSThread, stack_addr) == 0x304); -static_assert(offsetof(OSThread, specific) == 0x310); - -struct OSMutex -{ - OSThreadQueue thread_queue; // Threads waiting to own the mutex - u32 owner_addr; // Thread owning the mutex - s32 lock_count; // Mutex lock count - OSMutexLink link; // Used to traverse the thread's mutex queue - // OSLockMutex uses it to insert the acquired mutex at the end of the queue - - void Read(u32 addr); -}; - -static_assert(std::is_trivially_copyable_v); -static_assert(std::is_standard_layout_v); -static_assert(offsetof(OSMutex, owner_addr) == 0x8); -static_assert(offsetof(OSMutex, link) == 0x10); - -class OSThreadView : public Common::Debug::ThreadView -{ -public: - explicit OSThreadView(u32 addr); - ~OSThreadView() = default; - - const OSThread& Data() const; - - PartialContext GetContext() const override; - u32 GetAddress() const override; - u16 GetState() const override; - bool IsSuspended() const override; - bool IsDetached() const override; - s32 GetBasePriority() const override; - s32 GetEffectivePriority() const override; - u32 GetStackStart() const override; - u32 GetStackEnd() const override; - std::size_t GetStackSize() const override; - s32 GetErrno() const override; - std::string GetSpecific() const override; - bool IsValid() const override; - -private: - u32 m_address = 0; - OSThread m_thread; -}; - -} // namespace Common::Debug diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index f39b52ed9f..017695ce45 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -80,6 +80,8 @@ add_library(core Debugger/Dump.cpp Debugger/Dump.h Debugger/GCELF.h + Debugger/OSThread.cpp + Debugger/OSThread.h Debugger/PPCDebugInterface.cpp Debugger/PPCDebugInterface.h Debugger/RSO.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 390b467614..35dd58d202 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -40,6 +40,7 @@ + @@ -399,6 +400,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 91553ac3af..73b159219f 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -217,6 +217,9 @@ Debugger + + Debugger + Debugger @@ -996,12 +999,12 @@ PowerPC\Jit64 - - HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA - - - HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA - + + HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA + + + HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA + @@ -1050,6 +1053,9 @@ Debugger + + Debugger + Debugger @@ -1755,8 +1761,8 @@ PowerPC\JitArmCommon - - HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA + + HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA diff --git a/Source/Core/Core/Debugger/OSThread.cpp b/Source/Core/Core/Debugger/OSThread.cpp new file mode 100644 index 0000000000..18a5a31b83 --- /dev/null +++ b/Source/Core/Core/Debugger/OSThread.cpp @@ -0,0 +1,208 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/Debugger/OSThread.h" + +#include +#include + +#include "Core/PowerPC/MMU.h" + +namespace Core::Debug +{ +// Context offsets based on the following functions: +// - OSSaveContext +// - OSSaveFPUContext +// - OSDumpContext +// - OSClearContext +// - OSExceptionVector +void OSContext::Read(u32 addr) +{ + for (std::size_t i = 0; i < gpr.size(); i++) + gpr[i] = PowerPC::HostRead_U32(addr + u32(i * sizeof(int))); + cr = PowerPC::HostRead_U32(addr + 0x80); + lr = PowerPC::HostRead_U32(addr + 0x84); + ctr = PowerPC::HostRead_U32(addr + 0x88); + xer = PowerPC::HostRead_U32(addr + 0x8C); + for (std::size_t i = 0; i < fpr.size(); i++) + fpr[i] = PowerPC::HostRead_F64(addr + 0x90 + u32(i * sizeof(double))); + fpscr = PowerPC::HostRead_U64(addr + 0x190); + srr0 = PowerPC::HostRead_U32(addr + 0x198); + srr1 = PowerPC::HostRead_U32(addr + 0x19c); + dummy = PowerPC::HostRead_U16(addr + 0x1a0); + state = static_cast(PowerPC::HostRead_U16(addr + 0x1a2)); + for (std::size_t i = 0; i < gqr.size(); i++) + gqr[i] = PowerPC::HostRead_U32(addr + 0x1a4 + u32(i * sizeof(int))); + psf_padding = 0; + for (std::size_t i = 0; i < psf.size(); i++) + psf[i] = PowerPC::HostRead_F64(addr + 0x1c8 + u32(i * sizeof(double))); +} + +// Mutex offsets based on the following functions: +// - OSInitMutex +// - OSLockMutex +// - __OSUnlockAllMutex +void OSMutex::Read(u32 addr) +{ + thread_queue.head = PowerPC::HostRead_U32(addr); + thread_queue.tail = PowerPC::HostRead_U32(addr + 0x4); + owner_addr = PowerPC::HostRead_U32(addr + 0x8); + lock_count = PowerPC::HostRead_U32(addr + 0xc); + link.next = PowerPC::HostRead_U32(addr + 0x10); + link.prev = PowerPC::HostRead_U32(addr + 0x14); +} + +// Thread offsets based on the following functions: +// - OSCreateThread +// - OSIsThreadTerminated +// - OSJoinThread +// - OSSuspendThread +// - OSSetPriority +// - OSExitThread +// - OSLockMutex +// - __OSUnlockAllMutex +// - __OSThreadInit +// - OSSetThreadSpecific +// - SOInit (for errno) +void OSThread::Read(u32 addr) +{ + context.Read(addr); + state = PowerPC::HostRead_U16(addr + 0x2c8); + is_detached = PowerPC::HostRead_U16(addr + 0x2ca); + suspend = PowerPC::HostRead_U32(addr + 0x2cc); + effective_priority = PowerPC::HostRead_U32(addr + 0x2d0); + base_priority = PowerPC::HostRead_U32(addr + 0x2d4); + exit_code_addr = PowerPC::HostRead_U32(addr + 0x2d8); + + queue_addr = PowerPC::HostRead_U32(addr + 0x2dc); + queue_link.next = PowerPC::HostRead_U32(addr + 0x2e0); + queue_link.prev = PowerPC::HostRead_U32(addr + 0x2e4); + + join_queue.head = PowerPC::HostRead_U32(addr + 0x2e8); + join_queue.tail = PowerPC::HostRead_U32(addr + 0x2ec); + + mutex_addr = PowerPC::HostRead_U32(addr + 0x2f0); + mutex_queue.head = PowerPC::HostRead_U32(addr + 0x2f4); + mutex_queue.tail = PowerPC::HostRead_U32(addr + 0x2f8); + + thread_link.next = PowerPC::HostRead_U32(addr + 0x2fc); + thread_link.prev = PowerPC::HostRead_U32(addr + 0x300); + + stack_addr = PowerPC::HostRead_U32(addr + 0x304); + stack_end = PowerPC::HostRead_U32(addr + 0x308); + error = PowerPC::HostRead_U32(addr + 0x30c); + specific[0] = PowerPC::HostRead_U32(addr + 0x310); + specific[1] = PowerPC::HostRead_U32(addr + 0x314); +} + +bool OSThread::IsValid() const +{ + return PowerPC::HostIsRAMAddress(stack_end) && PowerPC::HostRead_U32(stack_end) == STACK_MAGIC; +} + +OSThreadView::OSThreadView(u32 addr) +{ + m_address = addr; + m_thread.Read(addr); +} + +const OSThread& OSThreadView::Data() const +{ + return m_thread; +} + +Common::Debug::PartialContext OSThreadView::GetContext() const +{ + Common::Debug::PartialContext context; + + if (!IsValid()) + return context; + + context.gpr = m_thread.context.gpr; + context.cr = m_thread.context.cr; + context.lr = m_thread.context.lr; + context.ctr = m_thread.context.ctr; + context.xer = m_thread.context.xer; + context.fpr = m_thread.context.fpr; + context.fpscr = m_thread.context.fpscr; + context.srr0 = m_thread.context.srr0; + context.srr1 = m_thread.context.srr1; + context.dummy = m_thread.context.dummy; + context.state = static_cast(m_thread.context.state); + context.gqr = m_thread.context.gqr; + context.psf = m_thread.context.psf; + + return context; +} + +u32 OSThreadView::GetAddress() const +{ + return m_address; +} + +u16 OSThreadView::GetState() const +{ + return m_thread.state; +} + +bool OSThreadView::IsSuspended() const +{ + return m_thread.suspend > 0; +} + +bool OSThreadView::IsDetached() const +{ + return m_thread.is_detached != 0; +} + +s32 OSThreadView::GetBasePriority() const +{ + return m_thread.base_priority; +} + +s32 OSThreadView::GetEffectivePriority() const +{ + return m_thread.effective_priority; +} + +u32 OSThreadView::GetStackStart() const +{ + return m_thread.stack_addr; +} + +u32 OSThreadView::GetStackEnd() const +{ + return m_thread.stack_end; +} + +std::size_t OSThreadView::GetStackSize() const +{ + return GetStackStart() - GetStackEnd(); +} + +s32 OSThreadView::GetErrno() const +{ + return m_thread.error; +} + +std::string OSThreadView::GetSpecific() const +{ + std::string specific; + + for (u32 addr : m_thread.specific) + { + if (!PowerPC::HostIsRAMAddress(addr)) + break; + specific += fmt::format("{:08x} \"{}\"\n", addr, PowerPC::HostGetString(addr)); + } + + return specific; +} + +bool OSThreadView::IsValid() const +{ + return m_thread.IsValid(); +} + +} // namespace Core::Debug diff --git a/Source/Core/Core/Debugger/OSThread.h b/Source/Core/Core/Debugger/OSThread.h new file mode 100644 index 0000000000..c5aa3fee8d --- /dev/null +++ b/Source/Core/Core/Debugger/OSThread.h @@ -0,0 +1,154 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/Debug/Threads.h" + +namespace Core::Debug +{ +template +struct OSQueue +{ + u32 head; + u32 tail; +}; +template +struct OSLink +{ + u32 next; + u32 prev; +}; + +struct OSMutex; +struct OSThread; + +using OSThreadQueue = OSQueue; +using OSThreadLink = OSLink; + +using OSMutexQueue = OSQueue; +using OSMutexLink = OSLink; + +struct OSContext +{ + enum class State : u16 + { + HasFPU = 1, + HasException = 2, + }; + std::array gpr; + u32 cr; + u32 lr; + u32 ctr; + u32 xer; + std::array fpr; + u64 fpscr; + u32 srr0; + u32 srr1; + u16 dummy; + State state; + std::array gqr; + u32 psf_padding; + std::array psf; + + void Read(u32 addr); +}; + +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_standard_layout_v); +static_assert(offsetof(OSContext, cr) == 0x80); +static_assert(offsetof(OSContext, fpscr) == 0x190); +static_assert(offsetof(OSContext, gqr) == 0x1a4); +static_assert(offsetof(OSContext, psf) == 0x1c8); + +struct OSThread +{ + OSContext context; + + u16 state; // Thread state (ready, running, waiting, moribund) + u16 is_detached; // Is thread detached + s32 suspend; // Suspended if greater than zero + s32 effective_priority; // Effective priority + s32 base_priority; // Base priority + u32 exit_code_addr; // Exit value address + + u32 queue_addr; // Address of the queue the thread is on + OSThreadLink queue_link; // Used to traverse the thread queue + // OSSleepThread uses it to insert the current thread at the end of the thread queue + + OSThreadQueue join_queue; // Threads waiting to be joined + + u32 mutex_addr; // Mutex waiting + OSMutexQueue mutex_queue; // Mutex owned + + OSThreadLink thread_link; // Link containing all active threads + + // The STACK_MAGIC is written at stack_end + u32 stack_addr; + u32 stack_end; + + s32 error; // errno value + std::array specific; // Pointers to data (can be used to store thread names) + + static constexpr u32 STACK_MAGIC = 0xDEADBABE; + void Read(u32 addr); + bool IsValid() const; +}; + +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_standard_layout_v); +static_assert(offsetof(OSThread, state) == 0x2c8); +static_assert(offsetof(OSThread, mutex_addr) == 0x2f0); +static_assert(offsetof(OSThread, stack_addr) == 0x304); +static_assert(offsetof(OSThread, specific) == 0x310); + +struct OSMutex +{ + OSThreadQueue thread_queue; // Threads waiting to own the mutex + u32 owner_addr; // Thread owning the mutex + s32 lock_count; // Mutex lock count + OSMutexLink link; // Used to traverse the thread's mutex queue + // OSLockMutex uses it to insert the acquired mutex at the end of the queue + + void Read(u32 addr); +}; + +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_standard_layout_v); +static_assert(offsetof(OSMutex, owner_addr) == 0x8); +static_assert(offsetof(OSMutex, link) == 0x10); + +class OSThreadView : public Common::Debug::ThreadView +{ +public: + explicit OSThreadView(u32 addr); + ~OSThreadView() = default; + + const OSThread& Data() const; + + Common::Debug::PartialContext GetContext() const override; + u32 GetAddress() const override; + u16 GetState() const override; + bool IsSuspended() const override; + bool IsDetached() const override; + s32 GetBasePriority() const override; + s32 GetEffectivePriority() const override; + u32 GetStackStart() const override; + u32 GetStackEnd() const override; + std::size_t GetStackSize() const override; + s32 GetErrno() const override; + std::string GetSpecific() const override; + bool IsValid() const override; + +private: + u32 m_address = 0; + OSThread m_thread; +}; + +} // namespace Core::Debug diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index f44c20d7f2..0ca90f52b4 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -11,10 +11,10 @@ #include #include "Common/Align.h" -#include "Common/Debug/OSThread.h" #include "Common/GekkoDisassembler.h" #include "Core/Core.h" +#include "Core/Debugger/OSThread.h" #include "Core/HW/DSP.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PPCSymbolDB.h" @@ -176,14 +176,14 @@ Common::Debug::Threads PPCDebugInterface::GetThreads() const if (!PowerPC::HostIsRAMAddress(active_queue_head)) return threads; - auto active_thread = std::make_unique(active_queue_head); + auto active_thread = std::make_unique(active_queue_head); if (!active_thread->IsValid()) return threads; const auto insert_threads = [&threads](u32 addr, auto get_next_addr) { while (addr != 0 && PowerPC::HostIsRAMAddress(addr)) { - auto thread = std::make_unique(addr); + auto thread = std::make_unique(addr); if (!thread->IsValid()) break; addr = get_next_addr(*thread); -- cgit v1.2.3