From 6a2d1112c3cf64b46f7c60d7878d5cc8101fc5cd Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 7 Jun 2024 10:07:44 +0200 Subject: Debug code to help track linda gc during keeper operation --- src/debug.h | 2 ++ src/linda.cpp | 2 ++ src/linda.h | 32 +++++++++++++++++++++++++++++--- src/lindafactory.cpp | 2 +- 4 files changed, 34 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/debug.h b/src/debug.h index a0a4b8d..99fe48a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -15,6 +15,7 @@ inline void LUA_ASSERT_IMPL(lua_State* L_, bool cond_, char const* file_, int co } #define LUA_ASSERT(L_, cond_) LUA_ASSERT_IMPL(L_, cond_, __FILE__, __LINE__, #cond_) +#define LUA_ASSERT_CODE(code_) code_ class StackChecker { @@ -102,6 +103,7 @@ class StackChecker #else // HAVE_LUA_ASSERT() #define LUA_ASSERT(L_, c) nullptr // nothing +#define LUA_ASSERT_CODE(code_) nullptr #define STACK_CHECK_START_REL(L_, offset_) #define STACK_CHECK_START_ABS(L_, offset_) diff --git a/src/linda.cpp b/src/linda.cpp index 8b6df8e..3449f89 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -181,6 +181,8 @@ int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_) lua_State* const _KL{ _K ? _K->L : nullptr }; if (_KL == nullptr) return 0; + + LUA_ASSERT_CODE(auto const _koip{ _linda->startKeeperOperation(L_) }); // if we didn't do anything wrong, the keeper stack should be clean LUA_ASSERT(L_, lua_gettop(_KL) == 0); diff --git a/src/linda.h b/src/linda.h index 8db380a..809ade5 100644 --- a/src/linda.h +++ b/src/linda.h @@ -23,15 +23,39 @@ using LindaGroup = Unique; class Linda : public DeepPrelude // Deep userdata MUST start with this header { + public: + class KeeperOperationInProgress + { + private: + Linda& linda; + [[maybe_unused]] lua_State* const L; // just here for inspection while debugging + + public: + KeeperOperationInProgress(Linda& linda_, lua_State* const L_) + : linda{ linda_ } + , L{ L_ } + { + [[maybe_unused]] int const _prev{ linda.keeperOperationCount.fetch_add(1, std::memory_order_seq_cst) }; + } + + public: + ~KeeperOperationInProgress() + { + [[maybe_unused]] int const _prev{ linda.keeperOperationCount.fetch_sub(1, std::memory_order_seq_cst) }; + } + }; + private: static constexpr size_t kEmbeddedNameLength = 24; using EmbeddedName = std::array; // depending on the name length, it is either embedded inside the Linda, or allocated separately - std::variant nameVariant; + std::variant nameVariant{}; + // counts the keeper operations in progress + std::atomic keeperOperationCount{}; public: - std::condition_variable readHappened; - std::condition_variable writeHappened; + std::condition_variable readHappened{}; + std::condition_variable writeHappened{}; Universe* const U{ nullptr }; // the universe this linda belongs to int const keeperIndex{ -1 }; // the keeper associated to this linda CancelRequest cancelRequest{ CancelRequest::None }; @@ -60,7 +84,9 @@ class Linda public: [[nodiscard]] Keeper* acquireKeeper() const; [[nodiscard]] std::string_view getName() const; + [[nodiscard]] bool inKeeperOperation() const { return keeperOperationCount.load(std::memory_order_seq_cst) != 0; } void releaseKeeper(Keeper* keeper_) const; [[nodiscard]] static int ProtectedCall(lua_State* L_, lua_CFunction f_); + [[nodiscard]] KeeperOperationInProgress startKeeperOperation(lua_State* const L_) { return KeeperOperationInProgress{ *this, L_ }; }; [[nodiscard]] Keeper* whichKeeper() const { return U->keepers.getKeeper(keeperIndex); } }; diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index 3f4b9b0..6a2b000 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp @@ -69,7 +69,7 @@ void LindaFactory::createMetatable(lua_State* L_) const void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const { Linda* const _linda{ static_cast(o_) }; - LUA_ASSERT(L_, _linda); + LUA_ASSERT(L_, _linda && !_linda->inKeeperOperation()); Keeper* const _myK{ _linda->whichKeeper() }; // if collected after the universe, keepers are already destroyed, and there is nothing to clear if (_myK) { -- cgit v1.2.3-55-g6feb