Просмотр исходного кода

core: hle: kernel: k_handle_table: Refresh.

bunnei 3 лет назад
Родитель
Сommit
6636b81573
2 измененных файлов с 87 добавлено и 54 удалено
  1. 15 18
      src/core/hle/kernel/k_handle_table.cpp
  2. 72 36
      src/core/hle/kernel/k_handle_table.h

+ 15 - 18
src/core/hle/kernel/k_handle_table.cpp

@@ -5,14 +5,11 @@
 
 namespace Kernel {
 
-KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
-KHandleTable::~KHandleTable() = default;
-
 Result KHandleTable::Finalize() {
     // Get the table and clear our record of it.
     u16 saved_table_size = 0;
     {
-        KScopedDisableDispatch dd(kernel);
+        KScopedDisableDispatch dd{m_kernel};
         KScopedSpinLock lk(m_lock);
 
         std::swap(m_table_size, saved_table_size);
@@ -25,28 +22,28 @@ Result KHandleTable::Finalize() {
         }
     }
 
-    return ResultSuccess;
+    R_SUCCEED();
 }
 
 bool KHandleTable::Remove(Handle handle) {
     // Don't allow removal of a pseudo-handle.
-    if (Svc::IsPseudoHandle(handle)) {
+    if (Svc::IsPseudoHandle(handle)) [[unlikely]] {
         return false;
     }
 
     // Handles must not have reserved bits set.
     const auto handle_pack = HandlePack(handle);
-    if (handle_pack.reserved != 0) {
+    if (handle_pack.reserved != 0) [[unlikely]] {
         return false;
     }
 
     // Find the object and free the entry.
     KAutoObject* obj = nullptr;
     {
-        KScopedDisableDispatch dd(kernel);
+        KScopedDisableDispatch dd{m_kernel};
         KScopedSpinLock lk(m_lock);
 
-        if (this->IsValidHandle(handle)) {
+        if (this->IsValidHandle(handle)) [[likely]] {
             const auto index = handle_pack.index;
 
             obj = m_objects[index];
@@ -57,13 +54,13 @@ bool KHandleTable::Remove(Handle handle) {
     }
 
     // Close the object.
-    kernel.UnregisterInUseObject(obj);
+    m_kernel.UnregisterInUseObject(obj);
     obj->Close();
     return true;
 }
 
 Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
-    KScopedDisableDispatch dd(kernel);
+    KScopedDisableDispatch dd{m_kernel};
     KScopedSpinLock lk(m_lock);
 
     // Never exceed our capacity.
@@ -82,22 +79,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
         *out_handle = EncodeHandle(static_cast<u16>(index), linear_id);
     }
 
-    return ResultSuccess;
+    R_SUCCEED();
 }
 
 Result KHandleTable::Reserve(Handle* out_handle) {
-    KScopedDisableDispatch dd(kernel);
+    KScopedDisableDispatch dd{m_kernel};
     KScopedSpinLock lk(m_lock);
 
     // Never exceed our capacity.
     R_UNLESS(m_count < m_table_size, ResultOutOfHandles);
 
     *out_handle = EncodeHandle(static_cast<u16>(this->AllocateEntry()), this->AllocateLinearId());
-    return ResultSuccess;
+    R_SUCCEED();
 }
 
 void KHandleTable::Unreserve(Handle handle) {
-    KScopedDisableDispatch dd(kernel);
+    KScopedDisableDispatch dd{m_kernel};
     KScopedSpinLock lk(m_lock);
 
     // Unpack the handle.
@@ -108,7 +105,7 @@ void KHandleTable::Unreserve(Handle handle) {
     ASSERT(reserved == 0);
     ASSERT(linear_id != 0);
 
-    if (index < m_table_size) {
+    if (index < m_table_size) [[likely]] {
         // NOTE: This code does not check the linear id.
         ASSERT(m_objects[index] == nullptr);
         this->FreeEntry(index);
@@ -116,7 +113,7 @@ void KHandleTable::Unreserve(Handle handle) {
 }
 
 void KHandleTable::Register(Handle handle, KAutoObject* obj) {
-    KScopedDisableDispatch dd(kernel);
+    KScopedDisableDispatch dd{m_kernel};
     KScopedSpinLock lk(m_lock);
 
     // Unpack the handle.
@@ -127,7 +124,7 @@ void KHandleTable::Register(Handle handle, KAutoObject* obj) {
     ASSERT(reserved == 0);
     ASSERT(linear_id != 0);
 
-    if (index < m_table_size) {
+    if (index < m_table_size) [[likely]] {
         // Set the entry.
         ASSERT(m_objects[index] == nullptr);
 

+ 72 - 36
src/core/hle/kernel/k_handle_table.h

@@ -21,33 +21,38 @@ namespace Kernel {
 class KernelCore;
 
 class KHandleTable {
-public:
     YUZU_NON_COPYABLE(KHandleTable);
     YUZU_NON_MOVEABLE(KHandleTable);
 
+public:
     static constexpr size_t MaxTableSize = 1024;
 
-    explicit KHandleTable(KernelCore& kernel_);
-    ~KHandleTable();
+public:
+    explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {}
 
     Result Initialize(s32 size) {
+        // Check that the table size is valid.
         R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
 
+        // Lock.
+        KScopedDisableDispatch dd{m_kernel};
+        KScopedSpinLock lk(m_lock);
+
         // Initialize all fields.
         m_max_count = 0;
-        m_table_size = static_cast<u16>((size <= 0) ? MaxTableSize : size);
+        m_table_size = static_cast<s16>((size <= 0) ? MaxTableSize : size);
         m_next_linear_id = MinLinearId;
         m_count = 0;
         m_free_head_index = -1;
 
         // Free all entries.
-        for (s16 i = 0; i < static_cast<s16>(m_table_size); ++i) {
+        for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
             m_objects[i] = nullptr;
-            m_entry_infos[i].next_free_index = i - 1;
+            m_entry_infos[i].next_free_index = static_cast<s16>(i - 1);
             m_free_head_index = i;
         }
 
-        return ResultSuccess;
+        R_SUCCEED();
     }
 
     size_t GetTableSize() const {
@@ -66,13 +71,13 @@ public:
     template <typename T = KAutoObject>
     KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const {
         // Lock and look up in table.
-        KScopedDisableDispatch dd(kernel);
+        KScopedDisableDispatch dd{m_kernel};
         KScopedSpinLock lk(m_lock);
 
-        if constexpr (std::is_same_v<T, KAutoObject>) {
+        if constexpr (std::is_same<T, KAutoObject>::value) {
             return this->GetObjectImpl(handle);
         } else {
-            if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) {
+            if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] {
                 return obj->DynamicCast<T*>();
             } else {
                 return nullptr;
@@ -85,13 +90,13 @@ public:
         // Handle pseudo-handles.
         if constexpr (std::derived_from<KProcess, T>) {
             if (handle == Svc::PseudoHandle::CurrentProcess) {
-                auto* const cur_process = kernel.CurrentProcess();
+                auto* const cur_process = m_kernel.CurrentProcess();
                 ASSERT(cur_process != nullptr);
                 return cur_process;
             }
         } else if constexpr (std::derived_from<KThread, T>) {
             if (handle == Svc::PseudoHandle::CurrentThread) {
-                auto* const cur_thread = GetCurrentThreadPointer(kernel);
+                auto* const cur_thread = GetCurrentThreadPointer(m_kernel);
                 ASSERT(cur_thread != nullptr);
                 return cur_thread;
             }
@@ -100,6 +105,37 @@ public:
         return this->template GetObjectWithoutPseudoHandle<T>(handle);
     }
 
+    KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(Handle handle) const {
+        // Lock and look up in table.
+        KScopedDisableDispatch dd{m_kernel};
+        KScopedSpinLock lk(m_lock);
+
+        return this->GetObjectImpl(handle);
+    }
+
+    KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const {
+        // Handle pseudo-handles.
+        ASSERT(cur_thread != nullptr);
+        if (handle == Svc::PseudoHandle::CurrentProcess) {
+            auto* const cur_process =
+                static_cast<KAutoObject*>(static_cast<void*>(cur_thread->GetOwnerProcess()));
+            ASSERT(cur_process != nullptr);
+            return cur_process;
+        }
+        if (handle == Svc::PseudoHandle::CurrentThread) {
+            return static_cast<KAutoObject*>(cur_thread);
+        }
+
+        return GetObjectForIpcWithoutPseudoHandle(handle);
+    }
+
+    KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const {
+        KScopedDisableDispatch dd{m_kernel};
+        KScopedSpinLock lk(m_lock);
+
+        return this->GetObjectByIndexImpl(out_handle, index);
+    }
+
     Result Reserve(Handle* out_handle);
     void Unreserve(Handle handle);
 
@@ -112,7 +148,7 @@ public:
         size_t num_opened;
         {
             // Lock the table.
-            KScopedDisableDispatch dd(kernel);
+            KScopedDisableDispatch dd{m_kernel};
             KScopedSpinLock lk(m_lock);
             for (num_opened = 0; num_opened < num_handles; num_opened++) {
                 // Get the current handle.
@@ -120,13 +156,13 @@ public:
 
                 // Get the object for the current handle.
                 KAutoObject* cur_object = this->GetObjectImpl(cur_handle);
-                if (cur_object == nullptr) {
+                if (cur_object == nullptr) [[unlikely]] {
                     break;
                 }
 
                 // Cast the current object to the desired type.
                 T* cur_t = cur_object->DynamicCast<T*>();
-                if (cur_t == nullptr) {
+                if (cur_t == nullptr) [[unlikely]] {
                     break;
                 }
 
@@ -137,7 +173,7 @@ public:
         }
 
         // If we converted every object, succeed.
-        if (num_opened == num_handles) {
+        if (num_opened == num_handles) [[likely]] {
             return true;
         }
 
@@ -191,21 +227,21 @@ private:
         ASSERT(reserved == 0);
 
         // Validate our indexing information.
-        if (raw_value == 0) {
+        if (raw_value == 0) [[unlikely]] {
             return false;
         }
-        if (linear_id == 0) {
+        if (linear_id == 0) [[unlikely]] {
             return false;
         }
-        if (index >= m_table_size) {
+        if (index >= m_table_size) [[unlikely]] {
             return false;
         }
 
         // Check that there's an object, and our serial id is correct.
-        if (m_objects[index] == nullptr) {
+        if (m_objects[index] == nullptr) [[unlikely]] {
             return false;
         }
-        if (m_entry_infos[index].GetLinearId() != linear_id) {
+        if (m_entry_infos[index].GetLinearId() != linear_id) [[unlikely]] {
             return false;
         }
 
@@ -215,11 +251,11 @@ private:
     KAutoObject* GetObjectImpl(Handle handle) const {
         // Handles must not have reserved bits set.
         const auto handle_pack = HandlePack(handle);
-        if (handle_pack.reserved != 0) {
+        if (handle_pack.reserved != 0) [[unlikely]] {
             return nullptr;
         }
 
-        if (this->IsValidHandle(handle)) {
+        if (this->IsValidHandle(handle)) [[likely]] {
             return m_objects[handle_pack.index];
         } else {
             return nullptr;
@@ -227,9 +263,8 @@ private:
     }
 
     KAutoObject* GetObjectByIndexImpl(Handle* out_handle, size_t index) const {
-
         // Index must be in bounds.
-        if (index >= m_table_size) {
+        if (index >= m_table_size) [[unlikely]] {
             return nullptr;
         }
 
@@ -244,18 +279,15 @@ private:
 
 private:
     union HandlePack {
-        HandlePack() = default;
-        HandlePack(Handle handle) : raw{static_cast<u32>(handle)} {}
+        constexpr HandlePack() = default;
+        constexpr HandlePack(Handle handle) : raw{static_cast<u32>(handle)} {}
 
-        u32 raw;
+        u32 raw{};
         BitField<0, 15, u32> index;
         BitField<15, 15, u32> linear_id;
         BitField<30, 2, u32> reserved;
     };
 
-    static constexpr u16 MinLinearId = 1;
-    static constexpr u16 MaxLinearId = 0x7FFF;
-
     static constexpr Handle EncodeHandle(u16 index, u16 linear_id) {
         HandlePack handle{};
         handle.index.Assign(index);
@@ -264,6 +296,10 @@ private:
         return handle.raw;
     }
 
+private:
+    static constexpr u16 MinLinearId = 1;
+    static constexpr u16 MaxLinearId = 0x7FFF;
+
     union EntryInfo {
         u16 linear_id;
         s16 next_free_index;
@@ -271,21 +307,21 @@ private:
         constexpr u16 GetLinearId() const {
             return linear_id;
         }
-        constexpr s16 GetNextFreeIndex() const {
+        constexpr s32 GetNextFreeIndex() const {
             return next_free_index;
         }
     };
 
 private:
+    KernelCore& m_kernel;
     std::array<EntryInfo, MaxTableSize> m_entry_infos{};
     std::array<KAutoObject*, MaxTableSize> m_objects{};
-    s32 m_free_head_index{-1};
+    mutable KSpinLock m_lock;
+    s32 m_free_head_index{};
     u16 m_table_size{};
     u16 m_max_count{};
-    u16 m_next_linear_id{MinLinearId};
+    u16 m_next_linear_id{};
     u16 m_count{};
-    mutable KSpinLock m_lock;
-    KernelCore& kernel;
 };
 
 } // namespace Kernel