Browse Source

Core: Switch `RID_alloc::owns` to lock-free

Stuart Carnie 1 month ago
parent
commit
bdfe8549b8
1 changed files with 34 additions and 7 deletions
  1. 34 7
      core/templates/rid_owner.h

+ 34 - 7
core/templates/rid_owner.h

@@ -310,16 +310,24 @@ public:
 	}
 	}
 
 
 	_FORCE_INLINE_ bool owns(const RID &p_rid) const {
 	_FORCE_INLINE_ bool owns(const RID &p_rid) const {
+		if (p_rid == RID()) {
+			return false;
+		}
+
 		if constexpr (THREAD_SAFE) {
 		if constexpr (THREAD_SAFE) {
-			mutex.lock();
+			SYNC_ACQUIRE;
 		}
 		}
 
 
 		uint64_t id = p_rid.get_id();
 		uint64_t id = p_rid.get_id();
 		uint32_t idx = uint32_t(id & 0xFFFFFFFF);
 		uint32_t idx = uint32_t(id & 0xFFFFFFFF);
-		if (unlikely(idx >= max_alloc)) {
-			if constexpr (THREAD_SAFE) {
-				mutex.unlock();
-			}
+		uint32_t ma;
+		if constexpr (THREAD_SAFE) {
+			ma = ((std::atomic<uint32_t> *)&max_alloc)->load(std::memory_order_relaxed);
+		} else {
+			ma = max_alloc;
+		}
+
+		if (unlikely(idx >= ma)) {
 			return false;
 			return false;
 		}
 		}
 
 
@@ -328,10 +336,29 @@ public:
 
 
 		uint32_t validator = uint32_t(id >> 32);
 		uint32_t validator = uint32_t(id >> 32);
 
 
-		bool owned = (chunks[idx_chunk][idx_element].validator & 0x7FFFFFFF) == validator;
+		if constexpr (THREAD_SAFE) {
+#ifdef TSAN_ENABLED
+			__tsan_acquire(&chunks[idx_chunk]); // We know not a race in practice.
+			__tsan_acquire(&chunks[idx_chunk][idx_element]); // We know not a race in practice.
+#endif
+		}
+
+		Chunk &c = chunks[idx_chunk][idx_element];
 
 
 		if constexpr (THREAD_SAFE) {
 		if constexpr (THREAD_SAFE) {
-			mutex.unlock();
+#ifdef TSAN_ENABLED
+			__tsan_release(&chunks[idx_chunk]);
+			__tsan_release(&chunks[idx_chunk][idx_element]);
+			__tsan_acquire(&c.validator); // We know not a race in practice.
+#endif
+		}
+
+		bool owned = (c.validator & 0x7FFFFFFF) == validator;
+
+		if constexpr (THREAD_SAFE) {
+#ifdef TSAN_ENABLED
+			__tsan_release(&c.validator);
+#endif
 		}
 		}
 
 
 		return owned;
 		return owned;