diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/k_handle_table.cpp | 33 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_handle_table.h | 108 | 
2 files changed, 87 insertions, 54 deletions
| diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index e830ca46e..1c7a766c8 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/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); diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 0864a737c..e98a01c86 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/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 | 
