diff options
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 4 |
4 files changed, 70 insertions, 1 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 955769503..52f253d1e 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -80,6 +80,14 @@ u64 Process::GetTotalPhysicalMemoryUsed() const { | |||
| 80 | return vm_manager.GetCurrentHeapSize() + main_thread_stack_size + code_memory_size; | 80 | return vm_manager.GetCurrentHeapSize() + main_thread_stack_size + code_memory_size; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | void Process::RegisterThread(const Thread* thread) { | ||
| 84 | thread_list.push_back(thread); | ||
| 85 | } | ||
| 86 | |||
| 87 | void Process::UnregisterThread(const Thread* thread) { | ||
| 88 | thread_list.remove(thread); | ||
| 89 | } | ||
| 90 | |||
| 83 | ResultCode Process::ClearSignalState() { | 91 | ResultCode Process::ClearSignalState() { |
| 84 | if (status == ProcessStatus::Exited) { | 92 | if (status == ProcessStatus::Exited) { |
| 85 | LOG_ERROR(Kernel, "called on a terminated process instance."); | 93 | LOG_ERROR(Kernel, "called on a terminated process instance."); |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 732d12170..f9ddc937c 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <bitset> | 8 | #include <bitset> |
| 9 | #include <cstddef> | 9 | #include <cstddef> |
| 10 | #include <list> | ||
| 10 | #include <string> | 11 | #include <string> |
| 11 | #include <vector> | 12 | #include <vector> |
| 12 | #include <boost/container/static_vector.hpp> | 13 | #include <boost/container/static_vector.hpp> |
| @@ -189,6 +190,19 @@ public: | |||
| 189 | /// Retrieves the total physical memory used by this process in bytes. | 190 | /// Retrieves the total physical memory used by this process in bytes. |
| 190 | u64 GetTotalPhysicalMemoryUsed() const; | 191 | u64 GetTotalPhysicalMemoryUsed() const; |
| 191 | 192 | ||
| 193 | /// Gets the list of all threads created with this process as their owner. | ||
| 194 | const std::list<const Thread*>& GetThreadList() const { | ||
| 195 | return thread_list; | ||
| 196 | } | ||
| 197 | |||
| 198 | /// Registers a thread as being created under this process, | ||
| 199 | /// adding it to this process' thread list. | ||
| 200 | void RegisterThread(const Thread* thread); | ||
| 201 | |||
| 202 | /// Unregisters a thread from this process, removing it | ||
| 203 | /// from this process' thread list. | ||
| 204 | void UnregisterThread(const Thread* thread); | ||
| 205 | |||
| 192 | /// Clears the signaled state of the process if and only if it's signaled. | 206 | /// Clears the signaled state of the process if and only if it's signaled. |
| 193 | /// | 207 | /// |
| 194 | /// @pre The process must not be already terminated. If this is called on a | 208 | /// @pre The process must not be already terminated. If this is called on a |
| @@ -308,6 +322,9 @@ private: | |||
| 308 | /// Random values for svcGetInfo RandomEntropy | 322 | /// Random values for svcGetInfo RandomEntropy |
| 309 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy; | 323 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy; |
| 310 | 324 | ||
| 325 | /// List of threads that are running with this process as their owner. | ||
| 326 | std::list<const Thread*> thread_list; | ||
| 327 | |||
| 311 | /// System context | 328 | /// System context |
| 312 | Core::System& system; | 329 | Core::System& system; |
| 313 | 330 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 3cd948bb5..23c768f57 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -2020,6 +2020,46 @@ static ResultCode GetProcessList(u32* out_num_processes, VAddr out_process_ids, | |||
| 2020 | return RESULT_SUCCESS; | 2020 | return RESULT_SUCCESS; |
| 2021 | } | 2021 | } |
| 2022 | 2022 | ||
| 2023 | ResultCode GetThreadList(u32* out_num_threads, VAddr out_thread_ids, u32 out_thread_ids_size, | ||
| 2024 | Handle debug_handle) { | ||
| 2025 | // TODO: Handle this case when debug events are supported. | ||
| 2026 | UNIMPLEMENTED_IF(debug_handle != InvalidHandle); | ||
| 2027 | |||
| 2028 | LOG_DEBUG(Kernel_SVC, "called. out_thread_ids=0x{:016X}, out_thread_ids_size={}", | ||
| 2029 | out_thread_ids, out_thread_ids_size); | ||
| 2030 | |||
| 2031 | // If the size is negative or larger than INT32_MAX / sizeof(u64) | ||
| 2032 | if ((out_thread_ids_size & 0xF0000000) != 0) { | ||
| 2033 | LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. size={}", | ||
| 2034 | out_thread_ids_size); | ||
| 2035 | return ERR_OUT_OF_RANGE; | ||
| 2036 | } | ||
| 2037 | |||
| 2038 | const auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess(); | ||
| 2039 | const auto& vm_manager = current_process->VMManager(); | ||
| 2040 | const auto total_copy_size = out_thread_ids_size * sizeof(u64); | ||
| 2041 | |||
| 2042 | if (out_thread_ids_size > 0 && | ||
| 2043 | !vm_manager.IsWithinAddressSpace(out_thread_ids, total_copy_size)) { | ||
| 2044 | LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", | ||
| 2045 | out_thread_ids, out_thread_ids + total_copy_size); | ||
| 2046 | return ERR_INVALID_ADDRESS_STATE; | ||
| 2047 | } | ||
| 2048 | |||
| 2049 | const auto& thread_list = current_process->GetThreadList(); | ||
| 2050 | const auto num_threads = thread_list.size(); | ||
| 2051 | const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads); | ||
| 2052 | |||
| 2053 | auto list_iter = thread_list.cbegin(); | ||
| 2054 | for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { | ||
| 2055 | Memory::Write64(out_thread_ids, (*list_iter)->GetThreadID()); | ||
| 2056 | out_thread_ids += sizeof(u64); | ||
| 2057 | } | ||
| 2058 | |||
| 2059 | *out_num_threads = static_cast<u32>(num_threads); | ||
| 2060 | return RESULT_SUCCESS; | ||
| 2061 | } | ||
| 2062 | |||
| 2023 | namespace { | 2063 | namespace { |
| 2024 | struct FunctionDef { | 2064 | struct FunctionDef { |
| 2025 | using Func = void(); | 2065 | using Func = void(); |
| @@ -2133,7 +2173,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 2133 | {0x63, nullptr, "GetDebugEvent"}, | 2173 | {0x63, nullptr, "GetDebugEvent"}, |
| 2134 | {0x64, nullptr, "ContinueDebugEvent"}, | 2174 | {0x64, nullptr, "ContinueDebugEvent"}, |
| 2135 | {0x65, SvcWrap<GetProcessList>, "GetProcessList"}, | 2175 | {0x65, SvcWrap<GetProcessList>, "GetProcessList"}, |
| 2136 | {0x66, nullptr, "GetThreadList"}, | 2176 | {0x66, SvcWrap<GetThreadList>, "GetThreadList"}, |
| 2137 | {0x67, nullptr, "GetDebugThreadContext"}, | 2177 | {0x67, nullptr, "GetDebugThreadContext"}, |
| 2138 | {0x68, nullptr, "SetDebugThreadContext"}, | 2178 | {0x68, nullptr, "SetDebugThreadContext"}, |
| 2139 | {0x69, nullptr, "QueryDebugProcessMemory"}, | 2179 | {0x69, nullptr, "QueryDebugProcessMemory"}, |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index fa3ac3abc..3ec3710b2 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -62,6 +62,8 @@ void Thread::Stop() { | |||
| 62 | } | 62 | } |
| 63 | wait_objects.clear(); | 63 | wait_objects.clear(); |
| 64 | 64 | ||
| 65 | owner_process->UnregisterThread(this); | ||
| 66 | |||
| 65 | // Mark the TLS slot in the thread's page as free. | 67 | // Mark the TLS slot in the thread's page as free. |
| 66 | owner_process->FreeTLSSlot(tls_address); | 68 | owner_process->FreeTLSSlot(tls_address); |
| 67 | } | 69 | } |
| @@ -202,6 +204,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name | |||
| 202 | thread->scheduler->AddThread(thread); | 204 | thread->scheduler->AddThread(thread); |
| 203 | thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread); | 205 | thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread); |
| 204 | 206 | ||
| 207 | thread->owner_process->RegisterThread(thread.get()); | ||
| 208 | |||
| 205 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used | 209 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used |
| 206 | // to initialize the context | 210 | // to initialize the context |
| 207 | ResetThreadContext(thread->context, stack_top, entry_point, arg); | 211 | ResetThreadContext(thread->context, stack_top, entry_point, arg); |