13 changed files with 287 additions and 9 deletions
-
13src/core/CMakeLists.txt
-
2src/core/hle/service/am/applet.h
-
2src/core/hle/service/am/applet_data_broker.h
-
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
-
2src/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