mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	service: add os types and multi wait API
This commit is contained in:
		
							parent
							
								
									c10e720ba9
								
							
						
					
					
						commit
						9404633bfd
					
				| @ -548,8 +548,6 @@ add_library(core STATIC | ||||
|     hle/service/es/es.h | ||||
|     hle/service/eupld/eupld.cpp | ||||
|     hle/service/eupld/eupld.h | ||||
|     hle/service/event.cpp | ||||
|     hle/service/event.h | ||||
|     hle/service/fatal/fatal.cpp | ||||
|     hle/service/fatal/fatal.h | ||||
|     hle/service/fatal/fatal_p.cpp | ||||
| @ -676,8 +674,6 @@ add_library(core STATIC | ||||
|     hle/service/mm/mm_u.h | ||||
|     hle/service/mnpp/mnpp_app.cpp | ||||
|     hle/service/mnpp/mnpp_app.h | ||||
|     hle/service/mutex.cpp | ||||
|     hle/service/mutex.h | ||||
|     hle/service/ncm/ncm.cpp | ||||
|     hle/service/ncm/ncm.h | ||||
|     hle/service/nfc/common/amiibo_crypto.cpp | ||||
| @ -790,6 +786,15 @@ add_library(core STATIC | ||||
|     hle/service/nvnflinger/window.h | ||||
|     hle/service/olsc/olsc.cpp | ||||
|     hle/service/olsc/olsc.h | ||||
|     hle/service/os/event.cpp | ||||
|     hle/service/os/event.h | ||||
|     hle/service/os/multi_wait_holder.cpp | ||||
|     hle/service/os/multi_wait_holder.h | ||||
|     hle/service/os/multi_wait_utils.h | ||||
|     hle/service/os/multi_wait.cpp | ||||
|     hle/service/os/multi_wait.h | ||||
|     hle/service/os/mutex.cpp | ||||
|     hle/service/os/mutex.h | ||||
|     hle/service/pcie/pcie.cpp | ||||
|     hle/service/pcie/pcie.h | ||||
|     hle/service/pctl/pctl.cpp | ||||
|  | ||||
| @ -9,8 +9,8 @@ | ||||
| #include "common/math_util.h" | ||||
| #include "core/hle/service/apm/apm_controller.h" | ||||
| #include "core/hle/service/caps/caps_types.h" | ||||
| #include "core/hle/service/event.h" | ||||
| #include "core/hle/service/kernel_helpers.h" | ||||
| #include "core/hle/service/os/event.h" | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| #include "core/hle/service/am/am_types.h" | ||||
|  | ||||
| @ -7,8 +7,8 @@ | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| 
 | ||||
| #include "core/hle/service/event.h" | ||||
| #include "core/hle/service/kernel_helpers.h" | ||||
| #include "core/hle/service/os/event.h" | ||||
| 
 | ||||
| union Result; | ||||
| 
 | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/kernel/k_event.h" | ||||
| #include "core/hle/service/event.h" | ||||
| #include "core/hle/service/kernel_helpers.h" | ||||
| #include "core/hle/service/os/event.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
							
								
								
									
										59
									
								
								src/core/hle/service/os/multi_wait.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/core/hle/service/os/multi_wait.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/kernel/k_hardware_timer.h" | ||||
| #include "core/hle/kernel/k_synchronization_object.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/svc_common.h" | ||||
| #include "core/hle/service/os/multi_wait.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| MultiWait::MultiWait() = default; | ||||
| MultiWait::~MultiWait() = default; | ||||
| 
 | ||||
| MultiWaitHolder* MultiWait::WaitAny(Kernel::KernelCore& kernel) { | ||||
|     return this->TimedWaitImpl(kernel, -1); | ||||
| } | ||||
| 
 | ||||
| MultiWaitHolder* MultiWait::TryWaitAny(Kernel::KernelCore& kernel) { | ||||
|     return this->TimedWaitImpl(kernel, 0); | ||||
| } | ||||
| 
 | ||||
| MultiWaitHolder* MultiWait::TimedWaitAny(Kernel::KernelCore& kernel, s64 timeout_ns) { | ||||
|     return this->TimedWaitImpl(kernel, kernel.HardwareTimer().GetTick() + timeout_ns); | ||||
| } | ||||
| 
 | ||||
| MultiWaitHolder* MultiWait::TimedWaitImpl(Kernel::KernelCore& kernel, s64 timeout_tick) { | ||||
|     std::array<MultiWaitHolder*, Kernel::Svc::ArgumentHandleCountMax> holders{}; | ||||
|     std::array<Kernel::KSynchronizationObject*, Kernel::Svc::ArgumentHandleCountMax> objects{}; | ||||
| 
 | ||||
|     s32 out_index = -1; | ||||
|     s32 num_objects = 0; | ||||
| 
 | ||||
|     for (auto it = m_wait_list.begin(); it != m_wait_list.end(); it++) { | ||||
|         ASSERT(num_objects < Kernel::Svc::ArgumentHandleCountMax); | ||||
|         holders[num_objects] = std::addressof(*it); | ||||
|         objects[num_objects] = it->GetNativeHandle(); | ||||
|         num_objects++; | ||||
|     } | ||||
| 
 | ||||
|     Kernel::KSynchronizationObject::Wait(kernel, std::addressof(out_index), objects.data(), | ||||
|                                          num_objects, timeout_tick); | ||||
| 
 | ||||
|     if (out_index == -1) { | ||||
|         return nullptr; | ||||
|     } else { | ||||
|         return holders[out_index]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void MultiWait::MoveAll(MultiWait* other) { | ||||
|     while (!other->m_wait_list.empty()) { | ||||
|         MultiWaitHolder& holder = other->m_wait_list.front(); | ||||
|         holder.UnlinkFromMultiWait(); | ||||
|         holder.LinkToMultiWait(this); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Service
 | ||||
							
								
								
									
										36
									
								
								src/core/hle/service/os/multi_wait.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/core/hle/service/os/multi_wait.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/service/os/multi_wait_holder.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| class KernelCore; | ||||
| } | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| class MultiWait final { | ||||
| public: | ||||
|     explicit MultiWait(); | ||||
|     ~MultiWait(); | ||||
| 
 | ||||
| public: | ||||
|     MultiWaitHolder* WaitAny(Kernel::KernelCore& kernel); | ||||
|     MultiWaitHolder* TryWaitAny(Kernel::KernelCore& kernel); | ||||
|     MultiWaitHolder* TimedWaitAny(Kernel::KernelCore& kernel, s64 timeout_ns); | ||||
|     // TODO: SdkReplyAndReceive?
 | ||||
| 
 | ||||
|     void MoveAll(MultiWait* other); | ||||
| 
 | ||||
| private: | ||||
|     MultiWaitHolder* TimedWaitImpl(Kernel::KernelCore& kernel, s64 timeout_tick); | ||||
| 
 | ||||
| private: | ||||
|     friend class MultiWaitHolder; | ||||
|     using ListType = Common::IntrusiveListMemberTraits<&MultiWaitHolder::m_list_node>::ListType; | ||||
|     ListType m_wait_list{}; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service
 | ||||
							
								
								
									
										25
									
								
								src/core/hle/service/os/multi_wait_holder.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/core/hle/service/os/multi_wait_holder.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/os/multi_wait.h" | ||||
| #include "core/hle/service/os/multi_wait_holder.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| void MultiWaitHolder::LinkToMultiWait(MultiWait* multi_wait) { | ||||
|     if (m_multi_wait != nullptr) { | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
| 
 | ||||
|     m_multi_wait = multi_wait; | ||||
|     m_multi_wait->m_wait_list.push_back(*this); | ||||
| } | ||||
| 
 | ||||
| void MultiWaitHolder::UnlinkFromMultiWait() { | ||||
|     if (m_multi_wait) { | ||||
|         m_multi_wait->m_wait_list.erase(m_multi_wait->m_wait_list.iterator_to(*this)); | ||||
|         m_multi_wait = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Service
 | ||||
							
								
								
									
										44
									
								
								src/core/hle/service/os/multi_wait_holder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/core/hle/service/os/multi_wait_holder.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/intrusive_list.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| class KSynchronizationObject; | ||||
| } // namespace Kernel
 | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| class MultiWait; | ||||
| 
 | ||||
| class MultiWaitHolder { | ||||
| public: | ||||
|     explicit MultiWaitHolder(Kernel::KSynchronizationObject* native_handle) | ||||
|         : m_native_handle(native_handle) {} | ||||
| 
 | ||||
|     void LinkToMultiWait(MultiWait* multi_wait); | ||||
|     void UnlinkFromMultiWait(); | ||||
| 
 | ||||
|     void SetUserData(uintptr_t user_data) { | ||||
|         m_user_data = user_data; | ||||
|     } | ||||
| 
 | ||||
|     uintptr_t GetUserData() const { | ||||
|         return m_user_data; | ||||
|     } | ||||
| 
 | ||||
|     Kernel::KSynchronizationObject* GetNativeHandle() const { | ||||
|         return m_native_handle; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     friend class MultiWait; | ||||
|     Common::IntrusiveListNode m_list_node{}; | ||||
|     MultiWait* m_multi_wait{}; | ||||
|     Kernel::KSynchronizationObject* m_native_handle{}; | ||||
|     uintptr_t m_user_data{}; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service
 | ||||
							
								
								
									
										109
									
								
								src/core/hle/service/os/multi_wait_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/core/hle/service/os/multi_wait_utils.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/service/os/multi_wait.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| namespace impl { | ||||
| 
 | ||||
| class AutoMultiWaitHolder { | ||||
| private: | ||||
|     MultiWaitHolder m_holder; | ||||
| 
 | ||||
| public: | ||||
|     template <typename T> | ||||
|     explicit AutoMultiWaitHolder(MultiWait* multi_wait, T&& arg) : m_holder(arg) { | ||||
|         m_holder.LinkToMultiWait(multi_wait); | ||||
|     } | ||||
| 
 | ||||
|     ~AutoMultiWaitHolder() { | ||||
|         m_holder.UnlinkFromMultiWait(); | ||||
|     } | ||||
| 
 | ||||
|     std::pair<MultiWaitHolder*, int> ConvertResult(const std::pair<MultiWaitHolder*, int> result, | ||||
|                                                    int index) { | ||||
|         if (result.first == std::addressof(m_holder)) { | ||||
|             return std::make_pair(static_cast<MultiWaitHolder*>(nullptr), index); | ||||
|         } else { | ||||
|             return result; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| using WaitAnyFunction = decltype(&MultiWait::WaitAny); | ||||
| 
 | ||||
| inline std::pair<MultiWaitHolder*, int> WaitAnyImpl(Kernel::KernelCore& kernel, | ||||
|                                                     MultiWait* multi_wait, WaitAnyFunction func, | ||||
|                                                     int) { | ||||
|     return std::pair<MultiWaitHolder*, int>((multi_wait->*func)(kernel), -1); | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename... Args> | ||||
| inline std::pair<MultiWaitHolder*, int> WaitAnyImpl(Kernel::KernelCore& kernel, | ||||
|                                                     MultiWait* multi_wait, WaitAnyFunction func, | ||||
|                                                     int index, T&& x, Args&&... args) { | ||||
|     AutoMultiWaitHolder holder(multi_wait, std::forward<T>(x)); | ||||
|     return holder.ConvertResult( | ||||
|         WaitAnyImpl(kernel, multi_wait, func, index + 1, std::forward<Args>(args)...), index); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
| inline std::pair<MultiWaitHolder*, int> WaitAnyImpl(Kernel::KernelCore& kernel, | ||||
|                                                     MultiWait* multi_wait, WaitAnyFunction func, | ||||
|                                                     Args&&... args) { | ||||
|     return WaitAnyImpl(kernel, multi_wait, func, 0, std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
| inline std::pair<MultiWaitHolder*, int> WaitAnyImpl(Kernel::KernelCore& kernel, | ||||
|                                                     WaitAnyFunction func, Args&&... args) { | ||||
|     MultiWait temp_multi_wait; | ||||
|     return WaitAnyImpl(kernel, std::addressof(temp_multi_wait), func, 0, | ||||
|                        std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| class NotBoolButInt { | ||||
| public: | ||||
|     constexpr NotBoolButInt(int v) : m_value(v) {} | ||||
|     constexpr operator int() const { | ||||
|         return m_value; | ||||
|     } | ||||
|     explicit operator bool() const = delete; | ||||
| 
 | ||||
| private: | ||||
|     int m_value; | ||||
| }; | ||||
| 
 | ||||
| } // namespace impl
 | ||||
| 
 | ||||
| template <typename... Args> | ||||
|     requires(sizeof...(Args) > 0) | ||||
| inline std::pair<MultiWaitHolder*, int> WaitAny(Kernel::KernelCore& kernel, MultiWait* multi_wait, | ||||
|                                                 Args&&... args) { | ||||
|     return impl::WaitAnyImpl(kernel, &MultiWait::WaitAny, multi_wait, std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
|     requires(sizeof...(Args) > 0) | ||||
| inline int WaitAny(Kernel::KernelCore& kernel, Args&&... args) { | ||||
|     return impl::WaitAnyImpl(kernel, &MultiWait::WaitAny, std::forward<Args>(args)...).second; | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
|     requires(sizeof...(Args) > 0) | ||||
| inline std::pair<MultiWaitHolder*, int> TryWaitAny(Kernel::KernelCore& kernel, | ||||
|                                                    MultiWait* multi_wait, Args&&... args) { | ||||
|     return impl::WaitAnyImpl(kernel, &MultiWait::TryWaitAny, multi_wait, | ||||
|                              std::forward<Args>(args)...); | ||||
| } | ||||
| 
 | ||||
| template <typename... Args> | ||||
|     requires(sizeof...(Args) > 0) | ||||
| inline impl::NotBoolButInt TryWaitAny(Kernel::KernelCore& kernel, Args&&... args) { | ||||
|     return impl::WaitAnyImpl(kernel, &MultiWait::TryWaitAny, std::forward<Args>(args)...).second; | ||||
| } | ||||
| 
 | ||||
| } // namespace Service
 | ||||
| @ -4,7 +4,7 @@ | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/k_event.h" | ||||
| #include "core/hle/kernel/k_synchronization_object.h" | ||||
| #include "core/hle/service/mutex.h" | ||||
| #include "core/hle/service/os/mutex.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| @ -14,7 +14,7 @@ | ||||
| #include "common/thread.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/hle_ipc.h" | ||||
| #include "core/hle/service/mutex.h" | ||||
| #include "core/hle/service/os/mutex.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user