kernel: Synchronize
This commit is contained in:
parent
9252ad4e10
commit
b94e576653
@ -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{};
|
||||
|
@ -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();
|
||||
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(
|
||||
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);
|
||||
// Get the 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),
|
||||
// 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({
|
||||
|
@ -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,
|
||||
/// 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);
|
||||
|
Loading…
Reference in New Issue
Block a user