kernel: Synchronize
This commit is contained in:
parent
9252ad4e10
commit
b94e576653
|
@ -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{};
|
||||||
|
|
|
@ -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.
|
||||||
|
if (num_handles > 0) {
|
||||||
|
// Ensure we can try to get the handles.
|
||||||
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
|
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
|
||||||
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
|
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
|
||||||
ResultInvalidPointer);
|
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({
|
||||||
|
|
|
@ -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
|
||||||
|
Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
|
||||||
int32_t num_handles, int64_t timeout_ns) {
|
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);
|
||||||
|
|
Reference in New Issue