summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Lioncash2018-08-13 00:13:47 -0400
committerGravatar Lioncash2018-08-13 00:16:40 -0400
commit3476f5b4d38d31d6f17a335311a2fa814be8bf25 (patch)
treed0929304994c704ac6dd152a92d528c0e25d715b /src/core/hle/kernel
parentMerge pull request #1043 from Subv/timing (diff)
downloadyuzu-3476f5b4d38d31d6f17a335311a2fa814be8bf25.tar.gz
yuzu-3476f5b4d38d31d6f17a335311a2fa814be8bf25.tar.xz
yuzu-3476f5b4d38d31d6f17a335311a2fa814be8bf25.zip
kernel/object: Tighten object against data races
Despite being covered by a global mutex, we should still ensure that the class handles its reference counts properly. This avoids potential shenanigans when it comes to data races. Given this is the root object that drives quite a bit of the kernel object hierarchy, ensuring we always have the correct behavior (and no races) is a good thing.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/object.h15
2 files changed, 9 insertions, 8 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1b0cd0abf..8c19e86d3 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -11,7 +11,7 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14unsigned int Object::next_object_id; 14std::atomic<u32> Object::next_object_id{0};
15 15
16/// Initialize the kernel 16/// Initialize the kernel
17void Init() { 17void Init() {
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 83df68dfd..526ac9cc3 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <string> 8#include <string>
8#include <utility> 9#include <utility>
9 10
@@ -42,8 +43,8 @@ public:
42 virtual ~Object(); 43 virtual ~Object();
43 44
44 /// Returns a unique identifier for the object. For debugging purposes only. 45 /// Returns a unique identifier for the object. For debugging purposes only.
45 unsigned int GetObjectId() const { 46 u32 GetObjectId() const {
46 return object_id; 47 return object_id.load(std::memory_order_relaxed);
47 } 48 }
48 49
49 virtual std::string GetTypeName() const { 50 virtual std::string GetTypeName() const {
@@ -61,23 +62,23 @@ public:
61 bool IsWaitable() const; 62 bool IsWaitable() const;
62 63
63public: 64public:
64 static unsigned int next_object_id; 65 static std::atomic<u32> next_object_id;
65 66
66private: 67private:
67 friend void intrusive_ptr_add_ref(Object*); 68 friend void intrusive_ptr_add_ref(Object*);
68 friend void intrusive_ptr_release(Object*); 69 friend void intrusive_ptr_release(Object*);
69 70
70 unsigned int ref_count = 0; 71 std::atomic<u32> ref_count{0};
71 unsigned int object_id = next_object_id++; 72 std::atomic<u32> object_id{next_object_id++};
72}; 73};
73 74
74// Special functions used by boost::instrusive_ptr to do automatic ref-counting 75// Special functions used by boost::instrusive_ptr to do automatic ref-counting
75inline void intrusive_ptr_add_ref(Object* object) { 76inline void intrusive_ptr_add_ref(Object* object) {
76 ++object->ref_count; 77 object->ref_count.fetch_add(1, std::memory_order_relaxed);
77} 78}
78 79
79inline void intrusive_ptr_release(Object* object) { 80inline void intrusive_ptr_release(Object* object) {
80 if (--object->ref_count == 0) { 81 if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
81 delete object; 82 delete object;
82 } 83 }
83} 84}