diff --git a/include/unifex/tracing/async_stack.hpp b/include/unifex/tracing/async_stack.hpp index ec7f67d6..fc6fff35 100644 --- a/include/unifex/tracing/async_stack.hpp +++ b/include/unifex/tracing/async_stack.hpp @@ -150,7 +150,7 @@ struct AsyncStackRoot; struct AsyncStackFrame; namespace detail { class ScopedAsyncStackRoot; -} +} // namespace detail // Get access to the current thread's top-most AsyncStackRoot. // @@ -321,9 +321,7 @@ struct frame_ptr { return frame_ptr{p}; } - explicit operator void*() const noexcept { - return p_; - } + explicit operator void*() const noexcept { return p_; } private: void* p_; diff --git a/source/async_stack.cpp b/source/async_stack.cpp index 9cc0465b..f63d9e8b 100644 --- a/source/async_stack.cpp +++ b/source/async_stack.cpp @@ -21,12 +21,12 @@ #include #if !defined(UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD) -#if defined(__linux__) -# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 1 -#else +# if defined(__linux__) +# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 1 +# else // defaults to using vector to store AsyncStackRoots instead of a pthread key -# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 0 -#endif +# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 0 +# endif #endif #if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD @@ -41,9 +41,14 @@ extern "C" { // Initialise to some value that will be interpreted as an invalid key. inline pthread_key_t folly_async_stack_root_tls_key = 0xFFFF'FFFFu; } -#else -# include -#endif //UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD +#else +# include +# if defined(_WIN32) +# include +# elif defined(__linux__) +# include +# endif // defined(_WIN32) +#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD namespace unifex { @@ -58,34 +63,47 @@ struct AsyncStackRootHolderList { asyncStackRootHolders_.reserve(50); } -void add(void* holder) { - std::lock_guard lock(mutex_); - asyncStackRootHolders_.push_back(holder); -} + void add(void* holder) { + std::lock_guard lock(mutex_); + asyncStackRootHolders_.push_back(holder); + } -void remove(void* holder) { - std::lock_guard lock(mutex_); - auto it = std::find(asyncStackRootHolders_.begin(), asyncStackRootHolders_.end(), holder); - if (it != asyncStackRootHolders_.end()) { - std::swap(*it, asyncStackRootHolders_.back()); - asyncStackRootHolders_.pop_back(); + void remove(void* holder) { + std::lock_guard lock(mutex_); + auto it = std::find( + asyncStackRootHolders_.begin(), asyncStackRootHolders_.end(), holder); + if (it != asyncStackRootHolders_.end()) { + std::swap(*it, asyncStackRootHolders_.back()); + asyncStackRootHolders_.pop_back(); + } } -} -std::vector getAsyncStackRoots() { - if (!mutex_.try_lock()) { - // assume we crashed holding the lock and give up - return {}; + std::vector getAsyncStackRoots() { + if (!mutex_.try_lock()) { + // assume we crashed holding the lock and give up + return {}; + } + std::lock_guard lock(mutex_, std::adopt_lock); + return asyncStackRootHolders_; } - std::lock_guard lock(mutex_, std::adopt_lock); - return asyncStackRootHolders_; -} }; extern "C" { - auto* kUnifexAsyncStackRootHolderList = new AsyncStackRootHolderList(); +auto* kUnifexAsyncStackRootHolderList = new AsyncStackRootHolderList(); +} + +static std::uint64_t get_os_thread_id() { +# if defined(__APPLE__) + std::uint64_t tid; + pthread_threadid_np(nullptr, &tid); + return tid; +# elif defined(_WIN32) + return std::uint64_t(GetCurrentThreadId()); +# else + return std::uint64_t(gettid()); +# endif } -#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD == 0 +#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD == 0 namespace { @@ -108,23 +126,26 @@ static void ensureAsyncRootTlsKeyIsInitialised() noexcept { #endif struct AsyncStackRootHolder { - AsyncStackRootHolder() noexcept { - #if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD - ensureAsyncRootTlsKeyIsInitialised(); - [[maybe_unused]] const int result = - pthread_setspecific(folly_async_stack_root_tls_key, this); - UNIFEX_ASSERT(result == 0); - #else - kUnifexAsyncStackRootHolderList->add(this); - #endif +#if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD + ensureAsyncRootTlsKeyIsInitialised(); + [[maybe_unused]] const int result = + pthread_setspecific(folly_async_stack_root_tls_key, this); + UNIFEX_ASSERT(result == 0); +#else + kUnifexAsyncStackRootHolderList->add(this); + threadId = unifex::get_os_thread_id(); +#endif } - #if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD - ~AsyncStackRootHolder() noexcept { - kUnifexAsyncStackRootHolderList->remove(this); - } - #endif +#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD + ~AsyncStackRootHolder() noexcept { + kUnifexAsyncStackRootHolderList->remove(this); + } + + std::uint64_t get_thread_id() const noexcept { return threadId; } + +#endif AsyncStackRoot* get() const noexcept { return value.load(std::memory_order_relaxed); @@ -139,6 +160,9 @@ struct AsyncStackRootHolder { } std::atomic value{nullptr}; +#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD + std::uint64_t threadId = 0; +#endif }; static thread_local AsyncStackRootHolder currentThreadAsyncStackRoot; @@ -220,6 +244,6 @@ UNIFEX_NO_INLINE void resumeCoroutineWithNewAsyncStackRoot( h.resume(); } -#endif // FOLLY_HAS_COROUTINES +#endif // !UNIFEX_NO_COROUTINES } // namespace unifex