summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp37
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp41
3 files changed, 52 insertions, 36 deletions
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index dd662b3f8..d178c2453 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -338,6 +338,15 @@ public:
return m_parent != nullptr;
}
+ std::span<KSynchronizationObject*> GetSynchronizationObjectBuffer() {
+ return m_sync_object_buffer.sync_objects;
+ }
+
+ std::span<Handle> GetHandleBuffer() {
+ return {m_sync_object_buffer.handles.data() + Svc::ArgumentHandleCountMax,
+ Svc::ArgumentHandleCountMax};
+ }
+
u16 GetUserDisableCount() const;
void SetInterruptFlag();
void ClearInterruptFlag();
@@ -855,6 +864,7 @@ private:
u32* m_light_ipc_data{};
KProcessAddress m_tls_address{};
KLightLock m_activity_pause_lock;
+ SyncObjectBuffer m_sync_object_buffer{};
s64 m_schedule_count{};
s64 m_last_scheduled_tick{};
std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{};
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 60247df2e..bb94f6934 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -38,22 +38,31 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) {
+ // Ensure number of handles is valid.
+ R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+
+ // Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
-
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
- R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
- handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
- ResultInvalidPointer);
-
- std::array<Handle, Svc::ArgumentHandleCountMax> handles;
- GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
-
- // Convert handle list to object table.
- std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
- R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),
- num_handles),
- ResultInvalidHandle);
+ auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
+ auto handles = GetCurrentThread(kernel).GetHandleBuffer();
+
+ // Copy user handles.
+ if (num_handles > 0) {
+ // Ensure we can try to get the handles.
+ R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
+ handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
+ ResultInvalidPointer);
+
+ // Get the handles.
+ GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
+ sizeof(Handle) * num_handles);
+
+ // Convert the handles to objects.
+ R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
+ objs.data(), handles.data(), num_handles),
+ ResultInvalidHandle);
+ }
// Ensure handles are closed when we're done.
SCOPE_EXIT({
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 53df5bcd8..f02d03f30 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -47,21 +47,35 @@ Result ResetSignal(Core::System& system, Handle handle) {
R_THROW(ResultInvalidHandle);
}
-static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
- int32_t num_handles, int64_t timeout_ns) {
+/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
+Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
+ int32_t num_handles, int64_t timeout_ns) {
+ LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
+ num_handles, timeout_ns);
+
// Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
// Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
+ auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
+ auto handles = GetCurrentThread(kernel).GetHandleBuffer();
// Copy user handles.
if (num_handles > 0) {
+ // Ensure we can try to get the handles.
+ R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
+ user_handles, static_cast<u64>(sizeof(Handle) * num_handles)),
+ ResultInvalidPointer);
+
+ // Get the handles.
+ GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
+ sizeof(Handle) * num_handles);
+
// Convert the handles to objects.
- R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
- num_handles),
+ R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
+ objs.data(), handles.data(), num_handles),
ResultInvalidHandle);
}
@@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
R_RETURN(res);
}
-/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
- int32_t num_handles, int64_t timeout_ns) {
- LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
- num_handles, timeout_ns);
-
- // Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
- std::array<Handle, Svc::ArgumentHandleCountMax> handles;
- if (num_handles > 0) {
- GetCurrentMemory(system.Kernel())
- .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
- }
-
- R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
-}
-
/// Resumes a thread waiting on WaitSynchronization
Result CancelSynchronization(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);