7 changed files with 265 additions and 3 deletions
-
2src/core/CMakeLists.txt
-
2src/core/hle/kernel/init/init_slab_setup.cpp
-
102src/core/hle/kernel/k_object_name.cpp
-
86src/core/hle/kernel/k_object_name.h
-
14src/core/hle/kernel/kernel.cpp
-
8src/core/hle/kernel/kernel.h
-
54src/core/hle/kernel/svc/svc_port.cpp
@ -0,0 +1,102 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "core/hle/kernel/k_object_name.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {} |
|||
KObjectNameGlobalData::~KObjectNameGlobalData() = default; |
|||
|
|||
void KObjectName::Initialize(KAutoObject* obj, const char* name) { |
|||
// Set member variables.
|
|||
m_object = obj; |
|||
std::strncpy(m_name.data(), name, sizeof(m_name) - 1); |
|||
m_name[sizeof(m_name) - 1] = '\x00'; |
|||
|
|||
// Open a reference to the object we hold.
|
|||
m_object->Open(); |
|||
} |
|||
|
|||
bool KObjectName::MatchesName(const char* name) const { |
|||
return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0; |
|||
} |
|||
|
|||
Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) { |
|||
// Create a new object name.
|
|||
KObjectName* new_name = KObjectName::Allocate(kernel); |
|||
R_UNLESS(new_name != nullptr, ResultOutOfResource); |
|||
|
|||
// Initialize the new name.
|
|||
new_name->Initialize(obj, name); |
|||
|
|||
// Check if there's an existing name.
|
|||
{ |
|||
// Get the global data.
|
|||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; |
|||
|
|||
// Ensure we have exclusive access to the global list.
|
|||
KScopedLightLock lk{gd.GetObjectListLock()}; |
|||
|
|||
// If the object doesn't exist, put it into the list.
|
|||
KScopedAutoObject existing_object = FindImpl(kernel, name); |
|||
if (existing_object.IsNull()) { |
|||
gd.GetObjectList().push_back(*new_name); |
|||
R_SUCCEED(); |
|||
} |
|||
} |
|||
|
|||
// The object already exists, which is an error condition. Perform cleanup.
|
|||
obj->Close(); |
|||
KObjectName::Free(kernel, new_name); |
|||
R_THROW(ResultInvalidState); |
|||
} |
|||
|
|||
Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) { |
|||
// Get the global data.
|
|||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; |
|||
|
|||
// Ensure we have exclusive access to the global list.
|
|||
KScopedLightLock lk{gd.GetObjectListLock()}; |
|||
|
|||
// Find a matching entry in the list, and delete it.
|
|||
for (auto& name : gd.GetObjectList()) { |
|||
if (name.MatchesName(compare_name) && obj == name.GetObject()) { |
|||
// We found a match, clean up its resources.
|
|||
obj->Close(); |
|||
gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name)); |
|||
KObjectName::Free(kernel, std::addressof(name)); |
|||
R_SUCCEED(); |
|||
} |
|||
} |
|||
|
|||
// We didn't find the object in the list.
|
|||
R_THROW(ResultNotFound); |
|||
} |
|||
|
|||
KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) { |
|||
// Get the global data.
|
|||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; |
|||
|
|||
// Ensure we have exclusive access to the global list.
|
|||
KScopedLightLock lk{gd.GetObjectListLock()}; |
|||
|
|||
return FindImpl(kernel, name); |
|||
} |
|||
|
|||
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) { |
|||
// Get the global data.
|
|||
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; |
|||
|
|||
// Try to find a matching object in the global list.
|
|||
for (const auto& name : gd.GetObjectList()) { |
|||
if (name.MatchesName(compare_name)) { |
|||
return name.GetObject(); |
|||
} |
|||
} |
|||
|
|||
// There's no matching entry in the list.
|
|||
return nullptr; |
|||
} |
|||
|
|||
} // namespace Kernel
|
|||
@ -0,0 +1,86 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include <array> |
|||
#include <memory> |
|||
#include <boost/intrusive/list.hpp> |
|||
|
|||
#include "core/hle/kernel/k_light_lock.h" |
|||
#include "core/hle/kernel/slab_helpers.h" |
|||
#include "core/hle/kernel/svc_results.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
class KObjectNameGlobalData; |
|||
|
|||
class KObjectName : public KSlabAllocated<KObjectName>, public boost::intrusive::list_base_hook<> { |
|||
public: |
|||
explicit KObjectName(KernelCore&) {} |
|||
virtual ~KObjectName() = default; |
|||
|
|||
static constexpr size_t NameLengthMax = 12; |
|||
using List = boost::intrusive::list<KObjectName>; |
|||
|
|||
static Result NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name); |
|||
static Result Delete(KernelCore& kernel, KAutoObject* obj, const char* name); |
|||
|
|||
static KScopedAutoObject<KAutoObject> Find(KernelCore& kernel, const char* name); |
|||
|
|||
template <typename Derived> |
|||
static Result Delete(KernelCore& kernel, const char* name) { |
|||
// Find the object. |
|||
KScopedAutoObject obj = Find(kernel, name); |
|||
R_UNLESS(obj.IsNotNull(), ResultNotFound); |
|||
|
|||
// Cast the object to the desired type. |
|||
Derived* derived = obj->DynamicCast<Derived*>(); |
|||
R_UNLESS(derived != nullptr, ResultNotFound); |
|||
|
|||
// Check that the object is closed. |
|||
R_UNLESS(derived->IsServerClosed(), ResultInvalidState); |
|||
|
|||
return Delete(kernel, obj.GetPointerUnsafe(), name); |
|||
} |
|||
|
|||
template <typename Derived> |
|||
requires(std::derived_from<Derived, KAutoObject>) |
|||
static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) { |
|||
return Find(kernel, name); |
|||
} |
|||
|
|||
private: |
|||
static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name); |
|||
|
|||
void Initialize(KAutoObject* obj, const char* name); |
|||
|
|||
bool MatchesName(const char* name) const; |
|||
KAutoObject* GetObject() const { |
|||
return m_object; |
|||
} |
|||
|
|||
private: |
|||
std::array<char, NameLengthMax> m_name{}; |
|||
KAutoObject* m_object{}; |
|||
}; |
|||
|
|||
class KObjectNameGlobalData { |
|||
public: |
|||
explicit KObjectNameGlobalData(KernelCore& kernel); |
|||
~KObjectNameGlobalData(); |
|||
|
|||
KLightLock& GetObjectListLock() { |
|||
return m_object_list_lock; |
|||
} |
|||
|
|||
KObjectName::List& GetObjectList() { |
|||
return m_object_list; |
|||
} |
|||
|
|||
private: |
|||
KLightLock m_object_list_lock; |
|||
KObjectName::List m_object_list; |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue