diff options
| author | 2021-04-17 23:38:20 -0700 | |
|---|---|---|
| committer | 2021-05-05 16:40:51 -0700 | |
| commit | 674122038ad01aae7eb4b6eff604f94fb8864bd4 (patch) | |
| tree | 78553461d9351d222e82cbdc66f9672130979960 /src/core/hle/kernel/svc.cpp | |
| parent | hle: kernel: svc: Use new handle table API for Process. (diff) | |
| download | yuzu-674122038ad01aae7eb4b6eff604f94fb8864bd4.tar.gz yuzu-674122038ad01aae7eb4b6eff604f94fb8864bd4.tar.xz yuzu-674122038ad01aae7eb4b6eff604f94fb8864bd4.zip | |
hle: kernel: svc: Migrate WaitSynchronization.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 70 |
1 files changed, 23 insertions, 47 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 790839a4b..9e8184758 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -430,65 +430,41 @@ static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, | |||
| 430 | 430 | ||
| 431 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 431 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 432 | static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, | 432 | static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, |
| 433 | u64 handle_count, s64 nano_seconds) { | 433 | u64 num_handles, s64 nano_seconds) { |
| 434 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", | 434 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", |
| 435 | handles_address, handle_count, nano_seconds); | 435 | handles_address, num_handles, nano_seconds); |
| 436 | 436 | ||
| 437 | auto& memory = system.Memory(); | 437 | // Ensure number of handles is valid. |
| 438 | if (!memory.IsValidVirtualAddress(handles_address)) { | 438 | R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); |
| 439 | LOG_ERROR(Kernel_SVC, | ||
| 440 | "Handle address is not a valid virtual address, handle_address=0x{:016X}", | ||
| 441 | handles_address); | ||
| 442 | return ResultInvalidPointer; | ||
| 443 | } | ||
| 444 | |||
| 445 | static constexpr u64 MaxHandles = 0x40; | ||
| 446 | |||
| 447 | if (handle_count > MaxHandles) { | ||
| 448 | LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}", | ||
| 449 | MaxHandles, handle_count); | ||
| 450 | return ResultOutOfRange; | ||
| 451 | } | ||
| 452 | 439 | ||
| 453 | auto& kernel = system.Kernel(); | 440 | auto& kernel = system.Kernel(); |
| 454 | std::vector<KSynchronizationObject*> objects(handle_count); | 441 | std::vector<KSynchronizationObject*> objs(num_handles); |
| 455 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 442 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 443 | Handle* handles = system.Memory().GetPointer<Handle>(handles_address); | ||
| 456 | 444 | ||
| 457 | for (u64 i = 0; i < handle_count; ++i) { | 445 | // Copy user handles. |
| 458 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 446 | if (num_handles > 0) { |
| 447 | // Convert the handles to objects. | ||
| 448 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | ||
| 449 | num_handles), | ||
| 450 | ResultInvalidHandle); | ||
| 451 | } | ||
| 459 | 452 | ||
| 460 | bool succeeded{}; | 453 | // Ensure handles are closed when we're done. |
| 461 | { | 454 | SCOPE_EXIT({ |
| 462 | auto object = handle_table.Get<KSynchronizationObject>(handle); | 455 | for (u64 i = 0; i < num_handles; ++i) { |
| 463 | if (object) { | 456 | objs[i]->Close(); |
| 464 | objects[i] = object; | ||
| 465 | succeeded = true; | ||
| 466 | } | ||
| 467 | } | 457 | } |
| 458 | }); | ||
| 468 | 459 | ||
| 469 | // TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES | 460 | return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()), |
| 470 | if (!succeeded) { | 461 | nano_seconds); |
| 471 | { | ||
| 472 | auto object = handle_table.GetObject<KSynchronizationObject>(handle); | ||
| 473 | |||
| 474 | if (object.IsNull()) { | ||
| 475 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | ||
| 476 | return ResultInvalidHandle; | ||
| 477 | } | ||
| 478 | |||
| 479 | objects[i] = object.GetPointerUnsafe(); | ||
| 480 | succeeded = true; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | } | ||
| 484 | return KSynchronizationObject::Wait(kernel, index, objects.data(), | ||
| 485 | static_cast<s32>(objects.size()), nano_seconds); | ||
| 486 | } | 462 | } |
| 487 | 463 | ||
| 488 | static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, | 464 | static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, |
| 489 | s32 handle_count, u32 timeout_high, s32* index) { | 465 | s32 num_handles, u32 timeout_high, s32* index) { |
| 490 | const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; | 466 | const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; |
| 491 | return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds); | 467 | return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds); |
| 492 | } | 468 | } |
| 493 | 469 | ||
| 494 | /// Resumes a thread waiting on WaitSynchronization | 470 | /// Resumes a thread waiting on WaitSynchronization |