1 // Copyright 2020 Dolphin Emulator Project 2 // Licensed under GPLv2+ 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <string> 9 #include <type_traits> 10 11 #include "Common/CommonTypes.h" 12 #include "Common/Debug/Threads.h" 13 14 namespace Common::Debug 15 { 16 template <class C> 17 struct OSQueue 18 { 19 u32 head; 20 u32 tail; 21 }; 22 template <class C> 23 struct OSLink 24 { 25 u32 next; 26 u32 prev; 27 }; 28 29 struct OSMutex; 30 struct OSThread; 31 32 using OSThreadQueue = OSQueue<OSThread>; 33 using OSThreadLink = OSLink<OSThread>; 34 35 using OSMutexQueue = OSQueue<OSMutex>; 36 using OSMutexLink = OSLink<OSMutex>; 37 38 struct OSContext 39 { 40 enum class State : u16 41 { 42 HasFPU = 1, 43 HasException = 2, 44 }; 45 std::array<u32, 32> gpr; 46 u32 cr; 47 u32 lr; 48 u32 ctr; 49 u32 xer; 50 std::array<double, 32> fpr; 51 u64 fpscr; 52 u32 srr0; 53 u32 srr1; 54 u16 dummy; 55 State state; 56 std::array<u32, 8> gqr; 57 u32 psf_padding; 58 std::array<double, 32> psf; 59 60 void Read(u32 addr); 61 }; 62 63 static_assert(std::is_trivially_copyable_v<OSContext>); 64 static_assert(std::is_standard_layout_v<OSContext>); 65 static_assert(offsetof(OSContext, cr) == 0x80); 66 static_assert(offsetof(OSContext, fpscr) == 0x190); 67 static_assert(offsetof(OSContext, gqr) == 0x1a4); 68 static_assert(offsetof(OSContext, psf) == 0x1c8); 69 70 struct OSThread 71 { 72 OSContext context; 73 74 u16 state; // Thread state (ready, running, waiting, moribund) 75 u16 is_detached; // Is thread detached 76 s32 suspend; // Suspended if greater than zero 77 s32 effective_priority; // Effective priority 78 s32 base_priority; // Base priority 79 u32 exit_code_addr; // Exit value address 80 81 u32 queue_addr; // Address of the queue the thread is on 82 OSThreadLink queue_link; // Used to traverse the thread queue 83 // OSSleepThread uses it to insert the current thread at the end of the thread queue 84 85 OSThreadQueue join_queue; // Threads waiting to be joined 86 87 u32 mutex_addr; // Mutex waiting 88 OSMutexQueue mutex_queue; // Mutex owned 89 90 OSThreadLink thread_link; // Link containing all active threads 91 92 // The STACK_MAGIC is written at stack_end 93 u32 stack_addr; 94 u32 stack_end; 95 96 s32 error; // errno value 97 std::array<u32, 2> specific; // Pointers to data (can be used to store thread names) 98 99 static constexpr u32 STACK_MAGIC = 0xDEADBABE; 100 void Read(u32 addr); 101 bool IsValid() const; 102 }; 103 104 static_assert(std::is_trivially_copyable_v<OSThread>); 105 static_assert(std::is_standard_layout_v<OSThread>); 106 static_assert(offsetof(OSThread, state) == 0x2c8); 107 static_assert(offsetof(OSThread, mutex_addr) == 0x2f0); 108 static_assert(offsetof(OSThread, stack_addr) == 0x304); 109 static_assert(offsetof(OSThread, specific) == 0x310); 110 111 struct OSMutex 112 { 113 OSThreadQueue thread_queue; // Threads waiting to own the mutex 114 u32 owner_addr; // Thread owning the mutex 115 s32 lock_count; // Mutex lock count 116 OSMutexLink link; // Used to traverse the thread's mutex queue 117 // OSLockMutex uses it to insert the acquired mutex at the end of the queue 118 119 void Read(u32 addr); 120 }; 121 122 static_assert(std::is_trivially_copyable_v<OSMutex>); 123 static_assert(std::is_standard_layout_v<OSMutex>); 124 static_assert(offsetof(OSMutex, owner_addr) == 0x8); 125 static_assert(offsetof(OSMutex, link) == 0x10); 126 127 class OSThreadView : public Common::Debug::ThreadView 128 { 129 public: 130 explicit OSThreadView(u32 addr); 131 ~OSThreadView() = default; 132 133 const OSThread& Data() const; 134 135 PartialContext GetContext() const override; 136 u32 GetAddress() const override; 137 u16 GetState() const override; 138 bool IsSuspended() const override; 139 bool IsDetached() const override; 140 s32 GetBasePriority() const override; 141 s32 GetEffectivePriority() const override; 142 u32 GetStackStart() const override; 143 u32 GetStackEnd() const override; 144 std::size_t GetStackSize() const override; 145 s32 GetErrno() const override; 146 std::string GetSpecific() const override; 147 bool IsValid() const override; 148 149 private: 150 u32 m_address = 0; 151 OSThread m_thread; 152 }; 153 154 } // namespace Common::Debug 155