commit
41183b622f
@ -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
|
Loading…
Reference in New Issue