diff options
| author | 2018-08-13 00:13:47 -0400 | |
|---|---|---|
| committer | 2018-08-13 00:16:40 -0400 | |
| commit | 3476f5b4d38d31d6f17a335311a2fa814be8bf25 (patch) | |
| tree | d0929304994c704ac6dd152a92d528c0e25d715b /src/core/hle/kernel | |
| parent | Merge pull request #1043 from Subv/timing (diff) | |
| download | yuzu-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.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.h | 15 |
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 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| 14 | unsigned int Object::next_object_id; | 14 | std::atomic<u32> Object::next_object_id{0}; |
| 15 | 15 | ||
| 16 | /// Initialize the kernel | 16 | /// Initialize the kernel |
| 17 | void Init() { | 17 | void 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 | ||
| 63 | public: | 64 | public: |
| 64 | static unsigned int next_object_id; | 65 | static std::atomic<u32> next_object_id; |
| 65 | 66 | ||
| 66 | private: | 67 | private: |
| 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 |
| 75 | inline void intrusive_ptr_add_ref(Object* object) { | 76 | inline 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 | ||
| 79 | inline void intrusive_ptr_release(Object* object) { | 80 | inline 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 | } |