Merge pull request #10969 from Morph1984/k-synchronize

kernel: Synchronize
This commit is contained in:
liamwhite 2023-07-02 17:38:14 -04:00 committed by GitHub
commit daaf03942f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 33 deletions

View file

@ -338,6 +338,15 @@ public:
return m_parent != nullptr; 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; u16 GetUserDisableCount() const;
void SetInterruptFlag(); void SetInterruptFlag();
void ClearInterruptFlag(); void ClearInterruptFlag();
@ -855,6 +864,7 @@ private:
u32* m_light_ipc_data{}; u32* m_light_ipc_data{};
KProcessAddress m_tls_address{}; KProcessAddress m_tls_address{};
KLightLock m_activity_pause_lock; KLightLock m_activity_pause_lock;
SyncObjectBuffer m_sync_object_buffer{};
s64 m_schedule_count{}; s64 m_schedule_count{};
s64 m_last_scheduled_tick{}; s64 m_last_scheduled_tick{};
std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{}; std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{};

View file

@ -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, Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) { 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& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
auto handles = GetCurrentThread(kernel).GetHandleBuffer();
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); // Copy user handles.
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( if (num_handles > 0) {
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), // Ensure we can try to get the handles.
ResultInvalidPointer); R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
ResultInvalidPointer);
std::array<Handle, Svc::ArgumentHandleCountMax> handles; // Get the handles.
GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles); GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
sizeof(Handle) * num_handles);
// Convert handle list to object table. // Convert the handles to objects.
std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(), objs.data(), handles.data(), num_handles),
num_handles), ResultInvalidHandle);
ResultInvalidHandle); }
// Ensure handles are closed when we're done. // Ensure handles are closed when we're done.
SCOPE_EXIT({ SCOPE_EXIT({

View file

@ -47,21 +47,35 @@ Result ResetSignal(Core::System& system, Handle handle) {
R_THROW(ResultInvalidHandle); R_THROW(ResultInvalidHandle);
} }
static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
int32_t num_handles, int64_t timeout_ns) { 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. // Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
// Get the synchronization context. // Get the synchronization context.
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); 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. // Copy user handles.
if (num_handles > 0) { 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. // Convert the handles to objects.
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
num_handles), objs.data(), handles.data(), num_handles),
ResultInvalidHandle); ResultInvalidHandle);
} }
@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
R_RETURN(res); 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 /// Resumes a thread waiting on WaitSynchronization
Result CancelSynchronization(Core::System& system, Handle handle) { Result CancelSynchronization(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);