Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add threadid to AsyncStackRootHolder #644

Merged
merged 14 commits into from
Dec 4, 2024
1 change: 0 additions & 1 deletion external/mpark-wg21
Submodule mpark-wg21 deleted from c556c4
6 changes: 2 additions & 4 deletions include/unifex/tracing/async_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct AsyncStackRoot;
struct AsyncStackFrame;
namespace detail {
class ScopedAsyncStackRoot;
}
} // namespace detail

// Get access to the current thread's top-most AsyncStackRoot.
//
Expand Down Expand Up @@ -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_;
Expand Down
110 changes: 67 additions & 43 deletions source/async_stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
#include <mutex>

#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
Expand All @@ -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 <vector>
#endif //UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
#else
# include <vector>
# if defined(_WIN32)
# include <windows.h>
# elif defined(__linux__)
# include <unistd.h>
# endif // defined(_WIN32)
#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD

namespace unifex {

Expand All @@ -58,34 +63,47 @@ struct AsyncStackRootHolderList {
asyncStackRootHolders_.reserve(50);
}

void add(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
asyncStackRootHolders_.push_back(holder);
}
void add(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
asyncStackRootHolders_.push_back(holder);
}

void remove(void* holder) {
std::lock_guard<std::mutex> 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<std::mutex> 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<void*> getAsyncStackRoots() {
if (!mutex_.try_lock()) {
// assume we crashed holding the lock and give up
return {};
std::vector<void*> getAsyncStackRoots() {
if (!mutex_.try_lock()) {
// assume we crashed holding the lock and give up
return {};
}
std::lock_guard<std::mutex> lock(mutex_, std::adopt_lock);
return asyncStackRootHolders_;
}
std::lock_guard<std::mutex> 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 {

Expand All @@ -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);
Expand All @@ -139,6 +160,9 @@ struct AsyncStackRootHolder {
}

std::atomic<AsyncStackRoot*> value{nullptr};
#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
std::uint64_t threadId = 0;
#endif
};

static thread_local AsyncStackRootHolder currentThreadAsyncStackRoot;
Expand Down Expand Up @@ -220,6 +244,6 @@ UNIFEX_NO_INLINE void resumeCoroutineWithNewAsyncStackRoot(
h.resume();
}

#endif // FOLLY_HAS_COROUTINES
#endif // !UNIFEX_NO_COROUTINES

} // namespace unifex
Loading