summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Liam2023-02-16 23:16:08 -0500
committerGravatar Liam2023-02-17 09:16:05 -0500
commit1773a1039f7422df4faac08aa366b6a6bbd645e4 (patch)
tree9560360871f1fcd6c12df2e77452cf37658309d3
parentMerge pull request #9802 from Kelebek1/wait_data_cache (diff)
downloadyuzu-1773a1039f7422df4faac08aa366b6a6bbd645e4.tar.gz
yuzu-1773a1039f7422df4faac08aa366b6a6bbd645e4.tar.xz
yuzu-1773a1039f7422df4faac08aa366b6a6bbd645e4.zip
kernel: add KObjectName
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_object_name.cpp102
-rw-r--r--src/core/hle/kernel/k_object_name.h86
-rw-r--r--src/core/hle/kernel/kernel.cpp14
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/svc/svc_port.cpp54
7 files changed, 265 insertions, 3 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 16ced4595..ff5502d87 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -225,6 +225,8 @@ add_library(core STATIC
225 hle/kernel/k_memory_manager.h 225 hle/kernel/k_memory_manager.h
226 hle/kernel/k_memory_region.h 226 hle/kernel/k_memory_region.h
227 hle/kernel/k_memory_region_type.h 227 hle/kernel/k_memory_region_type.h
228 hle/kernel/k_object_name.cpp
229 hle/kernel/k_object_name.h
228 hle/kernel/k_page_bitmap.h 230 hle/kernel/k_page_bitmap.h
229 hle/kernel/k_page_buffer.cpp 231 hle/kernel/k_page_buffer.cpp
230 hle/kernel/k_page_buffer.h 232 hle/kernel/k_page_buffer.h
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index 571acf4b2..abdb5639f 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -16,6 +16,7 @@
16#include "core/hle/kernel/k_event_info.h" 16#include "core/hle/kernel/k_event_info.h"
17#include "core/hle/kernel/k_memory_layout.h" 17#include "core/hle/kernel/k_memory_layout.h"
18#include "core/hle/kernel/k_memory_manager.h" 18#include "core/hle/kernel/k_memory_manager.h"
19#include "core/hle/kernel/k_object_name.h"
19#include "core/hle/kernel/k_page_buffer.h" 20#include "core/hle/kernel/k_page_buffer.h"
20#include "core/hle/kernel/k_port.h" 21#include "core/hle/kernel/k_port.h"
21#include "core/hle/kernel/k_process.h" 22#include "core/hle/kernel/k_process.h"
@@ -49,6 +50,7 @@ namespace Kernel::Init {
49 HANDLER(KThreadLocalPage, \ 50 HANDLER(KThreadLocalPage, \
50 (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \ 51 (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \
51 ##__VA_ARGS__) \ 52 ##__VA_ARGS__) \
53 HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ##__VA_ARGS__) \
52 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) \ 54 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) \
53 HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ##__VA_ARGS__) \ 55 HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
54 HANDLER(KDebug, (SLAB_COUNT(KDebug)), ##__VA_ARGS__) \ 56 HANDLER(KDebug, (SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
diff --git a/src/core/hle/kernel/k_object_name.cpp b/src/core/hle/kernel/k_object_name.cpp
new file mode 100644
index 000000000..df3a1c4c5
--- /dev/null
+++ b/src/core/hle/kernel/k_object_name.cpp
@@ -0,0 +1,102 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_object_name.h"
5
6namespace Kernel {
7
8KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {}
9KObjectNameGlobalData::~KObjectNameGlobalData() = default;
10
11void KObjectName::Initialize(KAutoObject* obj, const char* name) {
12 // Set member variables.
13 m_object = obj;
14 std::strncpy(m_name.data(), name, sizeof(m_name) - 1);
15 m_name[sizeof(m_name) - 1] = '\x00';
16
17 // Open a reference to the object we hold.
18 m_object->Open();
19}
20
21bool KObjectName::MatchesName(const char* name) const {
22 return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0;
23}
24
25Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) {
26 // Create a new object name.
27 KObjectName* new_name = KObjectName::Allocate(kernel);
28 R_UNLESS(new_name != nullptr, ResultOutOfResource);
29
30 // Initialize the new name.
31 new_name->Initialize(obj, name);
32
33 // Check if there's an existing name.
34 {
35 // Get the global data.
36 KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
37
38 // Ensure we have exclusive access to the global list.
39 KScopedLightLock lk{gd.GetObjectListLock()};
40
41 // If the object doesn't exist, put it into the list.
42 KScopedAutoObject existing_object = FindImpl(kernel, name);
43 if (existing_object.IsNull()) {
44 gd.GetObjectList().push_back(*new_name);
45 R_SUCCEED();
46 }
47 }
48
49 // The object already exists, which is an error condition. Perform cleanup.
50 obj->Close();
51 KObjectName::Free(kernel, new_name);
52 R_THROW(ResultInvalidState);
53}
54
55Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) {
56 // Get the global data.
57 KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
58
59 // Ensure we have exclusive access to the global list.
60 KScopedLightLock lk{gd.GetObjectListLock()};
61
62 // Find a matching entry in the list, and delete it.
63 for (auto& name : gd.GetObjectList()) {
64 if (name.MatchesName(compare_name) && obj == name.GetObject()) {
65 // We found a match, clean up its resources.
66 obj->Close();
67 gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name));
68 KObjectName::Free(kernel, std::addressof(name));
69 R_SUCCEED();
70 }
71 }
72
73 // We didn't find the object in the list.
74 R_THROW(ResultNotFound);
75}
76
77KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) {
78 // Get the global data.
79 KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
80
81 // Ensure we have exclusive access to the global list.
82 KScopedLightLock lk{gd.GetObjectListLock()};
83
84 return FindImpl(kernel, name);
85}
86
87KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) {
88 // Get the global data.
89 KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
90
91 // Try to find a matching object in the global list.
92 for (const auto& name : gd.GetObjectList()) {
93 if (name.MatchesName(compare_name)) {
94 return name.GetObject();
95 }
96 }
97
98 // There's no matching entry in the list.
99 return nullptr;
100}
101
102} // namespace Kernel
diff --git a/src/core/hle/kernel/k_object_name.h b/src/core/hle/kernel/k_object_name.h
new file mode 100644
index 000000000..b7f943134
--- /dev/null
+++ b/src/core/hle/kernel/k_object_name.h
@@ -0,0 +1,86 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <memory>
8#include <boost/intrusive/list.hpp>
9
10#include "core/hle/kernel/k_light_lock.h"
11#include "core/hle/kernel/slab_helpers.h"
12#include "core/hle/kernel/svc_results.h"
13
14namespace Kernel {
15
16class KObjectNameGlobalData;
17
18class KObjectName : public KSlabAllocated<KObjectName>, public boost::intrusive::list_base_hook<> {
19public:
20 explicit KObjectName(KernelCore&) {}
21 virtual ~KObjectName() = default;
22
23 static constexpr size_t NameLengthMax = 12;
24 using List = boost::intrusive::list<KObjectName>;
25
26 static Result NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name);
27 static Result Delete(KernelCore& kernel, KAutoObject* obj, const char* name);
28
29 static KScopedAutoObject<KAutoObject> Find(KernelCore& kernel, const char* name);
30
31 template <typename Derived>
32 static Result Delete(KernelCore& kernel, const char* name) {
33 // Find the object.
34 KScopedAutoObject obj = Find(kernel, name);
35 R_UNLESS(obj.IsNotNull(), ResultNotFound);
36
37 // Cast the object to the desired type.
38 Derived* derived = obj->DynamicCast<Derived*>();
39 R_UNLESS(derived != nullptr, ResultNotFound);
40
41 // Check that the object is closed.
42 R_UNLESS(derived->IsServerClosed(), ResultInvalidState);
43
44 return Delete(kernel, obj.GetPointerUnsafe(), name);
45 }
46
47 template <typename Derived>
48 requires(std::derived_from<Derived, KAutoObject>)
49 static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) {
50 return Find(kernel, name);
51 }
52
53private:
54 static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name);
55
56 void Initialize(KAutoObject* obj, const char* name);
57
58 bool MatchesName(const char* name) const;
59 KAutoObject* GetObject() const {
60 return m_object;
61 }
62
63private:
64 std::array<char, NameLengthMax> m_name{};
65 KAutoObject* m_object{};
66};
67
68class KObjectNameGlobalData {
69public:
70 explicit KObjectNameGlobalData(KernelCore& kernel);
71 ~KObjectNameGlobalData();
72
73 KLightLock& GetObjectListLock() {
74 return m_object_list_lock;
75 }
76
77 KObjectName::List& GetObjectList() {
78 return m_object_list;
79 }
80
81private:
82 KLightLock m_object_list_lock;
83 KObjectName::List m_object_list;
84};
85
86} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b1922659d..3a68a5633 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -29,6 +29,7 @@
29#include "core/hle/kernel/k_hardware_timer.h" 29#include "core/hle/kernel/k_hardware_timer.h"
30#include "core/hle/kernel/k_memory_layout.h" 30#include "core/hle/kernel/k_memory_layout.h"
31#include "core/hle/kernel/k_memory_manager.h" 31#include "core/hle/kernel/k_memory_manager.h"
32#include "core/hle/kernel/k_object_name.h"
32#include "core/hle/kernel/k_page_buffer.h" 33#include "core/hle/kernel/k_page_buffer.h"
33#include "core/hle/kernel/k_process.h" 34#include "core/hle/kernel/k_process.h"
34#include "core/hle/kernel/k_resource_limit.h" 35#include "core/hle/kernel/k_resource_limit.h"
@@ -84,6 +85,7 @@ struct KernelCore::Impl {
84 InitializeShutdownThreads(); 85 InitializeShutdownThreads();
85 InitializePhysicalCores(); 86 InitializePhysicalCores();
86 InitializePreemption(kernel); 87 InitializePreemption(kernel);
88 InitializeGlobalData(kernel);
87 89
88 // Initialize the Dynamic Slab Heaps. 90 // Initialize the Dynamic Slab Heaps.
89 { 91 {
@@ -194,6 +196,8 @@ struct KernelCore::Impl {
194 } 196 }
195 } 197 }
196 198
199 object_name_global_data.reset();
200
197 // Ensure that the object list container is finalized and properly shutdown. 201 // Ensure that the object list container is finalized and properly shutdown.
198 global_object_list_container->Finalize(); 202 global_object_list_container->Finalize();
199 global_object_list_container.reset(); 203 global_object_list_container.reset();
@@ -363,6 +367,10 @@ struct KernelCore::Impl {
363 } 367 }
364 } 368 }
365 369
370 void InitializeGlobalData(KernelCore& kernel) {
371 object_name_global_data = std::make_unique<KObjectNameGlobalData>(kernel);
372 }
373
366 void MakeApplicationProcess(KProcess* process) { 374 void MakeApplicationProcess(KProcess* process) {
367 application_process = process; 375 application_process = process;
368 } 376 }
@@ -838,6 +846,8 @@ struct KernelCore::Impl {
838 846
839 std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container; 847 std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
840 848
849 std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
850
841 /// Map of named ports managed by the kernel, which can be retrieved using 851 /// Map of named ports managed by the kernel, which can be retrieved using
842 /// the ConnectToPort SVC. 852 /// the ConnectToPort SVC.
843 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; 853 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
@@ -1138,6 +1148,10 @@ void KernelCore::SetCurrentEmuThread(KThread* thread) {
1138 impl->SetCurrentEmuThread(thread); 1148 impl->SetCurrentEmuThread(thread);
1139} 1149}
1140 1150
1151KObjectNameGlobalData& KernelCore::ObjectNameGlobalData() {
1152 return *impl->object_name_global_data;
1153}
1154
1141KMemoryManager& KernelCore::MemoryManager() { 1155KMemoryManager& KernelCore::MemoryManager() {
1142 return *impl->memory_manager; 1156 return *impl->memory_manager;
1143} 1157}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index a236e6b42..6e0668f7f 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -44,6 +44,8 @@ class KHardwareTimer;
44class KLinkedListNode; 44class KLinkedListNode;
45class KMemoryLayout; 45class KMemoryLayout;
46class KMemoryManager; 46class KMemoryManager;
47class KObjectName;
48class KObjectNameGlobalData;
47class KPageBuffer; 49class KPageBuffer;
48class KPageBufferSlabHeap; 50class KPageBufferSlabHeap;
49class KPort; 51class KPort;
@@ -240,6 +242,9 @@ public:
240 /// Register the current thread as a non CPU core thread. 242 /// Register the current thread as a non CPU core thread.
241 void RegisterHostThread(KThread* existing_thread = nullptr); 243 void RegisterHostThread(KThread* existing_thread = nullptr);
242 244
245 /// Gets global data for KObjectName.
246 KObjectNameGlobalData& ObjectNameGlobalData();
247
243 /// Gets the virtual memory manager for the kernel. 248 /// Gets the virtual memory manager for the kernel.
244 KMemoryManager& MemoryManager(); 249 KMemoryManager& MemoryManager();
245 250
@@ -372,6 +377,8 @@ public:
372 return slab_heap_container->page_buffer; 377 return slab_heap_container->page_buffer;
373 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { 378 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
374 return slab_heap_container->thread_local_page; 379 return slab_heap_container->thread_local_page;
380 } else if constexpr (std::is_same_v<T, KObjectName>) {
381 return slab_heap_container->object_name;
375 } else if constexpr (std::is_same_v<T, KSessionRequest>) { 382 } else if constexpr (std::is_same_v<T, KSessionRequest>) {
376 return slab_heap_container->session_request; 383 return slab_heap_container->session_request;
377 } else if constexpr (std::is_same_v<T, KSecureSystemResource>) { 384 } else if constexpr (std::is_same_v<T, KSecureSystemResource>) {
@@ -443,6 +450,7 @@ private:
443 KSlabHeap<KDeviceAddressSpace> device_address_space; 450 KSlabHeap<KDeviceAddressSpace> device_address_space;
444 KSlabHeap<KPageBuffer> page_buffer; 451 KSlabHeap<KPageBuffer> page_buffer;
445 KSlabHeap<KThreadLocalPage> thread_local_page; 452 KSlabHeap<KThreadLocalPage> thread_local_page;
453 KSlabHeap<KObjectName> object_name;
446 KSlabHeap<KSessionRequest> session_request; 454 KSlabHeap<KSessionRequest> session_request;
447 KSlabHeap<KSecureSystemResource> secure_system_resource; 455 KSlabHeap<KSecureSystemResource> secure_system_resource;
448 KSlabHeap<KEventInfo> event_info; 456 KSlabHeap<KEventInfo> event_info;
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index 2b7cebde5..2f9bfcb52 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -5,6 +5,7 @@
5#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/kernel/k_client_port.h" 6#include "core/hle/kernel/k_client_port.h"
7#include "core/hle/kernel/k_client_session.h" 7#include "core/hle/kernel/k_client_session.h"
8#include "core/hle/kernel/k_object_name.h"
8#include "core/hle/kernel/k_port.h" 9#include "core/hle/kernel/k_port.h"
9#include "core/hle/kernel/k_process.h" 10#include "core/hle/kernel/k_process.h"
10#include "core/hle/kernel/svc.h" 11#include "core/hle/kernel/svc.h"
@@ -74,10 +75,57 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
74 R_THROW(ResultNotImplemented); 75 R_THROW(ResultNotImplemented);
75} 76}
76 77
77Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name, 78Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
78 int32_t max_sessions) { 79 int32_t max_sessions) {
79 UNIMPLEMENTED(); 80 // Copy the provided name from user memory to kernel memory.
80 R_THROW(ResultNotImplemented); 81 std::array<char, KObjectName::NameLengthMax> name{};
82 system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
83
84 // Validate that sessions and name are valid.
85 R_UNLESS(max_sessions >= 0, ResultOutOfRange);
86 R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
87
88 if (max_sessions > 0) {
89 // Get the current handle table.
90 auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
91
92 // Create a new port.
93 KPort* port = KPort::Create(system.Kernel());
94 R_UNLESS(port != nullptr, ResultOutOfResource);
95
96 // Initialize the new port.
97 port->Initialize(max_sessions, false, "");
98
99 // Register the port.
100 KPort::Register(system.Kernel(), port);
101
102 // Ensure that our only reference to the port is in the handle table when we're done.
103 SCOPE_EXIT({
104 port->GetClientPort().Close();
105 port->GetServerPort().Close();
106 });
107
108 // Register the handle in the table.
109 R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
110 ON_RESULT_FAILURE {
111 handle_table.Remove(*out_server_handle);
112 };
113
114 // Create a new object name.
115 R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
116 name.data()));
117 } else /* if (max_sessions == 0) */ {
118 // Ensure that this else case is correct.
119 ASSERT(max_sessions == 0);
120
121 // If we're closing, there's no server handle.
122 *out_server_handle = InvalidHandle;
123
124 // Delete the object.
125 R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
126 }
127
128 R_SUCCEED();
81} 129}
82 130
83Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) { 131Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {