From 8f4d0c8a6634cbedc17ce728238145393eba85a8 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 21 Jan 2025 11:37:29 +0100 Subject: [PATCH] gobj: Make BufferContextChain thread-safe --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 1 + panda/src/gobj/bufferContext.cxx | 5 ++++- panda/src/gobj/bufferContextChain.cxx | 7 +++++++ panda/src/gobj/bufferContextChain.h | 4 ++++ panda/src/gobj/bufferResidencyTracker.cxx | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index c8aa716366..5a06fc4afc 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -15086,6 +15086,7 @@ get_texture_memory_size(CLP(TextureContext) *gtc) { void CLP(GraphicsStateGuardian):: check_nonresident_texture(BufferContextChain &chain) { #if defined(SUPPORT_FIXED_FUNCTION) && !defined(OPENGLES) // Residency queries not supported by OpenGL ES. + LightMutexHolder holder(chain._lock); size_t num_textures = chain.get_count(); if (num_textures == 0) { return; diff --git a/panda/src/gobj/bufferContext.cxx b/panda/src/gobj/bufferContext.cxx index b268400d35..4ee4f1833d 100644 --- a/panda/src/gobj/bufferContext.cxx +++ b/panda/src/gobj/bufferContext.cxx @@ -12,6 +12,7 @@ */ #include "bufferContext.h" +#include "lightMutexHolder.h" TypeHandle BufferContext::_type_handle; @@ -43,7 +44,8 @@ BufferContext:: void BufferContext:: set_owning_chain(BufferContextChain *chain) { if (chain != _owning_chain) { - if (_owning_chain != nullptr){ + if (_owning_chain != nullptr) { + LightMutexHolder holder(_owning_chain->_lock); --(_owning_chain->_count); _owning_chain->adjust_bytes(-(int)_data_size_bytes); remove_from_list(); @@ -52,6 +54,7 @@ set_owning_chain(BufferContextChain *chain) { _owning_chain = chain; if (_owning_chain != nullptr) { + LightMutexHolder holder(_owning_chain->_lock); ++(_owning_chain->_count); _owning_chain->adjust_bytes((int)_data_size_bytes); insert_before(_owning_chain); diff --git a/panda/src/gobj/bufferContextChain.cxx b/panda/src/gobj/bufferContextChain.cxx index 4f27c90c88..780ab23350 100644 --- a/panda/src/gobj/bufferContextChain.cxx +++ b/panda/src/gobj/bufferContextChain.cxx @@ -14,11 +14,15 @@ #include "bufferContextChain.h" #include "bufferContext.h" #include "indent.h" +#include "lightMutexHolder.h" /** * Returns the first BufferContext object stored in the tracker. You can walk * through the entire list of objects stored on the tracker by calling * get_next() on each returned object, until the return value is NULL. + * + * This does not grab the lock; make sure you are holding the lock while + * iterating over the chain. */ BufferContext *BufferContextChain:: get_first() { @@ -32,9 +36,11 @@ get_first() { /** * Moves all of the BufferContexts from the other tracker onto this one. + * The other chain must be locked. */ void BufferContextChain:: take_from(BufferContextChain &other) { + LightMutexHolder holder(_lock); _total_size += other._total_size; _count += other._count; other._total_size = 0; @@ -55,6 +61,7 @@ take_from(BufferContextChain &other) { */ void BufferContextChain:: write(std::ostream &out, int indent_level) const { + LightMutexHolder holder(_lock); indent(out, indent_level) << _count << " objects, consuming " << _total_size << " bytes:\n"; diff --git a/panda/src/gobj/bufferContextChain.h b/panda/src/gobj/bufferContextChain.h index b995c2e583..153401b264 100644 --- a/panda/src/gobj/bufferContextChain.h +++ b/panda/src/gobj/bufferContextChain.h @@ -16,6 +16,7 @@ #include "pandabase.h" #include "linkedListNode.h" +#include "lightMutex.h" class BufferContext; @@ -47,6 +48,9 @@ private: size_t _total_size; int _count; +public: + LightMutex _lock; + friend class BufferContext; }; diff --git a/panda/src/gobj/bufferResidencyTracker.cxx b/panda/src/gobj/bufferResidencyTracker.cxx index 9ac4fef735..3d05fbee83 100644 --- a/panda/src/gobj/bufferResidencyTracker.cxx +++ b/panda/src/gobj/bufferResidencyTracker.cxx @@ -117,6 +117,7 @@ write(std::ostream &out, int indent_level) const { */ void BufferResidencyTracker:: move_inactive(BufferContextChain &inactive, BufferContextChain &active) { + LightMutexHolder active_holder(active._lock); BufferContext *node = active.get_first(); while (node != nullptr) { nassertv((node->_residency_state & S_active) != 0);