diff options
| author | 2021-02-04 20:06:54 -0500 | |
|---|---|---|
| committer | 2021-02-12 18:57:34 -0500 | |
| commit | 5fa6b15215d2c15a1601c88ac1125a28c55797fc (patch) | |
| tree | 4a25c58180aecd1eb9bcc3560a1a3dfa18c67761 /src/core/hle/kernel/svc.cpp | |
| parent | kernel: Unify result codes (#5890) (diff) | |
| download | yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.tar.gz yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.tar.xz yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.zip | |
kernel: KScopedReservation implementation
This implements KScopedReservation, allowing resource limit reservations to be more HW accurate, and release upon failure without requiring too many conditionals.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4ef3c7ac5..1d377ffe6 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "core/hle/kernel/k_readable_event.h" | 30 | #include "core/hle/kernel/k_readable_event.h" |
| 31 | #include "core/hle/kernel/k_resource_limit.h" | 31 | #include "core/hle/kernel/k_resource_limit.h" |
| 32 | #include "core/hle/kernel/k_scheduler.h" | 32 | #include "core/hle/kernel/k_scheduler.h" |
| 33 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 33 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 34 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 34 | #include "core/hle/kernel/k_synchronization_object.h" | 35 | #include "core/hle/kernel/k_synchronization_object.h" |
| 35 | #include "core/hle/kernel/k_thread.h" | 36 | #include "core/hle/kernel/k_thread.h" |
| @@ -1516,8 +1517,13 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1516 | return ResultInvalidPriority; | 1517 | return ResultInvalidPriority; |
| 1517 | } | 1518 | } |
| 1518 | 1519 | ||
| 1519 | ASSERT(process.GetResourceLimit()->Reserve( | 1520 | KScopedResourceReservation thread_reservation( |
| 1520 | LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); | 1521 | kernel.CurrentProcess(), LimitableResource::Threads, 1, |
| 1522 | system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | ||
| 1523 | if (!thread_reservation.Succeeded()) { | ||
| 1524 | LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); | ||
| 1525 | return ERR_RESOURCE_LIMIT_EXCEEDED; | ||
| 1526 | } | ||
| 1521 | 1527 | ||
| 1522 | std::shared_ptr<KThread> thread; | 1528 | std::shared_ptr<KThread> thread; |
| 1523 | { | 1529 | { |
| @@ -1537,6 +1543,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1537 | // Set the thread name for debugging purposes. | 1543 | // Set the thread name for debugging purposes. |
| 1538 | thread->SetName( | 1544 | thread->SetName( |
| 1539 | fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); | 1545 | fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); |
| 1546 | thread_reservation.Commit(); | ||
| 1540 | 1547 | ||
| 1541 | return RESULT_SUCCESS; | 1548 | return RESULT_SUCCESS; |
| 1542 | } | 1549 | } |
| @@ -1884,6 +1891,13 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1884 | } | 1891 | } |
| 1885 | 1892 | ||
| 1886 | auto& kernel = system.Kernel(); | 1893 | auto& kernel = system.Kernel(); |
| 1894 | // Reserve a new transfer memory from the process resource limit. | ||
| 1895 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | ||
| 1896 | LimitableResource::TransferMemory); | ||
| 1897 | if (!trmem_reservation.Succeeded()) { | ||
| 1898 | LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); | ||
| 1899 | return ERR_RESOURCE_LIMIT_EXCEEDED; | ||
| 1900 | } | ||
| 1887 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); | 1901 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); |
| 1888 | 1902 | ||
| 1889 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { | 1903 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { |
| @@ -1895,6 +1909,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1895 | if (result.Failed()) { | 1909 | if (result.Failed()) { |
| 1896 | return result.Code(); | 1910 | return result.Code(); |
| 1897 | } | 1911 | } |
| 1912 | trmem_reservation.Commit(); | ||
| 1898 | 1913 | ||
| 1899 | *handle = *result; | 1914 | *handle = *result; |
| 1900 | return RESULT_SUCCESS; | 1915 | return RESULT_SUCCESS; |
| @@ -2002,8 +2017,17 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle | |||
| 2002 | static ResultCode SignalEvent(Core::System& system, Handle event_handle) { | 2017 | static ResultCode SignalEvent(Core::System& system, Handle event_handle) { |
| 2003 | LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); | 2018 | LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); |
| 2004 | 2019 | ||
| 2020 | auto& kernel = system.Kernel(); | ||
| 2005 | // Get the current handle table. | 2021 | // Get the current handle table. |
| 2006 | const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 2022 | const HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 2023 | |||
| 2024 | // Reserve a new event from the process resource limit. | ||
| 2025 | KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | ||
| 2026 | LimitableResource::Events); | ||
| 2027 | if (!event_reservation.Succeeded()) { | ||
| 2028 | LOG_ERROR(Kernel, "Could not reserve a new event"); | ||
| 2029 | return ERR_RESOURCE_LIMIT_EXCEEDED; | ||
| 2030 | } | ||
| 2007 | 2031 | ||
| 2008 | // Get the writable event. | 2032 | // Get the writable event. |
| 2009 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); | 2033 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); |
| @@ -2012,6 +2036,9 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { | |||
| 2012 | return ResultInvalidHandle; | 2036 | return ResultInvalidHandle; |
| 2013 | } | 2037 | } |
| 2014 | 2038 | ||
| 2039 | // Commit the successfuly reservation. | ||
| 2040 | event_reservation.Commit(); | ||
| 2041 | |||
| 2015 | return writable_event->Signal(); | 2042 | return writable_event->Signal(); |
| 2016 | } | 2043 | } |
| 2017 | 2044 | ||