forked from suyu/suyu
service: add os types and multi wait API
This commit is contained in:
parent
c10e720ba9
commit
9404633bfd
13 changed files with 287 additions and 9 deletions
|
@ -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 a new issue