Browse Source
Merge pull request #12949 from liamwhite/multi-wait
Merge pull request #12949 from liamwhite/multi-wait
service: add os types and multi wait APIpull/15/merge
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 569 additions and 352 deletions
-
13src/core/CMakeLists.txt
-
2src/core/hle/service/am/applet.h
-
2src/core/hle/service/am/applet_data_broker.h
-
130src/core/hle/service/glue/time/worker.cpp
-
2src/core/hle/service/os/event.cpp
-
0src/core/hle/service/os/event.h
-
59src/core/hle/service/os/multi_wait.cpp
-
36src/core/hle/service/os/multi_wait.h
-
25src/core/hle/service/os/multi_wait_holder.cpp
-
44src/core/hle/service/os/multi_wait_holder.h
-
109src/core/hle/service/os/multi_wait_utils.h
-
2src/core/hle/service/os/mutex.cpp
-
0src/core/hle/service/os/mutex.h
-
438src/core/hle/service/server_manager.cpp
-
59src/core/hle/service/server_manager.h
@ -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
|
|||
@ -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 |
|||
@ -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
|
|||
@ -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 |
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue