k_object_name.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/hle/kernel/k_object_name.h"
  4. namespace Kernel {
  5. KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {}
  6. KObjectNameGlobalData::~KObjectNameGlobalData() = default;
  7. void KObjectName::Initialize(KAutoObject* obj, const char* name) {
  8. // Set member variables.
  9. m_object = obj;
  10. std::strncpy(m_name.data(), name, sizeof(m_name) - 1);
  11. m_name[sizeof(m_name) - 1] = '\x00';
  12. // Open a reference to the object we hold.
  13. m_object->Open();
  14. }
  15. bool KObjectName::MatchesName(const char* name) const {
  16. return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0;
  17. }
  18. Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) {
  19. // Create a new object name.
  20. KObjectName* new_name = KObjectName::Allocate(kernel);
  21. R_UNLESS(new_name != nullptr, ResultOutOfResource);
  22. // Initialize the new name.
  23. new_name->Initialize(obj, name);
  24. // Check if there's an existing name.
  25. {
  26. // Get the global data.
  27. KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
  28. // Ensure we have exclusive access to the global list.
  29. KScopedLightLock lk{gd.GetObjectListLock()};
  30. // If the object doesn't exist, put it into the list.
  31. KScopedAutoObject existing_object = FindImpl(kernel, name);
  32. if (existing_object.IsNull()) {
  33. gd.GetObjectList().push_back(*new_name);
  34. R_SUCCEED();
  35. }
  36. }
  37. // The object already exists, which is an error condition. Perform cleanup.
  38. obj->Close();
  39. KObjectName::Free(kernel, new_name);
  40. R_THROW(ResultInvalidState);
  41. }
  42. Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) {
  43. // Get the global data.
  44. KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
  45. // Ensure we have exclusive access to the global list.
  46. KScopedLightLock lk{gd.GetObjectListLock()};
  47. // Find a matching entry in the list, and delete it.
  48. for (auto& name : gd.GetObjectList()) {
  49. if (name.MatchesName(compare_name) && obj == name.GetObject()) {
  50. // We found a match, clean up its resources.
  51. obj->Close();
  52. gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name));
  53. KObjectName::Free(kernel, std::addressof(name));
  54. R_SUCCEED();
  55. }
  56. }
  57. // We didn't find the object in the list.
  58. R_THROW(ResultNotFound);
  59. }
  60. KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) {
  61. // Get the global data.
  62. KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
  63. // Ensure we have exclusive access to the global list.
  64. KScopedLightLock lk{gd.GetObjectListLock()};
  65. return FindImpl(kernel, name);
  66. }
  67. KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) {
  68. // Get the global data.
  69. KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
  70. // Try to find a matching object in the global list.
  71. for (const auto& name : gd.GetObjectList()) {
  72. if (name.MatchesName(compare_name)) {
  73. return name.GetObject();
  74. }
  75. }
  76. // There's no matching entry in the list.
  77. return nullptr;
  78. }
  79. } // namespace Kernel