summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2021-03-31 14:43:39 -0700
committerGravatar bunnei2021-05-05 16:40:49 -0700
commitb8751630e20914482b6ba0b6347c5f8f668e9748 (patch)
treec24b9bb60f7df6e5950c694aba15815bc8ec04df /src
parentcommon: intrusive_red_black_tree: Disable static_assert that will not evaluat... (diff)
downloadyuzu-b8751630e20914482b6ba0b6347c5f8f668e9748.tar.gz
yuzu-b8751630e20914482b6ba0b6347c5f8f668e9748.tar.xz
yuzu-b8751630e20914482b6ba0b6347c5f8f668e9748.zip
hle: kernel: Add initial impl. of KAutoObject.
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/k_auto_object.cpp14
-rw-r--r--src/core/hle/kernel/k_auto_object.h290
3 files changed, 306 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c28abc24c..aa83b8733 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -161,6 +161,8 @@ add_library(core STATIC
161 hle/kernel/k_address_arbiter.h 161 hle/kernel/k_address_arbiter.h
162 hle/kernel/k_address_space_info.cpp 162 hle/kernel/k_address_space_info.cpp
163 hle/kernel/k_address_space_info.h 163 hle/kernel/k_address_space_info.h
164 hle/kernel/k_auto_object.cpp
165 hle/kernel/k_auto_object.h
164 hle/kernel/k_affinity_mask.h 166 hle/kernel/k_affinity_mask.h
165 hle/kernel/k_condition_variable.cpp 167 hle/kernel/k_condition_variable.cpp
166 hle/kernel/k_condition_variable.h 168 hle/kernel/k_condition_variable.h
diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp
new file mode 100644
index 000000000..dbe237f09
--- /dev/null
+++ b/src/core/hle/kernel/k_auto_object.cpp
@@ -0,0 +1,14 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_auto_object.h"
6
7namespace Kernel {
8
9KAutoObject* KAutoObject::Create(KAutoObject* obj) {
10 obj->m_ref_count = 1;
11 return obj;
12}
13
14} // namespace Kernel
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
new file mode 100644
index 000000000..567dad204
--- /dev/null
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -0,0 +1,290 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <atomic>
8
9#include "common/assert.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/intrusive_red_black_tree.h"
13#include "core/hle/kernel/k_class_token.h"
14
15namespace Kernel {
16
17class Process;
18
19#define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \
20 NON_COPYABLE(CLASS); \
21 NON_MOVEABLE(CLASS); \
22 \
23private: \
24 friend class ::Kernel::KClassTokenGenerator; \
25 static constexpr inline auto ObjectType = ::Kernel::KClassTokenGenerator::ObjectType::CLASS; \
26 static constexpr inline const char* const TypeName = #CLASS; \
27 static constexpr inline ClassTokenType ClassToken() { \
28 return ::Kernel::ClassToken<CLASS>; \
29 } \
30 \
31public: \
32 using BaseClass = BASE_CLASS; \
33 static constexpr TypeObj GetStaticTypeObj() { \
34 constexpr ClassTokenType Token = ClassToken(); \
35 return TypeObj(TypeName, Token); \
36 } \
37 static constexpr const char* GetStaticTypeName() { \
38 return TypeName; \
39 } \
40 virtual TypeObj GetTypeObj() const { \
41 return GetStaticTypeObj(); \
42 } \
43 virtual const char* GetTypeName() { \
44 return GetStaticTypeName(); \
45 } \
46 \
47private:
48
49class KAutoObject {
50protected:
51 class TypeObj {
52 private:
53 const char* m_name;
54 ClassTokenType m_class_token;
55
56 public:
57 constexpr explicit TypeObj(const char* n, ClassTokenType tok)
58 : m_name(n), m_class_token(tok) { // ...
59 }
60
61 constexpr const char* GetName() const {
62 return m_name;
63 }
64 constexpr ClassTokenType GetClassToken() const {
65 return m_class_token;
66 }
67
68 constexpr bool operator==(const TypeObj& rhs) {
69 return this->GetClassToken() == rhs.GetClassToken();
70 }
71
72 constexpr bool operator!=(const TypeObj& rhs) {
73 return this->GetClassToken() != rhs.GetClassToken();
74 }
75
76 constexpr bool IsDerivedFrom(const TypeObj& rhs) {
77 return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken();
78 }
79 };
80
81private:
82 KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject);
83
84private:
85 std::atomic<u32> m_ref_count;
86
87public:
88 static KAutoObject* Create(KAutoObject* ptr);
89
90public:
91 constexpr explicit KAutoObject() : m_ref_count(0) {}
92 virtual ~KAutoObject() {}
93
94 // Destroy is responsible for destroying the auto object's resources when ref_count hits zero.
95 virtual void Destroy() {
96 UNIMPLEMENTED();
97 }
98
99 // Finalize is responsible for cleaning up resource, but does not destroy the object.
100 virtual void Finalize() {
101 UNIMPLEMENTED();
102 }
103
104 virtual Process* GetOwner() const {
105 return nullptr;
106 }
107
108 u32 GetReferenceCount() const {
109 return m_ref_count.load();
110 }
111
112 bool IsDerivedFrom(const TypeObj& rhs) const {
113 return this->GetTypeObj().IsDerivedFrom(rhs);
114 }
115
116 bool IsDerivedFrom(const KAutoObject& rhs) const {
117 return this->IsDerivedFrom(rhs.GetTypeObj());
118 }
119
120 template <typename Derived>
121 Derived DynamicCast() {
122 static_assert(std::is_pointer<Derived>::value);
123 using DerivedType = typename std::remove_pointer<Derived>::type;
124
125 if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) {
126 return static_cast<Derived>(this);
127 } else {
128 return nullptr;
129 }
130 }
131
132 template <typename Derived>
133 const Derived DynamicCast() const {
134 static_assert(std::is_pointer<Derived>::value);
135 using DerivedType = typename std::remove_pointer<Derived>::type;
136
137 if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) {
138 return static_cast<Derived>(this);
139 } else {
140 return nullptr;
141 }
142 }
143
144 bool Open() {
145 // Atomically increment the reference count, only if it's positive.
146 u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire);
147 do {
148 if (cur_ref_count == 0) {
149 return false;
150 }
151 ASSERT(cur_ref_count < cur_ref_count + 1);
152 } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1,
153 std::memory_order_relaxed));
154
155 return true;
156 }
157
158 void Close() {
159 // Atomically decrement the reference count, not allowing it to become negative.
160 u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire);
161 do {
162 ASSERT(cur_ref_count > 0);
163 } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1,
164 std::memory_order_relaxed));
165
166 // If ref count hits zero, destroy the object.
167 if (cur_ref_count - 1 == 0) {
168 this->Destroy();
169 }
170 }
171};
172
173class KAutoObjectWithListContainer;
174
175class KAutoObjectWithList : public KAutoObject {
176private:
177 friend class KAutoObjectWithListContainer;
178
179private:
180 Common::IntrusiveRedBlackTreeNode list_node;
181
182public:
183 static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) {
184 const u64 lid = lhs.GetId();
185 const u64 rid = rhs.GetId();
186
187 if (lid < rid) {
188 return -1;
189 } else if (lid > rid) {
190 return 1;
191 } else {
192 return 0;
193 }
194 }
195
196public:
197 virtual u64 GetId() const {
198 return reinterpret_cast<u64>(this);
199 }
200};
201
202template <typename T>
203class KScopedAutoObject {
204 NON_COPYABLE(KScopedAutoObject);
205
206private:
207 template <typename U>
208 friend class KScopedAutoObject;
209
210private:
211 T* m_obj;
212
213private:
214 constexpr void Swap(KScopedAutoObject& rhs) {
215 std::swap(m_obj, rhs.m_obj);
216 }
217
218public:
219 constexpr KScopedAutoObject() : m_obj(nullptr) { // ...
220 }
221 constexpr KScopedAutoObject(T* o) : m_obj(o) {
222 if (m_obj != nullptr) {
223 m_obj->Open();
224 }
225 }
226
227 ~KScopedAutoObject() {
228 if (m_obj != nullptr) {
229 m_obj->Close();
230 }
231 m_obj = nullptr;
232 }
233
234 template <typename U>
235 requires(std::derived_from<T, U> ||
236 std::derived_from<U, T>) constexpr KScopedAutoObject(KScopedAutoObject<U>&& rhs) {
237 if constexpr (std::derived_from<U, T>) {
238 // Upcast.
239 m_obj = rhs.m_obj;
240 rhs.m_obj = nullptr;
241 } else {
242 // Downcast.
243 T* derived = nullptr;
244 if (rhs.m_obj != nullptr) {
245 derived = rhs.m_obj->template DynamicCast<T*>();
246 if (derived == nullptr) {
247 rhs.m_obj->Close();
248 }
249 }
250
251 m_obj = derived;
252 rhs.m_obj = nullptr;
253 }
254 }
255
256 constexpr KScopedAutoObject<T>& operator=(KScopedAutoObject<T>&& rhs) {
257 rhs.Swap(*this);
258 return *this;
259 }
260
261 constexpr T* operator->() {
262 return m_obj;
263 }
264 constexpr T& operator*() {
265 return *m_obj;
266 }
267
268 constexpr void Reset(T* o) {
269 KScopedAutoObject(o).Swap(*this);
270 }
271
272 constexpr T* GetPointerUnsafe() {
273 return m_obj;
274 }
275
276 constexpr T* ReleasePointerUnsafe() {
277 T* ret = m_obj;
278 m_obj = nullptr;
279 return ret;
280 }
281
282 constexpr bool IsNull() const {
283 return m_obj == nullptr;
284 }
285 constexpr bool IsNotNull() const {
286 return m_obj != nullptr;
287 }
288};
289
290} // namespace Kernel