From b63b411f266af9a5cd0d84f2d6429b30633b5dd3 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 19 Jun 2025 16:18:40 +0200 Subject: [PATCH] Nanotrace: Refactore event queue - replace std::mutex with a spinlock The event queue was previously stored in thread-local storage, which led to complications when the associated thread became invalid or was no longer active. In such cases, attempts to acquire a std::mutex lock failed silently, likely due to the mutex being tied to a thread context that no longer existed or was in an undefined state. To address this, we replaced the std::mutex with a spinlock (std::atomic_flag-based). Spinlocks are not dependent on thread ownership semantics and provide a lightweight alternative for short critical sections, especially in scenarios where thread-local state may be unreliable or transient. This change ensures more robust and predictable locking behavior in multi-threaded environments where thread-local resources may be deallocated or invalidated unexpectedly. Change-Id: Ife360c09a803c77dfd39b3f49ba89c57ad5bb856 Reviewed-by: Thomas Hartmann --- src/libs/nanotrace/nanotracehr.h | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h index 3fa1dbfc672..cbbeebac63b 100644 --- a/src/libs/nanotrace/nanotracehr.h +++ b/src/libs/nanotrace/nanotracehr.h @@ -396,9 +396,24 @@ inline bool operator&(IsFlow first, IsFlow second) struct TraceEventWithoutArguments; struct TraceEventWithArguments; +class SpinLock +{ +public: + void lock() + { + while (flag.test_and_set(std::memory_order_acquire)) { + } + } + + void unlock() { flag.clear(std::memory_order_release); } + +private: + std::atomic_flag flag; +}; + struct TaskWithArguments { - TaskWithArguments(std::unique_lock lock, + TaskWithArguments(std::unique_lock lock, Utils::span data, std::thread::id threadId) : lock{std::move(lock)} @@ -406,14 +421,14 @@ struct TaskWithArguments , threadId{threadId} {} - std::unique_lock lock; + std::unique_lock lock; Utils::span data; std::thread::id threadId; }; struct TaskWithoutArguments { - TaskWithoutArguments(std::unique_lock lock, + TaskWithoutArguments(std::unique_lock lock, Utils::span data, std::thread::id threadId) : lock{std::move(lock)} @@ -421,20 +436,20 @@ struct TaskWithoutArguments , threadId{threadId} {} - std::unique_lock lock; + std::unique_lock lock; Utils::span data; std::thread::id threadId; }; struct MetaData { - MetaData(std::unique_lock lock, std::string key, std::string value) + MetaData(std::unique_lock lock, std::string key, std::string value) : lock{std::move(lock)} , key{std::move(key)} , value{std::move(value)} {} - std::unique_lock lock; + std::unique_lock lock; std::string key; std::string value; }; @@ -646,7 +661,7 @@ public: TraceEventsSpan currentEvents; std::size_t eventsIndex = 0; IsEnabled isEnabled = IsEnabled::Yes; - std::mutex mutex; + SpinLock mutex; std::thread::id threadId; };