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.
This commit is contained in:
Lioncash 2018-08-13 00:13:47 -04:00
parent fecffeb0dd
commit 3476f5b4d3
2 changed files with 9 additions and 8 deletions

View file

@ -11,7 +11,7 @@
namespace Kernel { namespace Kernel {
unsigned int Object::next_object_id; std::atomic<u32> Object::next_object_id{0};
/// Initialize the kernel /// Initialize the kernel
void Init() { void Init() {

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <atomic>
#include <string> #include <string>
#include <utility> #include <utility>
@ -42,8 +43,8 @@ public:
virtual ~Object(); virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only. /// Returns a unique identifier for the object. For debugging purposes only.
unsigned int GetObjectId() const { u32 GetObjectId() const {
return object_id; return object_id.load(std::memory_order_relaxed);
} }
virtual std::string GetTypeName() const { virtual std::string GetTypeName() const {
@ -61,23 +62,23 @@ public:
bool IsWaitable() const; bool IsWaitable() const;
public: public:
static unsigned int next_object_id; static std::atomic<u32> next_object_id;
private: private:
friend void intrusive_ptr_add_ref(Object*); friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*); friend void intrusive_ptr_release(Object*);
unsigned int ref_count = 0; std::atomic<u32> ref_count{0};
unsigned int object_id = next_object_id++; std::atomic<u32> object_id{next_object_id++};
}; };
// Special functions used by boost::instrusive_ptr to do automatic ref-counting // Special functions used by boost::instrusive_ptr to do automatic ref-counting
inline void intrusive_ptr_add_ref(Object* object) { inline void intrusive_ptr_add_ref(Object* object) {
++object->ref_count; object->ref_count.fetch_add(1, std::memory_order_relaxed);
} }
inline void intrusive_ptr_release(Object* object) { inline void intrusive_ptr_release(Object* object) {
if (--object->ref_count == 0) { if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete object; delete object;
} }
} }